Fixed bug #17133: Pagetree - qtip can be used to execute custom javascript (XSS)...
[Packages/TYPO3.CMS.git] / t3lib / class.t3lib_parsehtml.php
index 4f6b8af..950a78b 100644 (file)
@@ -1,36 +1,36 @@
 <?php
 /***************************************************************
 <?php
 /***************************************************************
-*  Copyright notice
-*
-*  (c) 1999-2005 Kasper Skaarhoj (kasperYYYY@typo3.com)
-*  All rights reserved
-*
-*  This script is part of the TYPO3 project. The TYPO3 project is
-*  free software; you can redistribute it and/or modify
-*  it under the terms of the GNU General Public License as published by
-*  the Free Software Foundation; either version 2 of the License, or
-*  (at your option) any later version.
-*
-*  The GNU General Public License can be found at
-*  http://www.gnu.org/copyleft/gpl.html.
-*  A copy is found in the textfile GPL.txt and important notices to the license
-*  from the author is found in LICENSE.txt distributed with these scripts.
-*
-*
-*  This script is distributed in the hope that it will be useful,
-*  but WITHOUT ANY WARRANTY; without even the implied warranty of
-*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-*  GNU General Public License for more details.
-*
-*  This copyright notice MUST APPEAR in all copies of the script!
-***************************************************************/
+ *  Copyright notice
+ *
+ *  (c) 1999-2011 Kasper Skårhøj (kasperYYYY@typo3.com)
+ *  All rights reserved
+ *
+ *  This script is part of the TYPO3 project. The TYPO3 project is
+ *  free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  The GNU General Public License can be found at
+ *  http://www.gnu.org/copyleft/gpl.html.
+ *  A copy is found in the textfile GPL.txt and important notices to the license
+ *  from the author is found in LICENSE.txt distributed with these scripts.
+ *
+ *
+ *  This script is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  This copyright notice MUST APPEAR in all copies of the script!
+ ***************************************************************/
 /**
  * Contains class with functions for parsing HTML code.
  *
  * $Id$
 /**
  * Contains class with functions for parsing HTML code.
  *
  * $Id$
- * Revised for TYPO3 3.6 July/2003 by Kasper Skaarhoj
+ * Revised for TYPO3 3.6 July/2003 by Kasper Skårhøj
  *
  *
- * @author     Kasper Skaarhoj <kasperYYYY@typo3.com>
+ * @author     Kasper Skårhøj <kasperYYYY@typo3.com>
  */
 /**
  * [CLASS/FUNCTION INDEX of SCRIPT]
  */
 /**
  * [CLASS/FUNCTION INDEX of SCRIPT]
  *
  *
  *  106: class t3lib_parsehtml
  *
  *
  *  106: class t3lib_parsehtml
- *  123:     function getSubpart($content, $marker)
- *  151:     function substituteSubpart($content,$marker,$subpartContent,$recursive=1,$keepMarker=0)
+ *  123:        function getSubpart($content, $marker)
+ *  156:        function substituteSubpart($content,$marker,$subpartContent,$recursive=1,$keepMarker=0)
  *
  *
- *              SECTION: Parsing HTML code
- *  223:     function splitIntoBlock($tag,$content,$eliminateExtraEndTags=0)
- *  284:     function splitIntoBlockRecursiveProc($tag,$content,&$procObj,$callBackContent,$callBackTags,$level=0)
- *  320:     function splitTags($tag,$content)
- *  354:     function getAllParts($parts,$tag_parts=1,$include_tag=1)
- *  373:     function removeFirstAndLastTag($str)
- *  392:     function getFirstTag($str)
- *  407:     function getFirstTagName($str,$preserveCase=FALSE)
- *  422:     function get_tag_attributes($tag,$deHSC=0)
- *  464:     function split_tag_attributes($tag)
- *  507:     function checkTagTypeCounts($content,$blockTags='a,b,blockquote,body,div,em,font,form,h1,h2,h3,h4,h5,h6,i,li,map,ol,option,p,pre,select,span,strong,table,td,textarea,tr,u,ul', $soloTags='br,hr,img,input,area')
+ *                       SECTION: Parsing HTML code
+ *  247:        function splitIntoBlock($tag,$content,$eliminateExtraEndTags=0)
+ *  308:        function splitIntoBlockRecursiveProc($tag,$content,&$procObj,$callBackContent,$callBackTags,$level=0)
+ *  344:        function splitTags($tag,$content)
+ *  378:        function getAllParts($parts,$tag_parts=1,$include_tag=1)
+ *  396:        function removeFirstAndLastTag($str)
+ *  412:        function getFirstTag($str)
+ *  426:        function getFirstTagName($str,$preserveCase=FALSE)
+ *  445:        function get_tag_attributes($tag,$deHSC=0)
+ *  486:        function split_tag_attributes($tag)
+ *  524:        function checkTagTypeCounts($content,$blockTags='a,b,blockquote,body,div,em,font,form,h1,h2,h3,h4,h5,h6,i,li,map,ol,option,p,pre,select,span,strong,table,td,textarea,tr,u,ul', $soloTags='br,hr,img,input,area')
  *
  *
- *              SECTION: Clean HTML code
- *  600:     function HTMLcleaner($content, $tags=array(),$keepAll=0,$hSC=0,$addConfig=array())
- *  796:     function bidir_htmlspecialchars($value,$dir)
- *  819:     function prefixResourcePath($main_prefix,$content,$alternatives=array(),$suffix='')
- *  902:     function prefixRelPath($prefix,$srcVal,$suffix='')
- *  920:     function cleanFontTags($value,$keepFace=0,$keepSize=0,$keepColor=0)
- *  951:     function mapTags($value,$tags=array(),$ltChar='<',$ltChar2='<')
- *  968:     function unprotectTags($content,$tagList='')
- * 1001:     function stripTagsExcept($value,$tagList)
- * 1024:     function caseShift($str,$flag,$cacheKey='')
- * 1048:     function compileTagAttribs($tagAttrib,$meta=array(), $xhtmlClean=0)
- * 1077:     function get_tag_attributes_classic($tag,$deHSC=0)
- * 1090:     function indentLines($content, $number=1, $indentChar="\t")
- * 1107:     function HTMLparserConfig($TSconfig,$keepTags=array())
- * 1231:     function XHTML_clean($content)
- * 1253:     function processTag($value,$conf,$endTag,$protected=0)
- * 1299:     function processContent($value,$dir,$conf)
+ *                       SECTION: Clean HTML code
+ *  617:        function HTMLcleaner($content, $tags=array(),$keepAll=0,$hSC=0,$addConfig=array())
+ *  814:        function bidir_htmlspecialchars($value,$dir)
+ *  837:        function prefixResourcePath($main_prefix,$content,$alternatives=array(),$suffix='')
+ *  919:        function prefixRelPath($prefix,$srcVal,$suffix='')
+ *  937:        function cleanFontTags($value,$keepFace=0,$keepSize=0,$keepColor=0)
+ *  967:        function mapTags($value,$tags=array(),$ltChar='<',$ltChar2='<')
+ *  982:        function unprotectTags($content,$tagList='')
+ * 1015:        function stripTagsExcept($value,$tagList)
+ * 1038:        function caseShift($str,$flag,$cacheKey='')
+ * 1065:        function compileTagAttribs($tagAttrib,$meta=array(), $xhtmlClean=0)
+ * 1093:        function get_tag_attributes_classic($tag,$deHSC=0)
+ * 1106:        function indentLines($content, $number=1, $indentChar=TAB)
+ * 1123:        function HTMLparserConfig($TSconfig,$keepTags=array())
+ * 1247:        function XHTML_clean($content)
+ * 1269:        function processTag($value,$conf,$endTag,$protected=0)
+ * 1315:        function processContent($value,$dir,$conf)
  *
  * TOTAL FUNCTIONS: 28
  * (This index is automatically created/updated by the extension "extdeveval")
  *
  * TOTAL FUNCTIONS: 28
  * (This index is automatically created/updated by the extension "extdeveval")
  */
 
 
  */
 
 
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
 /**
  * Functions for parsing HTML.
  * You are encouraged to use this class in your own applications
  *
 /**
  * Functions for parsing HTML.
  * You are encouraged to use this class in your own applications
  *
- * @author     Kasper Skaarhoj <kasperYYYY@typo3.com>
+ * @author     Kasper Skårhøj <kasperYYYY@typo3.com>
  * @package TYPO3
  * @subpackage t3lib
  */
 class t3lib_parsehtml {
  * @package TYPO3
  * @subpackage t3lib
  */
 class t3lib_parsehtml {
-       var $caseShift_cache=array();
 
 
-
-       // *******************************************'
-       // COPY FROM class.tslib_content.php: / BEGIN
-       // substituteSubpart
-       // Cleaned locally 2/2003 !!!! (so different from tslib_content version)
-       // *******************************************'
+       protected $caseShift_cache = array();
+               // Void elements that do not have closing tags, as defined by HTML5, except link element
+       const VOID_ELEMENTS = 'area|base|br|col|command|embed|hr|img|input|keygen|meta|param|source|track|wbr';
 
        /**
 
        /**
-        * Returns the first subpart encapsulated in the marker, $marker (possibly present in $content as a HTML comment)
+        * Returns the first subpart encapsulated in the marker, $marker
+        * (possibly present in $content as a HTML comment)
         *
         * @param       string          Content with subpart wrapped in fx. "###CONTENT_PART###" inside.
         * @param       string          Marker string, eg. "###CONTENT_PART###"
         * @return      string
         */
         *
         * @param       string          Content with subpart wrapped in fx. "###CONTENT_PART###" inside.
         * @param       string          Marker string, eg. "###CONTENT_PART###"
         * @return      string
         */
-       function getSubpart($content, $marker)  {
-               if ($marker && strstr($content,$marker))        {
-                       $start = strpos($content, $marker)+strlen($marker);
-                       $stop = @strpos($content, $marker, $start+1);
-                       $sub = substr($content, $start, $stop-$start);
+       public static function getSubpart($content, $marker) {
+               $start = strpos($content, $marker);
 
 
-                       $reg=Array();
-                       ereg('^[^<]*-->',$sub,$reg);
-                       $start+=strlen($reg[0]);
+               if ($start === FALSE) {
+                       return '';
+               }
 
 
-                       $reg=Array();
-                       ereg('<!--[^>]*$',$sub,$reg);
-                       $stop-=strlen($reg[0]);
+               $start += strlen($marker);
+               $stop = strpos($content, $marker, $start);
+
+                       // Q: What shall get returned if no stop marker is given
+                       // /*everything till the end*/ or nothing?
+               if ($stop === FALSE) {
+                       return ''; /*substr($content, $start)*/
+               }
+
+               $content = substr($content, $start, $stop - $start);
+
+               $matches = array();
+               if (preg_match('/^([^\<]*\-\-\>)(.*)(\<\!\-\-[^\>]*)$/s', $content, $matches) === 1) {
+                       return $matches[2];
+               }
 
 
-                       return substr($content, $start, $stop-$start);
+               $matches = array(); // resetting $matches
+               if (preg_match('/(.*)(\<\!\-\-[^\>]*)$/s', $content, $matches) === 1) {
+                       return $matches[1];
                }
                }
+
+               $matches = array(); // resetting $matches
+               if (preg_match('/^([^\<]*\-\-\>)(.*)$/s', $content, $matches) === 1) {
+                       return $matches[2];
+               }
+
+               return $content;
        }
 
        /**
        }
 
        /**
@@ -148,59 +145,171 @@ class t3lib_parsehtml {
         * @param       boolean         If set, the marker around the subpart is not removed, but kept in the output
         * @return      string          Processed input content
         */
         * @param       boolean         If set, the marker around the subpart is not removed, but kept in the output
         * @return      string          Processed input content
         */
-       function substituteSubpart($content,$marker,$subpartContent,$recursive=1,$keepMarker=0) {
+       public static function substituteSubpart($content, $marker, $subpartContent, $recursive = 1, $keepMarker = 0) {
                $start = strpos($content, $marker);
                $start = strpos($content, $marker);
-               $stop = @strpos($content, $marker, $start+1)+strlen($marker);
-               if ($start && $stop>$start)     {
-                       // code before
-                       $before = substr($content, 0, $start);
-                       $reg=Array();
-                       ereg('<!--[^>]*$',$before,$reg);
-                       $start-=strlen($reg[0]);
-                       if ($keepMarker)        {
-                               $reg_k=Array();
-                               if ($reg[0])    ereg('^[^>]*-->',substr($content,$start),$reg_k);
-                               $before_marker = substr($content, $start, strlen($reg_k[0]?$reg_k[0]:$marker));
-                       }
-                       $before = substr($content, 0, $start);
-                               // code after
-                       $after = substr($content, $stop);
-                       $reg=Array();
-                       ereg('^[^<]*-->',$after,$reg);
-                       $stop+=strlen($reg[0]);
-                       if ($keepMarker)        {
-                               $reg_k=Array();
-                               if ($reg[0])    ereg('<!--[^<]*$',substr($content,0,$stop),$reg_k);
-                               $sLen = strlen($reg_k[0]?$reg_k[0]:$marker);
-                               $after_marker = substr($content, $stop-$sLen,$sLen);
-                       }
-                       $after = substr($content, $stop);
 
 
+               if ($start === FALSE) {
+                       return $content;
+               }
+
+               $startAM = $start + strlen($marker);
+               $stop = strpos($content, $marker, $startAM);
+
+               if ($stop === FALSE) {
+                       return $content;
+               }
+
+               $stopAM = $stop + strlen($marker);
+               $before = substr($content, 0, $start);
+               $after = substr($content, $stopAM);
+               $between = substr($content, $startAM, $stop - $startAM);
+
+               if ($recursive) {
+                       $after = self::substituteSubpart(
+                               $after,
+                               $marker,
+                               $subpartContent,
+                               $recursive,
+                               $keepMarker
+                       );
+               }
 
 
-                               // replace?
-                       if (is_array($subpartContent))  {
-                               $substContent=$subpartContent[0].$this->getSubpart($content,$marker).$subpartContent[1];
+               if ($keepMarker) {
+                       $matches = array();
+                       if (preg_match('/^([^\<]*\-\-\>)(.*)(\<\!\-\-[^\>]*)$/s', $between, $matches) === 1) {
+                               $before .= $marker . $matches[1];
+                               $between = $matches[2];
+                               $after = $matches[3] . $marker . $after;
+                       } elseif (preg_match('/^(.*)(\<\!\-\-[^\>]*)$/s', $between, $matches) === 1) {
+                               $before .= $marker;
+                               $between = $matches[1];
+                               $after = $matches[2] . $marker . $after;
+                       } elseif (preg_match('/^([^\<]*\-\-\>)(.*)$/s', $between, $matches) === 1) {
+                               $before .= $marker . $matches[1];
+                               $between = $matches[2];
+                               $after = $marker . $after;
                        } else {
                        } else {
-                               $substContent=$subpartContent;
+                               $before .= $marker;
+                               $after = $marker . $after;
                        }
 
                        }
 
-                       if ($recursive && strpos($after, $marker))      {
-                               return $before.($keepMarker?$before_marker:'').$substContent.($keepMarker?$after_marker:'').$this->substituteSubpart($after,$marker,$subpartContent);
-                       } else {
-                               return $before.($keepMarker?$before_marker:'').$substContent.($keepMarker?$after_marker:'').$after;
+               } else {
+                       $matches = array();
+                       if (preg_match('/^(.*)\<\!\-\-[^\>]*$/s', $before, $matches) === 1) {
+                               $before = $matches[1];
+                       }
+
+                       if (is_array($subpartContent)) {
+                               $matches = array();
+                               if (preg_match('/^([^\<]*\-\-\>)(.*)(\<\!\-\-[^\>]*)$/s', $between, $matches) === 1) {
+                                       $between = $matches[2];
+                               } elseif (preg_match('/^(.*)(\<\!\-\-[^\>]*)$/s', $between, $matches) === 1) {
+                                       $between = $matches[1];
+                               } elseif (preg_match('/^([^\<]*\-\-\>)(.*)$/s', $between, $matches) === 1) {
+                                       $between = $matches[2];
+                               }
+                       }
+
+                       $matches = array(); // resetting $matches
+                       if (preg_match('/^[^\<]*\-\-\>(.*)$/s', $after, $matches) === 1) {
+                               $after = $matches[1];
                        }
                        }
+               }
+
+               if (is_array($subpartContent)) {
+                       $between = $subpartContent[0] . $between . $subpartContent[1];
                } else {
                } else {
-                       return $content;
+                       $between = $subpartContent;
+               }
+
+               return $before . $between . $after;
+       }
+
+       /**
+        * Substitues multiple subparts at once
+        *
+        * @param       string          The content stream, typically HTML template content.
+        * @param       array           The array of key/value pairs being subpart/content values used in the substitution. For each element in this array the function will substitute a subpart in the content stream with the content.
+        * @return      string          The processed HTML content string.
+        */
+       public static function substituteSubpartArray($content, array $subpartsContent) {
+               foreach ($subpartsContent as $subpartMarker => $subpartContent) {
+                       $content = self::substituteSubpart(
+                               $content,
+                               $subpartMarker,
+                               $subpartContent
+                       );
                }
                }
+
+               return $content;
        }
        }
-       // *******************************************'
-       // COPY FROM class.tslib_content.php: / END
-       // *******************************************'
 
 
 
 
+       /**
+        * Substitutes a marker string in the input content
+        * (by a simple str_replace())
+        *
+        * @param       string          The content stream, typically HTML template content.
+        * @param       string          The marker string, typically on the form "###[the marker string]###"
+        * @param       mixed           The content to insert instead of the marker string found.
+        * @return      string          The processed HTML content string.
+        * @see substituteSubpart()
+        */
+       public static function substituteMarker($content, $marker, $markContent) {
+               return str_replace($marker, $markContent, $content);
+       }
 
 
 
 
+       /**
+        * Traverses the input $markContentArray array and for each key the marker
+        * by the same name (possibly wrapped and in upper case) will be
+        * substituted with the keys value in the array. This is very useful if you
+        * have a data-record to substitute in some content. In particular when you
+        * use the $wrap and $uppercase values to pre-process the markers. Eg. a
+        * key name like "myfield" could effectively be represented by the marker
+        * "###MYFIELD###" if the wrap value was "###|###" and the $uppercase
+        * boolean true.
+        *
+        * @param       string          The content stream, typically HTML template content.
+        * @param       array           The array of key/value pairs being marker/content values used in the substitution. For each element in this array the function will substitute a marker in the content stream with the content.
+        * @param       string          A wrap value - [part 1] | [part 2] - for the markers before substitution
+        * @param       boolean         If set, all marker string substitution is done with upper-case markers.
+        * @param       boolean         If set, all unused marker are deleted.
+        * @return      string          The processed output stream
+        * @see substituteMarker(), substituteMarkerInObject(), TEMPLATE()
+        */
+       public static function substituteMarkerArray($content, $markContentArray, $wrap = '', $uppercase = 0, $deleteUnused = 0) {
+               if (is_array($markContentArray)) {
+                       $wrapArr = t3lib_div::trimExplode('|', $wrap);
+
+                       foreach ($markContentArray as $marker => $markContent) {
+                               if ($uppercase) {
+                                               // use strtr instead of strtoupper to avoid locale problems with Turkish
+                                       $marker = strtr(
+                                               $marker,
+                                               'abcdefghijklmnopqrstuvwxyz',
+                                               'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
+                                       );
+                               }
 
 
+                               if (count($wrapArr) > 0) {
+                                       $marker = $wrapArr[0] . $marker . $wrapArr[1];
+                               }
+
+                               $content = str_replace($marker, $markContent, $content);
+                       }
+
+                       if ($deleteUnused) {
+                               if (empty($wrap)) {
+                                       $wrapArr = array('###', '###');
+                               }
+
+                               $content = preg_replace('/' . preg_quote($wrapArr[0]) . '([A-Z0-9_|\-]*)' . preg_quote($wrapArr[1]) . '/is', '', $content);
+                       }
+               }
+
+               return $content;
+       }
 
 
        /************************************
 
 
        /************************************
@@ -220,52 +329,52 @@ class t3lib_parsehtml {
         * @return      array           Even numbers in the array are outside the blocks, Odd numbers are block-content.
         * @see splitTags(), getAllParts(), removeFirstAndLastTag()
         */
         * @return      array           Even numbers in the array are outside the blocks, Odd numbers are block-content.
         * @see splitTags(), getAllParts(), removeFirstAndLastTag()
         */
-       function splitIntoBlock($tag,$content,$eliminateExtraEndTags=0) {
-               $tags=array_unique(t3lib_div::trimExplode(',',$tag,1));
-               $regexStr = '</?('.implode('|',$tags).')(>|[[:space:]][^>]*>)';
+       function splitIntoBlock($tag, $content, $eliminateExtraEndTags = 0) {
+               $tags = array_unique(t3lib_div::trimExplode(',', $tag, 1));
+               $regexStr = '/\<\/?(' . implode('|', $tags) . ')(\s*\>|\s[^\>]*\>)/si';
 
 
-               $parts = spliti($regexStr,$content);
+               $parts = preg_split($regexStr, $content);
 
 
-               $newParts=array();
-               $pointer=strlen($parts[0]);
-               $buffer=$parts[0];
-               $nested=0;
+               $newParts = array();
+               $pointer = strlen($parts[0]);
+               $buffer = $parts[0];
+               $nested = 0;
                reset($parts);
                next($parts);
                reset($parts);
                next($parts);
-               while(list($k,$v)=each($parts)) {
-                       $isEndTag= substr($content,$pointer,2)=='</' ? 1 : 0;
-                       $tagLen = strcspn(substr($content,$pointer),'>')+1;
-
-                       if (!$isEndTag) {       // We meet a start-tag:
-                               if (!$nested)   {       // Ground level:
-                                       $newParts[]=$buffer;    // previous buffer stored
-                                       $buffer='';
+               while (list($k, $v) = each($parts)) {
+                       $isEndTag = substr($content, $pointer, 2) == '</' ? 1 : 0;
+                       $tagLen = strcspn(substr($content, $pointer), '>') + 1;
+
+                       if (!$isEndTag) { // We meet a start-tag:
+                               if (!$nested) { // Ground level:
+                                       $newParts[] = $buffer; // previous buffer stored
+                                       $buffer = '';
                                }
                                }
-                               $nested++;      // We are inside now!
-                               $mbuffer=substr($content,$pointer,strlen($v)+$tagLen);  // New buffer set and pointer increased
-                               $pointer+=strlen($mbuffer);
-                               $buffer.=$mbuffer;
-                       } else {        // If we meet an endtag:
-                               $nested--;      // decrease nested-level
-                               $eliminated=0;
-                               if ($eliminateExtraEndTags && $nested<0)        {
-                                       $nested=0;
-                                       $eliminated=1;
+                               $nested++; // We are inside now!
+                               $mbuffer = substr($content, $pointer, strlen($v) + $tagLen); // New buffer set and pointer increased
+                               $pointer += strlen($mbuffer);
+                               $buffer .= $mbuffer;
+                       } else { // If we meet an endtag:
+                               $nested--; // decrease nested-level
+                               $eliminated = 0;
+                               if ($eliminateExtraEndTags && $nested < 0) {
+                                       $nested = 0;
+                                       $eliminated = 1;
                                } else {
                                } else {
-                                       $buffer.=substr($content,$pointer,$tagLen);     // In any case, add the endtag to current buffer and increase pointer
+                                       $buffer .= substr($content, $pointer, $tagLen); // In any case, add the endtag to current buffer and increase pointer
                                }
                                }
-                               $pointer+=$tagLen;
-                               if (!$nested && !$eliminated)   {       // if we're back on ground level, (and not by eliminating tags...
-                                       $newParts[]=$buffer;
-                                       $buffer='';
+                               $pointer += $tagLen;
+                               if (!$nested && !$eliminated) { // if we're back on ground level, (and not by eliminating tags...
+                                       $newParts[] = $buffer;
+                                       $buffer = '';
                                }
                                }
-                               $mbuffer=substr($content,$pointer,strlen($v));  // New buffer set and pointer increased
-                               $pointer+=strlen($mbuffer);
-                               $buffer.=$mbuffer;
+                               $mbuffer = substr($content, $pointer, strlen($v)); // New buffer set and pointer increased
+                               $pointer += strlen($mbuffer);
+                               $buffer .= $mbuffer;
                        }
 
                }
                        }
 
                }
-               $newParts[]=$buffer;
+               $newParts[] = $buffer;
                return $newParts;
        }
 
                return $newParts;
        }
 
@@ -281,30 +390,34 @@ class t3lib_parsehtml {
         * @return      string          Processed content
         * @see splitIntoBlock()
         */
         * @return      string          Processed content
         * @see splitIntoBlock()
         */
-       function splitIntoBlockRecursiveProc($tag,$content,&$procObj,$callBackContent,$callBackTags,$level=0)   {
-               $parts = $this->splitIntoBlock($tag,$content,TRUE);
-               foreach($parts as $k => $v)     {
-                       if ($k%2)       {
+       function splitIntoBlockRecursiveProc($tag, $content, &$procObj, $callBackContent, $callBackTags, $level = 0) {
+               $parts = $this->splitIntoBlock($tag, $content, TRUE);
+               foreach ($parts as $k => $v) {
+                       if ($k % 2) {
                                $firstTagName = $this->getFirstTagName($v, TRUE);
                                $tagsArray = array();
                                $tagsArray['tag_start'] = $this->getFirstTag($v);
                                $firstTagName = $this->getFirstTagName($v, TRUE);
                                $tagsArray = array();
                                $tagsArray['tag_start'] = $this->getFirstTag($v);
-                               $tagsArray['tag_end'] = '</'.$firstTagName.'>';
+                               $tagsArray['tag_end'] = '</' . $firstTagName . '>';
                                $tagsArray['tag_name'] = strtolower($firstTagName);
                                $tagsArray['add_level'] = 1;
                                $tagsArray['tag_name'] = strtolower($firstTagName);
                                $tagsArray['add_level'] = 1;
-                               $tagsArray['content'] = $this->splitIntoBlockRecursiveProc($tag,$this->removeFirstAndLastTag($v),$procObj,$callBackContent,$callBackTags,$level+$tagsArray['add_level']);
+                               $tagsArray['content'] = $this->splitIntoBlockRecursiveProc($tag, $this->removeFirstAndLastTag($v), $procObj, $callBackContent, $callBackTags, $level + $tagsArray['add_level']);
 
 
-                               if ($callBackTags)      $tagsArray = $procObj->$callBackTags($tagsArray,$level);
+                               if ($callBackTags) {
+                                       $tagsArray = $procObj->$callBackTags($tagsArray, $level);
+                               }
 
                                $parts[$k] =
 
                                $parts[$k] =
-                                       $tagsArray['tag_start'].
-                                       $tagsArray['content'].
-                                       $tagsArray['tag_end'];
+                                               $tagsArray['tag_start'] .
+                                               $tagsArray['content'] .
+                                               $tagsArray['tag_end'];
                        } else {
                        } else {
-                               if ($callBackContent)   $parts[$k] = $procObj->$callBackContent($parts[$k],$level);
+                               if ($callBackContent) {
+                                       $parts[$k] = $procObj->$callBackContent($parts[$k], $level);
+                               }
                        }
                }
 
                        }
                }
 
-               return implode('',$parts);
+               return implode('', $parts);
        }
 
        /**
        }
 
        /**
@@ -317,27 +430,27 @@ class t3lib_parsehtml {
         * @return      array           Even numbers in the array are outside the blocks, Odd numbers are block-content.
         * @see splitIntoBlock(), getAllParts(), removeFirstAndLastTag()
         */
         * @return      array           Even numbers in the array are outside the blocks, Odd numbers are block-content.
         * @see splitIntoBlock(), getAllParts(), removeFirstAndLastTag()
         */
-       function splitTags($tag,$content)       {
-               $tags = t3lib_div::trimExplode(',',$tag,1);
-               $regexStr = '<('.implode('|',$tags).')(>|\/>|[[:space:]][^>]*>)';
-               $parts = spliti($regexStr,$content);
+       function splitTags($tag, $content) {
+               $tags = t3lib_div::trimExplode(',', $tag, 1);
+               $regexStr = '/\<(' . implode('|', $tags) . ')(\s[^>]*)?\/?>/si';
+               $parts = preg_split($regexStr, $content);
 
                $pointer = strlen($parts[0]);
                $newParts = array();
                $newParts[] = $parts[0];
                reset($parts);
                next($parts);
 
                $pointer = strlen($parts[0]);
                $newParts = array();
                $newParts[] = $parts[0];
                reset($parts);
                next($parts);
-               while(list($k,$v)=each($parts)) {
-                       $tagLen = strcspn(substr($content,$pointer),'>')+1;
+               while (list($k, $v) = each($parts)) {
+                       $tagLen = strcspn(substr($content, $pointer), '>') + 1;
 
                                // Set tag:
 
                                // Set tag:
-                       $tag = substr($content,$pointer,$tagLen);       // New buffer set and pointer increased
+                       $tag = substr($content, $pointer, $tagLen); // New buffer set and pointer increased
                        $newParts[] = $tag;
                        $newParts[] = $tag;
-                       $pointer+= strlen($tag);
+                       $pointer += strlen($tag);
 
                                // Set content:
                        $newParts[] = $v;
 
                                // Set content:
                        $newParts[] = $v;
-                       $pointer+= strlen($v);
+                       $pointer += strlen($v);
                }
                return $newParts;
        }
                }
                return $newParts;
        }
@@ -351,13 +464,14 @@ class t3lib_parsehtml {
         * @return      array           Tag-parts/Non-tag-parts depending on input argument settings
         * @see splitIntoBlock(), splitTags()
         */
         * @return      array           Tag-parts/Non-tag-parts depending on input argument settings
         * @see splitIntoBlock(), splitTags()
         */
-       function getAllParts($parts,$tag_parts=1,$include_tag=1)        {
-               reset($parts);
-               $newParts=array();
-               while(list($k,$v)=each($parts)) {
-                       if (($k+($tag_parts?0:1))%2)    {
-                               if (!$include_tag)      $v=$this->removeFirstAndLastTag($v);
-                               $newParts[]=$v;
+       function getAllParts($parts, $tag_parts = 1, $include_tag = 1) {
+               $newParts = array();
+               foreach ($parts as $k => $v) {
+                       if (($k + ($tag_parts ? 0 : 1)) % 2) {
+                               if (!$include_tag) {
+                                       $v = $this->removeFirstAndLastTag($v);
+                               }
+                               $newParts[] = $v;
                        }
                }
                return $newParts;
                        }
                }
                return $newParts;
@@ -365,21 +479,18 @@ class t3lib_parsehtml {
 
        /**
         * Removes the first and last tag in the string
 
        /**
         * Removes the first and last tag in the string
-        * Anything before and after the first and last tags respectively is also removed
+        * Anything before the first and after the last tags respectively is also removed
         *
         * @param       string          String to process
         * @return      string
         */
         *
         * @param       string          String to process
         * @return      string
         */
-       function removeFirstAndLastTag($str)    {
-                       // First:
-               $endLen = strcspn($str,'>')+1;
-               $str = substr($str,$endLen);
-                       // Last:
-               $str = strrev($str);
-               $endLen = strcspn($str,'<')+1;
-               $str = substr($str,$endLen);
+       function removeFirstAndLastTag($str) {
+                       // End of first tag:
+               $start = strpos($str, '>');
+                       // Begin of last tag:
+               $end = strrpos($str, '<');
                        // return
                        // return
-               return strrev($str);
+               return substr($str, $start + 1, $end - $start - 1);
        }
 
        /**
        }
 
        /**
@@ -389,11 +500,10 @@ class t3lib_parsehtml {
         * @param       string          HTML string with tags
         * @return      string
         */
         * @param       string          HTML string with tags
         * @return      string
         */
-       function getFirstTag($str)      {
+       function getFirstTag($str) {
                        // First:
                        // First:
-               $endLen = strcspn($str,'>')+1;
-               $str = substr($str,0,$endLen);
-               return $str;
+               $endLen = strpos($str, '>') + 1;
+               return substr($str, 0, $endLen);
        }
 
        /**
        }
 
        /**
@@ -404,11 +514,15 @@ class t3lib_parsehtml {
         * @return      string          Tag name in upper case
         * @see getFirstTag()
         */
         * @return      string          Tag name in upper case
         * @see getFirstTag()
         */
-       function getFirstTagName($str,$preserveCase=FALSE)      {
-               list($tag) = split('[[:space:]]',substr(trim($this->getFirstTag($str)),1,-1), 2);
-               if (!$preserveCase)     $tag = strtoupper($tag);
-
-               return trim($tag);
+       function getFirstTagName($str, $preserveCase = FALSE) {
+               $matches = array();
+               if (preg_match('/^\s*\<([^\s\>]+)(\s|\>)/', $str, $matches) === 1) {
+                       if (!$preserveCase) {
+                               return strtoupper($matches[1]);
+                       }
+                       return $matches[1];
+               }
+               return '';
        }
 
        /**
        }
 
        /**
@@ -419,36 +533,35 @@ class t3lib_parsehtml {
         * @param       boolean         If set, the attribute values are de-htmlspecialchar'ed. Should actually always be set!
         * @return      array           array(Tag attributes,Attribute meta-data)
         */
         * @param       boolean         If set, the attribute values are de-htmlspecialchar'ed. Should actually always be set!
         * @return      array           array(Tag attributes,Attribute meta-data)
         */
-       function get_tag_attributes($tag,$deHSC=0)      {
-               list($components,$metaC) = $this->split_tag_attributes($tag);
-               $name = '';      // attribute name is stored here
-               $valuemode = '';
+       function get_tag_attributes($tag, $deHSC = 0) {
+               list($components, $metaC) = $this->split_tag_attributes($tag);
+               $name = ''; // attribute name is stored here
+               $valuemode = FALSE;
                $attributes = array();
                $attributesMeta = array();
                $attributes = array();
                $attributesMeta = array();
-               if (is_array($components))      {
-                       while (list($key,$val) = each ($components))    {
-                               if ($val != '=')        {       // Only if $name is set (if there is an attribute, that waits for a value), that valuemode is enabled. This ensures that the attribute is assigned it's value
-                                       if ($valuemode) {
-                                               if ($name)      {
-                                                       $attributes[$name] = $deHSC?t3lib_div::htmlspecialchars_decode($val):$val;
-                                                       $attributesMeta[$name]['dashType']=$metaC[$key];
+               if (is_array($components)) {
+                       foreach ($components as $key => $val) {
+                               if ($val != '=') { // Only if $name is set (if there is an attribute, that waits for a value), that valuemode is enabled. This ensures that the attribute is assigned it's value
+                                       if ($valuemode) {
+                                               if ($name) {
+                                                       $attributes[$name] = $deHSC ? t3lib_div::htmlspecialchars_decode($val) : $val;
+                                                       $attributesMeta[$name]['dashType'] = $metaC[$key];
                                                        $name = '';
                                                }
                                        } else {
                                                        $name = '';
                                                }
                                        } else {
-                                               if ($namekey = ereg_replace('[^a-zA-Z0-9_:-]','',$val)) {
+                                               if ($namekey = preg_replace('/[^[:alnum:]_\:\-]/', '', $val)) {
                                                        $name = strtolower($namekey);
                                                        $name = strtolower($namekey);
-                                                       $attributesMeta[$name]=array();
-                                                       $attributesMeta[$name]['origTag']=$namekey;
+                                                       $attributesMeta[$name] = array();
+                                                       $attributesMeta[$name]['origTag'] = $namekey;
                                                        $attributes[$name] = '';
                                                }
                                        }
                                                        $attributes[$name] = '';
                                                }
                                        }
-                                       $valuemode = '';
+                                       $valuemode = FALSE;
                                } else {
                                } else {
-                                       $valuemode = 'on';
+                                       $valuemode = TRUE;
                                }
                        }
                                }
                        }
-                       if (is_array($attributes))      reset($attributes);
-                       return array($attributes,$attributesMeta);
+                       return array($attributes, $attributesMeta);
                }
        }
 
                }
        }
 
@@ -461,34 +574,29 @@ class t3lib_parsehtml {
         * @access private
         * @see t3lib_div::split_tag_attributes()
         */
         * @access private
         * @see t3lib_div::split_tag_attributes()
         */
-       function split_tag_attributes($tag)     {
-               $tag_tmp = trim(eregi_replace ('^<[^[:space:]]*','',trim($tag)));
-                       // Removes any > in the end of the string
-               $tag_tmp = trim(eregi_replace ('>$','',$tag_tmp));
+       function split_tag_attributes($tag) {
+               $matches = array();
+               if (preg_match('/(\<[^\s]+\s+)?(.*?)\s*(\>)?$/s', $tag, $matches) !== 1) {
+                       return array(array(), array());
+               }
+               $tag_tmp = $matches[2];
 
                $metaValue = array();
                $value = array();
 
                $metaValue = array();
                $value = array();
-               while (strcmp($tag_tmp,''))     {       // Compared with empty string instead , 030102
-                       $firstChar=substr($tag_tmp,0,1);
-                       if (!strcmp($firstChar,'"') || !strcmp($firstChar,"'")) {
-                               $reg=explode($firstChar,$tag_tmp,3);
-                               $value[]=$reg[1];
-                               $metaValue[]=$firstChar;
-                               $tag_tmp=trim($reg[2]);
-                       } elseif (!strcmp($firstChar,'=')) {
-                               $value[] = '=';
-                               $metaValue[]='';
-                               $tag_tmp = trim(substr($tag_tmp,1));            // Removes = chars.
-                       } else {
-                                       // There are '' around the value. We look for the next ' ' or '>'
-                               $reg = split('[[:space:]=]',$tag_tmp,2);
-                               $value[] = trim($reg[0]);
-                               $metaValue[]='';
-                               $tag_tmp = trim(substr($tag_tmp,strlen($reg[0]),1).$reg[1]);
+               $matches = array();
+               if (preg_match_all('/("[^"]*"|\'[^\']*\'|[^\s"\'\=]+|\=)/s', $tag_tmp, $matches) > 0) {
+                       foreach ($matches[1] as $part) {
+                               $firstChar = substr($part, 0, 1);
+                               if ($firstChar == '"' || $firstChar == "'") {
+                                       $metaValue[] = $firstChar;
+                                       $value[] = substr($part, 1, -1);
+                               } else {
+                                       $metaValue[] = '';
+                                       $value[] = $part;
+                               }
                        }
                }
                        }
                }
-               if (is_array($value))   reset($value);
-               return array($value,$metaValue);
+               return array($value, $metaValue);
        }
 
        /**
        }
 
        /**
@@ -504,40 +612,44 @@ class t3lib_parsehtml {
         * @param       string          Tag names for solo tags (eg. img, br or input) in lowercase, commalist ("img,br,input")
         * @return      array           Analyse data.
         */
         * @param       string          Tag names for solo tags (eg. img, br or input) in lowercase, commalist ("img,br,input")
         * @return      array           Analyse data.
         */
-       function checkTagTypeCounts($content,$blockTags='a,b,blockquote,body,div,em,font,form,h1,h2,h3,h4,h5,h6,i,li,map,ol,option,p,pre,select,span,strong,table,td,textarea,tr,u,ul', $soloTags='br,hr,img,input,area')       {
+       function checkTagTypeCounts($content, $blockTags = 'a,b,blockquote,body,div,em,font,form,h1,h2,h3,h4,h5,h6,i,li,map,ol,option,p,pre,select,span,strong,table,td,textarea,tr,u,ul', $soloTags = 'br,hr,img,input,area') {
                $content = strtolower($content);
                $content = strtolower($content);
-               $analyzedOutput=array();
-               $analyzedOutput['counts']=array();      // Counts appearances of start-tags
-               $analyzedOutput['errors']=array();      // Lists ERRORS
-               $analyzedOutput['warnings']=array();    // Lists warnings.
-               $analyzedOutput['blocks']=array();      // Lists stats for block-tags
-               $analyzedOutput['solo']=array();        // Lists stats for solo-tags
+               $analyzedOutput = array();
+               $analyzedOutput['counts'] = array(); // Counts appearances of start-tags
+               $analyzedOutput['errors'] = array(); // Lists ERRORS
+               $analyzedOutput['warnings'] = array(); // Lists warnings.
+               $analyzedOutput['blocks'] = array(); // Lists stats for block-tags
+               $analyzedOutput['solo'] = array(); // Lists stats for solo-tags
 
                        // Block tags, must have endings...
 
                        // Block tags, must have endings...
-               $blockTags = explode(',',$blockTags);
-               foreach($blockTags as $tagName) {
-                       $countBegin = count(split('<'.$tagName.'[^[:alnum:]]',$content))-1;
-                       $countEnd = count(split('<\/'.$tagName.'[^[:alnum:]]',$content))-1;
-                       $analyzedOutput['blocks'][$tagName]=array($countBegin,$countEnd,$countBegin-$countEnd);
-                       if ($countBegin)        $analyzedOutput['counts'][$tagName]=$countBegin;
-                       if ($countBegin-$countEnd)      {
-                               if ($countBegin-$countEnd > 0)  {
-                                       $analyzedOutput['errors'][$tagName]='There were more start-tags ('.$countBegin.') than end-tags ('.$countEnd.') for the element "'.$tagName.'". There should be an equal amount!';
+               $blockTags = explode(',', $blockTags);
+               foreach ($blockTags as $tagName) {
+                       $countBegin = count(preg_split('/\<' . $tagName . '(\s|\>)/s', $content)) - 1;
+                       $countEnd = count(preg_split('/\<\/' . $tagName . '(\s|\>)/s', $content)) - 1;
+                       $analyzedOutput['blocks'][$tagName] = array($countBegin, $countEnd, $countBegin - $countEnd);
+                       if ($countBegin) {
+                               $analyzedOutput['counts'][$tagName] = $countBegin;
+                       }
+                       if ($countBegin - $countEnd) {
+                               if ($countBegin - $countEnd > 0) {
+                                       $analyzedOutput['errors'][$tagName] = 'There were more start-tags (' . $countBegin . ') than end-tags (' . $countEnd . ') for the element "' . $tagName . '". There should be an equal amount!';
                                } else {
                                } else {
-                                       $analyzedOutput['warnings'][$tagName]='There were more end-tags ('.$countEnd.') than start-tags ('.$countBegin.') for the element "'.$tagName.'". There should be an equal amount! However the problem is not fatal.';
+                                       $analyzedOutput['warnings'][$tagName] = 'There were more end-tags (' . $countEnd . ') than start-tags (' . $countBegin . ') for the element "' . $tagName . '". There should be an equal amount! However the problem is not fatal.';
                                }
                        }
                }
 
                        // Solo tags, must NOT have endings...
                                }
                        }
                }
 
                        // Solo tags, must NOT have endings...
-               $soloTags = explode(',',$soloTags);
-               foreach($soloTags as $tagName)  {
-                       $countBegin = count(split('<'.$tagName.'[^[:alnum:]]',$content))-1;
-                       $countEnd = count(split('<\/'.$tagName.'[^[:alnum:]]',$content))-1;
-                       $analyzedOutput['solo'][$tagName]=array($countBegin,$countEnd);
-                       if ($countBegin)        $analyzedOutput['counts'][$tagName]=$countBegin;
-                       if ($countEnd)  {
-                               $analyzedOutput['warnings'][$tagName]='There were end-tags found ('.$countEnd.') for the element "'.$tagName.'". This was not expected (although XHTML technically allows it).';
+               $soloTags = explode(',', $soloTags);
+               foreach ($soloTags as $tagName) {
+                       $countBegin = count(preg_split('/\<' . $tagName . '(\s|\>)/s', $content)) - 1;
+                       $countEnd = count(preg_split('/\<\/' . $tagName . '(\s|\>)/s', $content)) - 1;
+                       $analyzedOutput['solo'][$tagName] = array($countBegin, $countEnd);
+                       if ($countBegin) {
+                               $analyzedOutput['counts'][$tagName] = $countBegin;
+                       }
+                       if ($countEnd) {
+                               $analyzedOutput['warnings'][$tagName] = 'There were end-tags found (' . $countEnd . ') for the element "' . $tagName . '". This was not expected (although XHTML technically allows it).';
                        }
                }
 
                        }
                }
 
@@ -545,16 +657,6 @@ class t3lib_parsehtml {
        }
 
 
        }
 
 
-
-
-
-
-
-
-
-
-
-
        /*********************************
         *
         * Clean HTML code
        /*********************************
         *
         * Clean HTML code
@@ -567,28 +669,28 @@ class t3lib_parsehtml {
         * Initializing the $tags array to allow a list of tags (in this case <B>,<I>,<U> and <A>), set it like this:            $tags = array_flip(explode(',','b,a,i,u'))
         * If the value of the $tags[$tagname] entry is an array, advanced processing of the tags is initialized. These are the options:
         *
         * Initializing the $tags array to allow a list of tags (in this case <B>,<I>,<U> and <A>), set it like this:            $tags = array_flip(explode(',','b,a,i,u'))
         * If the value of the $tags[$tagname] entry is an array, advanced processing of the tags is initialized. These are the options:
         *
-        *      $tags[$tagname] = Array(
-        *              'overrideAttribs' => ''         If set, this string is preset as the attributes of the tag
-        *              'allowedAttribs' =>   '0' (zero) = no attributes allowed, '[commalist of attributes]' = only allowed attributes. If blank, all attributes are allowed.
-        *              'fixAttrib' => Array(
-        *                      '[attribute name]' => Array (
-        *                              'set' => Force the attribute value to this value.
-        *                              'unset' => Boolean: If set, the attribute is unset.
-        *                              'default' =>    If no attribute exists by this name, this value is set as default value (if this value is not blank)
-        *                              'always' =>     Boolean. If set, the attribute is always processed. Normally an attribute is processed only if it exists
-        *                              'trim,intval,lower,upper' =>    All booleans. If any of these keys are set, the value is passed through the respective PHP-functions.
-        *                              'range' => Array ('[low limit]','[high limit, optional]')               Setting integer range.
-        *                              'list' => Array ('[value1/default]','[value2]','[value3]')              Attribute must be in this list. If not, the value is set to the first element.
-        *                              'removeIfFalse' =>      Boolean/'blank'.        If set, then the attribute is removed if it is 'false'. If this value is set to 'blank' then the value must be a blank string (that means a 'zero' value will not be removed)
-        *                              'removeIfEquals' =>     [value] If the attribute value matches the value set here, then it is removed.
-        *                              'casesensitiveComp' => 1        If set, then the removeIfEquals and list comparisons will be case sensitive. Otherwise not.
-        *                      )
-        *              ),
-        *              'protect' => '',        Boolean. If set, the tag <> is converted to &lt; and &gt;
-        *              'remap' => '',          String. If set, the tagname is remapped to this tagname
-        *              'rmTagIfNoAttrib' => '',        Boolean. If set, then the tag is removed if no attributes happend to be there.
-        *              'nesting' => '',        Boolean/'global'. If set true, then this tag must have starting and ending tags in the correct order. Any tags not in this order will be discarded. Thus '</B><B><I></B></I></B>' will be converted to '<B><I></B></I>'. Is the value 'global' then true nesting in relation to other tags marked for 'global' nesting control is preserved. This means that if <B> and <I> are set for global nesting then this string '</B><B><I></B></I></B>' is converted to '<B></B>'
-        *      )
+        *       $tags[$tagname] = Array(
+        *               'overrideAttribs' => ''                If set, this string is preset as the attributes of the tag
+        *               'allowedAttribs' =>   '0' (zero) = no attributes allowed, '[commalist of attributes]' = only allowed attributes. If blank, all attributes are allowed.
+        *               'fixAttrib' => Array(
+        *                       '[attribute name]' => Array (
+        *                               'set' => Force the attribute value to this value.
+        *                               'unset' => Boolean: If set, the attribute is unset.
+        *                               'default' =>    If no attribute exists by this name, this value is set as default value (if this value is not blank)
+        *                               'always' =>     Boolean. If set, the attribute is always processed. Normally an attribute is processed only if it exists
+        *                               'trim,intval,lower,upper' =>    All booleans. If any of these keys are set, the value is passed through the respective PHP-functions.
+        *                               'range' => Array ('[low limit]','[high limit, optional]')              Setting integer range.
+        *                               'list' => Array ('[value1/default]','[value2]','[value3]')             Attribute must be in this list. If not, the value is set to the first element.
+        *                               'removeIfFalse' =>      Boolean/'blank'.       If set, then the attribute is removed if it is 'false'. If this value is set to 'blank' then the value must be a blank string (that means a 'zero' value will not be removed)
+        *                               'removeIfEquals' =>     [value]        If the attribute value matches the value set here, then it is removed.
+        *                               'casesensitiveComp' => 1       If set, then the removeIfEquals and list comparisons will be case sensitive. Otherwise not.
+        *                       )
+        *               ),
+        *               'protect' => '',       Boolean. If set, the tag <> is converted to &lt; and &gt;
+        *               'remap' => '',         String. If set, the tagname is remapped to this tagname
+        *               'rmTagIfNoAttrib' => '',       Boolean. If set, then the tag is removed if no attributes happend to be there.
+        *               'nesting' => '',       Boolean/'global'. If set true, then this tag must have starting and ending tags in the correct order. Any tags not in this order will be discarded. Thus '</B><B><I></B></I></B>' will be converted to '<B><I></B></I>'. Is the value 'global' then true nesting in relation to other tags marked for 'global' nesting control is preserved. This means that if <B> and <I> are set for global nesting then this string '</B><B><I></B></I></B>' is converted to '<B></B>'
+        *       )
         *
         * @param       string          $content; is the HTML-content being processed. This is also the result being returned.
         * @param       array           $tags; is an array where each key is a tagname in lowercase. Only tags present as keys in this array are preserved. The value of the key can be an array with a vast number of options to configure.
         *
         * @param       string          $content; is the HTML-content being processed. This is also the result being returned.
         * @param       array           $tags; is an array where each key is a tagname in lowercase. Only tags present as keys in this array are preserved. The value of the key can be an array with a vast number of options to configure.
@@ -597,134 +699,208 @@ class t3lib_parsehtml {
         * @param       array           Configuration array send along as $conf to the internal functions ->processContent() and ->processTag()
         * @return      string          Processed HTML content
         */
         * @param       array           Configuration array send along as $conf to the internal functions ->processContent() and ->processTag()
         * @return      string          Processed HTML content
         */
-       function HTMLcleaner($content, $tags=array(),$keepAll=0,$hSC=0,$addConfig=array())      {
+       function HTMLcleaner($content, $tags = array(), $keepAll = 0, $hSC = 0, $addConfig = array()) {
                $newContent = array();
                $newContent = array();
-               $tokArr = explode('<',$content);
-               $newContent[] = $this->processContent(current($tokArr),$hSC,$addConfig);
+               $tokArr = explode('<', $content);
+               $newContent[] = $this->processContent(current($tokArr), $hSC, $addConfig);
                next($tokArr);
 
                $c = 1;
                $tagRegister = array();
                $tagStack = array();
                next($tokArr);
 
                $c = 1;
                $tagRegister = array();
                $tagStack = array();
-               while(list(,$tok)=each($tokArr))        {
-                       $firstChar = substr($tok,0,1);
-#                      if (strcmp(trim($firstChar),''))        {               // It is a tag...
-                       if (ereg('[[:alnum:]\/]',$firstChar))   {               // It is a tag... (first char is a-z0-9 or /) (fixed 19/01 2004). This also avoids triggering on <?xml..> and <!DOCTYPE..>
-                               $tagEnd = strcspn($tok,'>');
-                               if (strlen($tok)!=$tagEnd)      {       // If there is and end-bracket...
-                                       $endTag = $firstChar=='/' ? 1 : 0;
-                                       $tagContent = substr($tok,$endTag,$tagEnd-$endTag);
-                                       $tagParts = split('[[:space:]]',$tagContent,2);
+               $inComment = FALSE;
+               $skipTag = FALSE;
+               while (list(, $tok) = each($tokArr)) {
+                       if ($inComment) {
+                               if (($eocPos = strpos($tok, '-->')) === FALSE) {
+                                               // End of comment is not found in the token. Go futher until end of comment is found in other tokens.
+                                       $newContent[$c++] = '<' . $tok;
+                                       continue;
+                               }
+                                       // Comment ends in the middle of the token: add comment and proceed with rest of the token
+                               $newContent[$c++] = '<' . substr($tok, 0, $eocPos + 3);
+                               $tok = substr($tok, $eocPos + 3);
+                               $inComment = FALSE;
+                               $skipTag = TRUE;
+                       }
+                       elseif (substr($tok, 0, 3) == '!--') {
+                               if (($eocPos = strpos($tok, '-->')) === FALSE) {
+                                               // Comment started in this token but it does end in the same token. Set a flag to skip till the end of comment
+                                       $newContent[$c++] = '<' . $tok;
+                                       $inComment = TRUE;
+                                       continue;
+                               }
+                                       // Start and end of comment are both in the current token. Add comment and proceed with rest of the token
+                               $newContent[$c++] = '<' . substr($tok, 0, $eocPos + 3);
+                               $tok = substr($tok, $eocPos + 3);
+                               $skipTag = TRUE;
+                       }
+                       $firstChar = substr($tok, 0, 1);
+                       if (!$skipTag && preg_match('/[[:alnum:]\/]/', $firstChar) == 1) { // It is a tag... (first char is a-z0-9 or /) (fixed 19/01 2004). This also avoids triggering on <?xml..> and <!DOCTYPE..>
+                               $tagEnd = strpos($tok, '>');
+                               if ($tagEnd) { // If there is and end-bracket...        tagEnd can't be 0 as the first character can't be a >
+                                       $endTag = $firstChar == '/' ? 1 : 0;
+                                       $tagContent = substr($tok, $endTag, $tagEnd - $endTag);
+                                       $tagParts = preg_split('/\s+/s', $tagContent, 2);
                                        $tagName = strtolower($tagParts[0]);
                                        $tagName = strtolower($tagParts[0]);
-                                       if (isset($tags[$tagName]))     {
-                                               if (is_array($tags[$tagName]))  {       // If there is processing to do for the tag:
-
-                                                       if (!$endTag)   {       // If NOT an endtag, do attribute processing (added dec. 2003)
+                                       $emptyTag = 0;
+                                       if (isset($tags[$tagName])) {
+                                               if (is_array($tags[$tagName])) { // If there is processing to do for the tag:
+                                                       if (preg_match('/^(' . self::VOID_ELEMENTS . ' )$/i', $tagName)) {
+                                                               $emptyTag = 1;
+                                                       }
+                                                       if (!$endTag) { // If NOT an endtag, do attribute processing (added dec. 2003)
                                                                        // Override attributes
                                                                        // Override attributes
-                                                               if (strcmp($tags[$tagName]['overrideAttribs'],''))      {
-                                                                       $tagParts[1]=$tags[$tagName]['overrideAttribs'];
+                                                               if (strcmp($tags[$tagName]['overrideAttribs'], '')) {
+                                                                       $tagParts[1] = $tags[$tagName]['overrideAttribs'];
                                                                }
 
                                                                        // Allowed tags
                                                                }
 
                                                                        // Allowed tags
-                                                               if (strcmp($tags[$tagName]['allowedAttribs'],''))       {
-                                                                       if (!strcmp($tags[$tagName]['allowedAttribs'],'0'))     {       // No attribs allowed
-                                                                               $tagParts[1]='';
+                                                               if (strcmp($tags[$tagName]['allowedAttribs'], '')) {
+                                                                       if (!strcmp($tags[$tagName]['allowedAttribs'], '0')) { // No attribs allowed
+                                                                               $tagParts[1] = '';
                                                                        } elseif (trim($tagParts[1])) {
                                                                                $tagAttrib = $this->get_tag_attributes($tagParts[1]);
                                                                        } elseif (trim($tagParts[1])) {
                                                                                $tagAttrib = $this->get_tag_attributes($tagParts[1]);
-                                                                               $tagParts[1]='';
+                                                                               $tagParts[1] = '';
                                                                                $newTagAttrib = array();
                                                                                $newTagAttrib = array();
-                                                                               $tList = t3lib_div::trimExplode(',',strtolower($tags[$tagName]['allowedAttribs']),1);
-                                                                               while(list(,$allowTag)=each($tList))    {
-                                                                                       if (isset($tagAttrib[0][$allowTag]))    $newTagAttrib[$allowTag]=$tagAttrib[0][$allowTag];
+                                                                               if (!($tList = $tags[$tagName]['_allowedAttribs'])) {
+                                                                                               // Just explode attribts for tag once
+                                                                                       $tList = $tags[$tagName]['_allowedAttribs'] = t3lib_div::trimExplode(',', strtolower($tags[$tagName]['allowedAttribs']), 1);
                                                                                }
                                                                                }
-                                                                               $tagParts[1]=$this->compileTagAttribs($newTagAttrib,$tagAttrib[1]);
+                                                                               foreach ($tList as $allowTag) {
+                                                                                       if (isset($tagAttrib[0][$allowTag])) {
+                                                                                               $newTagAttrib[$allowTag] = $tagAttrib[0][$allowTag];
+                                                                                       }
+                                                                               }
+                                                                               $tagParts[1] = $this->compileTagAttribs($newTagAttrib, $tagAttrib[1]);
                                                                        }
                                                                }
 
                                                                        // Fixed attrib values
                                                                        }
                                                                }
 
                                                                        // Fixed attrib values
-                                                               if (is_array($tags[$tagName]['fixAttrib']))     {
+                                                               if (is_array($tags[$tagName]['fixAttrib'])) {
                                                                        $tagAttrib = $this->get_tag_attributes($tagParts[1]);
                                                                        $tagAttrib = $this->get_tag_attributes($tagParts[1]);
-                                                                       $tagParts[1]='';
-                                                                       reset($tags[$tagName]['fixAttrib']);
-                                                                       while(list($attr,$params)=each($tags[$tagName]['fixAttrib']))   {
-                                                                               if (strlen($params['set']))     $tagAttrib[0][$attr] = $params['set'];
-                                                                               if (strlen($params['unset']))   unset($tagAttrib[0][$attr]);
-                                                                               if (strcmp($params['default'],'') && !isset($tagAttrib[0][$attr]))      $tagAttrib[0][$attr]=$params['default'];
-                                                                               if ($params['always'] || isset($tagAttrib[0][$attr]))   {
-                                                                                       if ($params['trim'])    {$tagAttrib[0][$attr]=trim($tagAttrib[0][$attr]);}
-                                                                                       if ($params['intval'])  {$tagAttrib[0][$attr]=intval($tagAttrib[0][$attr]);}
-                                                                                       if ($params['lower'])   {$tagAttrib[0][$attr]=strtolower($tagAttrib[0][$attr]);}
-                                                                                       if ($params['upper'])   {$tagAttrib[0][$attr]=strtoupper($tagAttrib[0][$attr]);}
-                                                                                       if ($params['range'])   {
-                                                                                               if (isset($params['range'][1])) {
-                                                                                                       $tagAttrib[0][$attr]=t3lib_div::intInRange($tagAttrib[0][$attr],intval($params['range'][0]),intval($params['range'][1]));
+                                                                       $tagParts[1] = '';
+                                                                       foreach ($tags[$tagName]['fixAttrib'] as $attr => $params) {
+                                                                               if (strlen($params['set'])) {
+                                                                                       $tagAttrib[0][$attr] = $params['set'];
+                                                                               }
+                                                                               if (strlen($params['unset'])) {
+                                                                                       unset($tagAttrib[0][$attr]);
+                                                                               }
+                                                                               if (strcmp($params['default'], '') && !isset($tagAttrib[0][$attr])) {
+                                                                                       $tagAttrib[0][$attr] = $params['default'];
+                                                                               }
+                                                                               if ($params['always'] || isset($tagAttrib[0][$attr])) {
+                                                                                       if ($params['trim']) {
+                                                                                               $tagAttrib[0][$attr] = trim($tagAttrib[0][$attr]);
+                                                                                       }
+                                                                                       if ($params['intval']) {
+                                                                                               $tagAttrib[0][$attr] = intval($tagAttrib[0][$attr]);
+                                                                                       }
+                                                                                       if ($params['lower']) {
+                                                                                               $tagAttrib[0][$attr] = strtolower($tagAttrib[0][$attr]);
+                                                                                       }
+                                                                                       if ($params['upper']) {
+                                                                                               $tagAttrib[0][$attr] = strtoupper($tagAttrib[0][$attr]);
+                                                                                       }
+                                                                                       if ($params['range']) {
+                                                                                               if (isset($params['range'][1])) {
+                                                                                                       $tagAttrib[0][$attr] = t3lib_div::intInRange($tagAttrib[0][$attr], intval($params['range'][0]), intval($params['range'][1]));
                                                                                                } else {
                                                                                                } else {
-                                                                                                       $tagAttrib[0][$attr]=t3lib_div::intInRange($tagAttrib[0][$attr],intval($params['range'][0]));
+                                                                                                       $tagAttrib[0][$attr] = t3lib_div::intInRange($tagAttrib[0][$attr], intval($params['range'][0]));
                                                                                                }
                                                                                        }
                                                                                                }
                                                                                        }
-                                                                                       if (is_array($params['list']))  {
-                                                                                               if (!in_array($this->caseShift($tagAttrib[0][$attr],$params['casesensitiveComp']),$this->caseShift($params['list'],$params['casesensitiveComp'],$tagName)))     $tagAttrib[0][$attr]=$params['list'][0];
+                                                                                       if (is_array($params['list'])) {
+                                                                                                       // For the class attribute, remove from the attribute value any class not in the list
+                                                                                                       // Classes are case sensitive
+                                                                                               if ($attr == 'class') {
+                                                                                                       $newClasses = array();
+                                                                                                       $classes = t3lib_div::trimExplode(' ', $tagAttrib[0][$attr], TRUE);
+                                                                                                       foreach ($classes as $class) {
+                                                                                                               if (in_array($class, $params['list'])) {
+                                                                                                                       $newClasses[] = $class;
+                                                                                                               }
+                                                                                                       }
+                                                                                                       if (count($newClasses)) {
+                                                                                                               $tagAttrib[0][$attr] = implode(' ', $newClasses);
+                                                                                                       } else {
+                                                                                                               $tagAttrib[0][$attr] = '';
+                                                                                                       }
+                                                                                               } else {
+                                                                                                       if (!in_array($this->caseShift($tagAttrib[0][$attr], $params['casesensitiveComp']), $this->caseShift($params['list'], $params['casesensitiveComp'], $tagName))) {
+                                                                                                               $tagAttrib[0][$attr] = $params['list'][0];
+                                                                                                       }
+                                                                                               }
                                                                                        }
                                                                                        }
-                                                                                       if (($params['removeIfFalse'] && $params['removeIfFalse']!='blank' && !$tagAttrib[0][$attr]) || ($params['removeIfFalse']=='blank' && !strcmp($tagAttrib[0][$attr],'')))        {
+                                                                                       if (($params['removeIfFalse'] && $params['removeIfFalse'] != 'blank' && !$tagAttrib[0][$attr]) || ($params['removeIfFalse'] == 'blank' && !strcmp($tagAttrib[0][$attr], ''))) {
                                                                                                unset($tagAttrib[0][$attr]);
                                                                                        }
                                                                                                unset($tagAttrib[0][$attr]);
                                                                                        }
-                                                                                       if (strcmp($params['removeIfEquals'],'') && !strcmp($this->caseShift($tagAttrib[0][$attr],$params['casesensitiveComp']),$this->caseShift($params['removeIfEquals'],$params['casesensitiveComp'])))      {
+                                                                                       if (strcmp($params['removeIfEquals'], '') && !strcmp($this->caseShift($tagAttrib[0][$attr], $params['casesensitiveComp']), $this->caseShift($params['removeIfEquals'], $params['casesensitiveComp']))) {
                                                                                                unset($tagAttrib[0][$attr]);
                                                                                        }
                                                                                                unset($tagAttrib[0][$attr]);
                                                                                        }
-                                                                                       if ($params['prefixLocalAnchors'])      {
-                                                                                               if (substr($tagAttrib[0][$attr],0,1)=='#')      {
+                                                                                       if ($params['prefixLocalAnchors']) {
+                                                                                               if (substr($tagAttrib[0][$attr], 0, 1) == '#') {
                                                                                                        $prefix = t3lib_div::getIndpEnv('TYPO3_REQUEST_URL');
                                                                                                        $prefix = t3lib_div::getIndpEnv('TYPO3_REQUEST_URL');
-                                                                                                       $tagAttrib[0][$attr] = $prefix.$tagAttrib[0][$attr];
-                                                                                                       if ($params['prefixLocalAnchors']==2 && t3lib_div::isFirstPartOfStr($prefix,t3lib_div::getIndpEnv('TYPO3_SITE_URL')))           {
-                                                                                                               $tagAttrib[0][$attr] = substr($tagAttrib[0][$attr],strlen(t3lib_div::getIndpEnv('TYPO3_SITE_URL')));
+                                                                                                       $tagAttrib[0][$attr] = $prefix . $tagAttrib[0][$attr];
+                                                                                                       if ($params['prefixLocalAnchors'] == 2 && t3lib_div::isFirstPartOfStr($prefix, t3lib_div::getIndpEnv('TYPO3_SITE_URL'))) {
+                                                                                                               $tagAttrib[0][$attr] = substr($tagAttrib[0][$attr], strlen(t3lib_div::getIndpEnv('TYPO3_SITE_URL')));
                                                                                                        }
                                                                                                }
                                                                                        }
                                                                                                        }
                                                                                                }
                                                                                        }
-                                                                                       if ($params['prefixRelPathWith'])       {
+                                                                                       if ($params['prefixRelPathWith']) {
                                                                                                $urlParts = parse_url($tagAttrib[0][$attr]);
                                                                                                $urlParts = parse_url($tagAttrib[0][$attr]);
-                                                                                               if (!$urlParts['scheme'] && substr($urlParts['path'],0,1)!='/') {       // If it is NOT an absolute URL (by http: or starting "/")
-                                                                                                       $tagAttrib[0][$attr] = $params['prefixRelPathWith'].$tagAttrib[0][$attr];
+                                                                                               if (!$urlParts['scheme'] && substr($urlParts['path'], 0, 1) != '/') { // If it is NOT an absolute URL (by http: or starting "/")
+                                                                                                       $tagAttrib[0][$attr] = $params['prefixRelPathWith'] . $tagAttrib[0][$attr];
                                                                                                }
                                                                                        }
                                                                                                }
                                                                                        }
-                                                                                       if ($params['userFunc'])        {
-                                                                                               $tagAttrib[0][$attr] = t3lib_div::callUserFunction($params['userFunc'],$tagAttrib[0][$attr],$this);
+                                                                                       if ($params['userFunc']) {
+                                                                                               $tagAttrib[0][$attr] = t3lib_div::callUserFunction($params['userFunc'], $tagAttrib[0][$attr], $this);
                                                                                        }
                                                                                }
                                                                        }
                                                                                        }
                                                                                }
                                                                        }
-                                                                       $tagParts[1]=$this->compileTagAttribs($tagAttrib[0],$tagAttrib[1]);
+                                                                       $tagParts[1] = $this->compileTagAttribs($tagAttrib[0], $tagAttrib[1]);
                                                                }
                                                                }
-                                                       } else {        // If endTag, remove any possible attributes:
-                                                               $tagParts[1]='';
+                                                       } else { // If endTag, remove any possible attributes:
+                                                               $tagParts[1] = '';
                                                        }
 
                                                                // Protecting the tag by converting < and > to &lt; and &gt; ??
                                                        }
 
                                                                // Protecting the tag by converting < and > to &lt; and &gt; ??
-                                                       if ($tags[$tagName]['protect']) {
-                                                               $lt = '&lt;';   $gt = '&gt;';
+                                                       if ($tags[$tagName]['protect']) {
+                                                               $lt = '&lt;';
+                                                               $gt = '&gt;';
                                                        } else {
                                                        } else {
-                                                               $lt = '<';      $gt = '>';
+                                                               $lt = '<';
+                                                               $gt = '>';
                                                        }
                                                                // Remapping tag name?
                                                        }
                                                                // Remapping tag name?
-                                                       if ($tags[$tagName]['remap'])   $tagParts[0] = $tags[$tagName]['remap'];
+                                                       if ($tags[$tagName]['remap']) {
+                                                               $tagParts[0] = $tags[$tagName]['remap'];
+                                                       }
 
                                                                // rmTagIfNoAttrib
 
                                                                // rmTagIfNoAttrib
-                                                       if ($endTag || trim($tagParts[1]) || !$tags[$tagName]['rmTagIfNoAttrib'])       {
-                                                               $setTag=1;
-
-                                                               if ($tags[$tagName]['nesting']) {
-                                                                       if (!is_array($tagRegister[$tagName]))  $tagRegister[$tagName]=array();
+                                                       if ($endTag || trim($tagParts[1]) || !$tags[$tagName]['rmTagIfNoAttrib']) {
+                                                               $setTag = 1;
+                                                                       // Remove this closing tag if $tagName was among $TSconfig['removeTags']
+                                                               if ($endTag && $tags[$tagName]['allowedAttribs'] === 0 && $tags[$tagName]['rmTagIfNoAttrib'] === 1) {
+                                                                       $setTag = 0;
+                                                               }
+                                                               if ($tags[$tagName]['nesting']) {
+                                                                       if (!is_array($tagRegister[$tagName])) {
+                                                                               $tagRegister[$tagName] = array();
+                                                                       }
 
 
-                                                                       if ($endTag)    {
-/*                                                                             if ($tags[$tagName]['nesting']=='global')       {
-                                                                                       $lastEl = end($tagStack);
-                                                                                       $correctTag = !strcmp($tagName,$lastEl);
-                                                                               } else $correctTag=1;
-       */
-                                                                               $correctTag=1;
-                                                                               if ($tags[$tagName]['nesting']=='global')       {
+                                                                       if ($endTag) {
+                                                                               /*                                                                              if ($tags[$tagName]['nesting']=='global')       {
+                                                                                                        $lastEl = end($tagStack);
+                                                                                                        $correctTag = !strcmp($tagName,$lastEl);
+                                                                                                } else $correctTag=1;
+                        */
+                                                                               $correctTag = 1;
+                                                                               if ($tags[$tagName]['nesting'] == 'global') {
                                                                                        $lastEl = end($tagStack);
                                                                                        $lastEl = end($tagStack);
-                                                                                       if (strcmp($tagName,$lastEl))   {
-                                                                                               if (in_array($tagName,$tagStack))       {
-                                                                                                       while(count($tagStack) && strcmp($tagName,$lastEl))     {
+                                                                                       if (strcmp($tagName, $lastEl)) {
+                                                                                               if (in_array($tagName, $tagStack)) {
+                                                                                                       while (count($tagStack) && strcmp($tagName, $lastEl)) {
                                                                                                                $elPos = end($tagRegister[$lastEl]);
                                                                                                                unset($newContent[$elPos]);
 
                                                                                                                $elPos = end($tagRegister[$lastEl]);
                                                                                                                unset($newContent[$elPos]);
 
@@ -733,57 +909,62 @@ class t3lib_parsehtml {
                                                                                                                $lastEl = end($tagStack);
                                                                                                        }
                                                                                                } else {
                                                                                                                $lastEl = end($tagStack);
                                                                                                        }
                                                                                                } else {
-                                                                                                       $correctTag=0;  // In this case the
+                                                                                                       $correctTag = 0; // In this case the
                                                                                                }
                                                                                        }
                                                                                }
                                                                                                }
                                                                                        }
                                                                                }
-                                                                               if (!count($tagRegister[$tagName]) || !$correctTag)     {
-                                                                                       $setTag=0;
+                                                                               if (!count($tagRegister[$tagName]) || !$correctTag) {
+                                                                                       $setTag = 0;
                                                                                } else {
                                                                                        array_pop($tagRegister[$tagName]);
                                                                                } else {
                                                                                        array_pop($tagRegister[$tagName]);
-                                                                                       if ($tags[$tagName]['nesting']=='global')       {array_pop($tagStack);}
+                                                                                       if ($tags[$tagName]['nesting'] == 'global') {
+                                                                                               array_pop($tagStack);
+                                                                                       }
                                                                                }
                                                                        } else {
                                                                                }
                                                                        } else {
-                                                                               array_push($tagRegister[$tagName],$c);
-                                                                               if ($tags[$tagName]['nesting']=='global')       {array_push($tagStack,$tagName);}
+                                                                               array_push($tagRegister[$tagName], $c);
+                                                                               if ($tags[$tagName]['nesting'] == 'global') {
+                                                                                       array_push($tagStack, $tagName);
+                                                                               }
                                                                        }
                                                                }
 
                                                                        }
                                                                }
 
-                                                               if ($setTag)    {
+                                                               if ($setTag) {
                                                                                // Setting the tag
                                                                                // Setting the tag
-                                                                       $newContent[$c++]=$this->processTag($lt.($endTag?'/':'').trim($tagParts[0].' '.$tagParts[1]).$gt,$addConfig,$endTag,$lt=='&lt;');
+                                                                       $newContent[$c++] = $this->processTag($lt . ($endTag ? '/' : '') . trim($tagParts[0] . ' ' . $tagParts[1]) . ($emptyTag ? ' /' : '' ) . $gt, $addConfig, $endTag, $lt == '&lt;');
                                                                }
                                                        }
                                                } else {
                                                                }
                                                        }
                                                } else {
-                                                       $newContent[$c++]=$this->processTag('<'.($endTag?'/':'').$tagContent.'>',$addConfig,$endTag);
+                                                       $newContent[$c++] = $this->processTag('<' . ($endTag ? '/' : '') . $tagContent . '>', $addConfig, $endTag);
                                                }
                                                }
-                                       } elseif ($keepAll) {   // This is if the tag was not defined in the array for processing:
-                                               if (!strcmp($keepAll,'protect'))        {
-                                                       $lt = '&lt;';   $gt = '&gt;';
+                                       } elseif ($keepAll) { // This is if the tag was not defined in the array for processing:
+                                               if (!strcmp($keepAll, 'protect')) {
+                                                       $lt = '&lt;';
+                                                       $gt = '&gt;';
                                                } else {
                                                } else {
-                                                       $lt = '<';      $gt = '>';
+                                                       $lt = '<';
+                                                       $gt = '>';
                                                }
                                                }
-                                               $newContent[$c++]=$this->processTag($lt.($endTag?'/':'').$tagContent.$gt,$addConfig,$endTag,$lt=='&lt;');
+                                               $newContent[$c++] = $this->processTag($lt . ($endTag ? '/' : '') . $tagContent . $gt, $addConfig, $endTag, $lt == '&lt;');
                                        }
                                        }
-                                       $newContent[$c++]=$this->processContent(substr($tok,$tagEnd+1),$hSC,$addConfig);
+                                       $newContent[$c++] = $this->processContent(substr($tok, $tagEnd + 1), $hSC, $addConfig);
                                } else {
                                } else {
-                                       $newContent[$c++]=$this->processContent('<'.$tok,$hSC,$addConfig);      // There were not end-bracket, so no tag...
+                                       $newContent[$c++] = $this->processContent('<' . $tok, $hSC, $addConfig); // There were not end-bracket, so no tag...
                                }
                        } else {
                                }
                        } else {
-                               $newContent[$c++]=$this->processContent('<'.$tok,$hSC,$addConfig);      // It was not a tag anyways
+                               $newContent[$c++] = $this->processContent(($skipTag ? '' : '<') . $tok, $hSC, $addConfig); // It was not a tag anyways
+                               $skipTag = FALSE;
                        }
                }
 
                        // Unsetting tags:
                        }
                }
 
                        // Unsetting tags:
-               reset($tagRegister);
-               while(list($tag,$positions)=each($tagRegister)) {
-                       reset($positions);
-                       while(list(,$pKey)=each($positions))    {
+               foreach ($tagRegister as $tag => $positions) {
+                       foreach ($positions as $pKey) {
                                unset($newContent[$pKey]);
                        }
                }
 
                                unset($newContent[$pKey]);
                        }
                }
 
-               return implode('',$newContent);
+               return implode('', $newContent);
        }
 
        /**
        }
 
        /**
@@ -793,16 +974,16 @@ class t3lib_parsehtml {
         * @param       integer         Direction: forth ($dir=1, dir=2 for preserving entities) AND back ($dir=-1)
         * @return      string          Output value
         */
         * @param       integer         Direction: forth ($dir=1, dir=2 for preserving entities) AND back ($dir=-1)
         * @return      string          Output value
         */
-       function bidir_htmlspecialchars($value,$dir)    {
-               if ($dir==1)    {
+       function bidir_htmlspecialchars($value, $dir) {
+               if ($dir == 1) {
                        $value = htmlspecialchars($value);
                        $value = htmlspecialchars($value);
-               } elseif ($dir==2)      {
+               } elseif ($dir == 2) {
                        $value = t3lib_div::deHSCentities(htmlspecialchars($value));
                        $value = t3lib_div::deHSCentities(htmlspecialchars($value));
-               } elseif ($dir==-1) {
-                       $value = str_replace('&gt;','>',$value);
-                       $value = str_replace('&lt;','<',$value);
-                       $value = str_replace('&quot;','"',$value);
-                       $value = str_replace('&amp;','&',$value);
+               } elseif ($dir == -1) {
+                       $value = str_replace('&gt;', '>', $value);
+                       $value = str_replace('&lt;', '<', $value);
+                       $value = str_replace('&quot;', '"', $value);
+                       $value = str_replace('&amp;', '&', $value);
                }
                return $value;
        }
                }
                return $value;
        }
@@ -816,25 +997,25 @@ class t3lib_parsehtml {
         * @param       string          Suffix string (put after the resource).
         * @return      string          Processed HTML content
         */
         * @param       string          Suffix string (put after the resource).
         * @return      string          Processed HTML content
         */
-       function prefixResourcePath($main_prefix,$content,$alternatives=array(),$suffix='')     {
-
-               $parts = $this->splitTags('embed,td,table,body,img,input,form,link,script,a',$content);
-               foreach($parts as $k => $v)     {
-                       if ($k%2)       {
-                               $params = $this->get_tag_attributes($v,1);
-                               $tagEnd = substr($v,-2)=='/>' ? ' />' : '>';    // Detect tag-ending so that it is re-applied correctly.
-                               $firstTagName = $this->getFirstTagName($v);     // The 'name' of the first tag
-                               $somethingDone=0;
+       function prefixResourcePath($main_prefix, $content, $alternatives = array(), $suffix = '') {
+
+               $parts = $this->splitTags('embed,td,table,body,img,input,form,link,script,a,param', $content);
+               foreach ($parts as $k => $v) {
+                       if ($k % 2) {
+                               $params = $this->get_tag_attributes($v);
+                               $tagEnd = substr($v, -2) == '/>' ? ' />' : '>'; // Detect tag-ending so that it is re-applied correctly.
+                               $firstTagName = $this->getFirstTagName($v); // The 'name' of the first tag
+                               $somethingDone = 0;
                                $prefix = isset($alternatives[strtoupper($firstTagName)]) ? $alternatives[strtoupper($firstTagName)] : $main_prefix;
                                $prefix = isset($alternatives[strtoupper($firstTagName)]) ? $alternatives[strtoupper($firstTagName)] : $main_prefix;
-                               switch(strtolower($firstTagName))       {
+                               switch (strtolower($firstTagName)) {
                                                // background - attribute:
                                        case 'td':
                                        case 'body':
                                        case 'table':
                                                $src = $params[0]['background'];
                                                // background - attribute:
                                        case 'td':
                                        case 'body':
                                        case 'table':
                                                $src = $params[0]['background'];
-                                               if ($src)       {
-                                                       $params[0]['background'] = $this->prefixRelPath($prefix,$params[0]['background'],$suffix);
-                                                       $somethingDone=1;
+                                               if ($src) {
+                                                       $params[0]['background'] = $this->prefixRelPath($prefix, $params[0]['background'], $suffix);
+                                                       $somethingDone = 1;
                                                }
                                        break;
                                                // src attribute
                                                }
                                        break;
                                                // src attribute
@@ -843,48 +1024,57 @@ class t3lib_parsehtml {
                                        case 'script':
                                        case 'embed':
                                                $src = $params[0]['src'];
                                        case 'script':
                                        case 'embed':
                                                $src = $params[0]['src'];
-                                               if ($src)       {
-                                                       $params[0]['src'] = $this->prefixRelPath($prefix,$params[0]['src'],$suffix);
-                                                       $somethingDone=1;
+                                               if ($src) {
+                                                       $params[0]['src'] = $this->prefixRelPath($prefix, $params[0]['src'], $suffix);
+                                                       $somethingDone = 1;
                                                }
                                        break;
                                        case 'link':
                                        case 'a':
                                                $src = $params[0]['href'];
                                                }
                                        break;
                                        case 'link':
                                        case 'a':
                                                $src = $params[0]['href'];
-                                               if ($src)       {
-                                                       $params[0]['href'] = $this->prefixRelPath($prefix,$params[0]['href'],$suffix);
-                                                       $somethingDone=1;
+                                               if ($src) {
+                                                       $params[0]['href'] = $this->prefixRelPath($prefix, $params[0]['href'], $suffix);
+                                                       $somethingDone = 1;
                                                }
                                        break;
                                                // action attribute
                                        case 'form':
                                                $src = $params[0]['action'];
                                                }
                                        break;
                                                // action attribute
                                        case 'form':
                                                $src = $params[0]['action'];
-                                               if ($src)       {
-                                                       $params[0]['action'] = $this->prefixRelPath($prefix,$params[0]['action'],$suffix);
-                                                       $somethingDone=1;
+                                               if ($src) {
+                                                       $params[0]['action'] = $this->prefixRelPath($prefix, $params[0]['action'], $suffix);
+                                                       $somethingDone = 1;
+                                               }
+                                       break;
+                                               // value attribute
+                                       case 'param':
+                                               $test = $params[0]['name'];
+                                               if ($test && $test === 'movie') {
+                                                       if ($params[0]['value']) {
+                                                               $params[0]['value'] = $this->prefixRelPath($prefix, $params[0]['value'], $suffix);
+                                                               $somethingDone = 1;
+                                                       }
                                                }
                                        break;
                                }
                                                }
                                        break;
                                }
-                               if ($somethingDone)     {
-                                       $tagParts = split('[[:space:]]',$v,2);
-                                       $tagParts[1]=$this->compileTagAttribs($params[0],$params[1]);
-                                       $parts[$k] = '<'.trim(strtolower($firstTagName).' '.$tagParts[1]).
-                                                                       $tagEnd;
+                               if ($somethingDone) {
+                                       $tagParts = preg_split('/\s+/s', $v, 2);
+                                       $tagParts[1] = $this->compileTagAttribs($params[0], $params[1]);
+                                       $parts[$k] = '<' . trim(strtolower($firstTagName) . ' ' . $tagParts[1]) . $tagEnd;
                                }
                        }
                }
                                }
                        }
                }
-               $content = implode('',$parts);
+               $content = implode('', $parts);
 
                        // Fix <style> section:
                $prefix = isset($alternatives['style']) ? $alternatives['style'] : $main_prefix;
 
                        // Fix <style> section:
                $prefix = isset($alternatives['style']) ? $alternatives['style'] : $main_prefix;
-               if (strlen($prefix))    {
-                       $parts = $this->splitIntoBlock('style',$content);
-                       foreach($parts as $k => $v)     {
-                               if ($k%2)       {
-                                       $parts[$k] = eregi_replace('(url[[:space:]]*\([[:space:]]*["\']?)([^"\')]*)(["\']?[[:space:]]*\))','\1'.$prefix.'\2'.$suffix.'\3',$parts[$k]);
+               if (strlen($prefix)) {
+                       $parts = $this->splitIntoBlock('style', $content);
+                       foreach ($parts as $k => $v) {
+                               if ($k % 2) {
+                                       $parts[$k] = preg_replace('/(url[[:space:]]*\([[:space:]]*["\']?)([^"\')]*)(["\']?[[:space:]]*\))/i', '\1' . $prefix . '\2' . $suffix . '\3', $parts[$k]);
                                }
                        }
                                }
                        }
-                       $content = implode('',$parts);
+                       $content = implode('', $parts);
                }
 
                return $content;
                }
 
                return $content;
@@ -899,10 +1089,15 @@ class t3lib_parsehtml {
         * @return      string          Output path, prefixed if no scheme in input string
         * @access private
         */
         * @return      string          Output path, prefixed if no scheme in input string
         * @access private
         */
-       function prefixRelPath($prefix,$srcVal,$suffix='')      {
-               $pU = parse_url($srcVal);
-               if (!$pU['scheme'] && substr($srcVal, 0, 1)!='/')       { // If not an absolute URL.
-                       $srcVal = $prefix.$srcVal.$suffix;
+       function prefixRelPath($prefix, $srcVal, $suffix = '') {
+                       // Only prefix if it's not an absolute URL or
+                       // only a link to a section within the page.
+               if (substr($srcVal, 0, 1) != '/' && substr($srcVal, 0, 1) != '#') {
+                       $urlParts = parse_url($srcVal);
+                               // only prefix URLs without a scheme
+                       if (!$urlParts['scheme']) {
+                               $srcVal = $prefix . $srcVal . $suffix;
+                       }
                }
                return $srcVal;
        }
                }
                return $srcVal;
        }
@@ -917,26 +1112,31 @@ class t3lib_parsehtml {
         * @param       boolean         If set, keep "color" attribute
         * @return      string          Processed HTML content
         */
         * @param       boolean         If set, keep "color" attribute
         * @return      string          Processed HTML content
         */
-       function cleanFontTags($value,$keepFace=0,$keepSize=0,$keepColor=0)     {
-               $fontSplit = $this->splitIntoBlock('font',$value);      // ,1 ?? - could probably be more stable if splitTags() was used since this depends on end-tags being properly set!
-               reset($fontSplit);
-               while(list($k,$v)=each($fontSplit))     {
-                       if ($k%2)       {       // font:
-                               $attribArray=$this->get_tag_attributes_classic($this->getFirstTag($v));
-                               $newAttribs=array();
-                               if ($keepFace && $attribArray['face'])  $newAttribs[]='face="'.$attribArray['face'].'"';
-                               if ($keepSize && $attribArray['size'])  $newAttribs[]='size="'.$attribArray['size'].'"';
-                               if ($keepColor && $attribArray['color'])        $newAttribs[]='color="'.$attribArray['color'].'"';
-
-                               $innerContent = $this->cleanFontTags($this->removeFirstAndLastTag($v),$keepFace,$keepSize,$keepColor);
-                               if (count($newAttribs)) {
-                                       $fontSplit[$k]='<font '.implode(' ',$newAttribs).'>'.$innerContent.'</font>';
+       function cleanFontTags($value, $keepFace = 0, $keepSize = 0, $keepColor = 0) {
+               $fontSplit = $this->splitIntoBlock('font', $value); // ,1 ?? - could probably be more stable if splitTags() was used since this depends on end-tags being properly set!
+               foreach ($fontSplit as $k => $v) {
+                       if ($k % 2) { // font:
+                               $attribArray = $this->get_tag_attributes_classic($this->getFirstTag($v));
+                               $newAttribs = array();
+                               if ($keepFace && $attribArray['face']) {
+                                       $newAttribs[] = 'face="' . $attribArray['face'] . '"';
+                               }
+                               if ($keepSize && $attribArray['size']) {
+                                       $newAttribs[] = 'size="' . $attribArray['size'] . '"';
+                               }
+                               if ($keepColor && $attribArray['color']) {
+                                       $newAttribs[] = 'color="' . $attribArray['color'] . '"';
+                               }
+
+                               $innerContent = $this->cleanFontTags($this->removeFirstAndLastTag($v), $keepFace, $keepSize, $keepColor);
+                               if (count($newAttribs)) {
+                                       $fontSplit[$k] = '<font ' . implode(' ', $newAttribs) . '>' . $innerContent . '</font>';
                                } else {
                                } else {
-                                       $fontSplit[$k]=$innerContent;
+                                       $fontSplit[$k] = $innerContent;
                                }
                        }
                }
                                }
                        }
                }
-               return implode('',$fontSplit);
+               return implode('', $fontSplit);
        }
 
        /**
        }
 
        /**
@@ -948,12 +1148,10 @@ class t3lib_parsehtml {
         * @param       string          Alternative less-than char to replace with (replace regex string)
         * @return      string          Processed HTML content
         */
         * @param       string          Alternative less-than char to replace with (replace regex string)
         * @return      string          Processed HTML content
         */
-       function mapTags($value,$tags=array(),$ltChar='<',$ltChar2='<') {
+       function mapTags($value, $tags = array(), $ltChar = '<', $ltChar2 = '<') {
 
 
-               foreach($tags as $from => $to)  {
-                       $value = eregi_replace($ltChar.$from.'>',$ltChar2.$to.'>',$value);
-                       $value = eregi_replace($ltChar.$from.'[[:space:]]([^>]*)>',$ltChar2.$to.' \\1>',$value);
-                       $value = eregi_replace($ltChar.'\/'.$from.'[^>]*>',$ltChar2.'/'.$to.'>',$value);
+               foreach ($tags as $from => $to) {
+                       $value = preg_replace('/' . preg_quote($ltChar) . '(\/)?' . $from . '\s([^\>])*(\/)?\>/', $ltChar2 . '$1' . $to . ' $2$3>', $value);
                }
                return $value;
        }
                }
                return $value;
        }
@@ -965,28 +1163,34 @@ class t3lib_parsehtml {
         * @param       string          Tag list, separated by comma. Lowercase!
         * @return      string          Processed HTML content
         */
         * @param       string          Tag list, separated by comma. Lowercase!
         * @return      string          Processed HTML content
         */
-       function unprotectTags($content,$tagList='')    {
-               $tagsArray = t3lib_div::trimExplode(',',$tagList,1);
-               $contentParts = explode('&lt;',$content);
-               next($contentParts);    // bypass the first
-               while(list($k,$tok)=each($contentParts))        {
-                       $firstChar = substr($tok,0,1);
-                       if (strcmp(trim($firstChar),''))        {
-                               $subparts = explode('&gt;',$tok,2);
+       function unprotectTags($content, $tagList = '') {
+               $tagsArray = t3lib_div::trimExplode(',', $tagList, 1);
+               $contentParts = explode('&lt;', $content);
+               next($contentParts); // bypass the first
+               while (list($k, $tok) = each($contentParts)) {
+                       $firstChar = substr($tok, 0, 1);
+                       if (strcmp(trim($firstChar), '')) {
+                               $subparts = explode('&gt;', $tok, 2);
                                $tagEnd = strlen($subparts[0]);
                                $tagEnd = strlen($subparts[0]);
-                               if (strlen($tok)!=$tagEnd)      {
-                                       $endTag = $firstChar=='/' ? 1 : 0;
-                                       $tagContent = substr($tok,$endTag,$tagEnd-$endTag);
-                                       $tagParts = split('[[:space:]]',$tagContent,2);
+                               if (strlen($tok) != $tagEnd) {
+                                       $endTag = $firstChar == '/' ? 1 : 0;
+                                       $tagContent = substr($tok, $endTag, $tagEnd - $endTag);
+                                       $tagParts = preg_split('/\s+/s', $tagContent, 2);
                                        $tagName = strtolower($tagParts[0]);
                                        $tagName = strtolower($tagParts[0]);
-                                       if (!strcmp($tagList,'') || in_array($tagName,$tagsArray))      {
-                                               $contentParts[$k] = '<'.$subparts[0].'>'.$subparts[1];
-                                       } else $contentParts[$k] = '&lt;'.$tok;
-                               } else $contentParts[$k] = '&lt;'.$tok;
-                       } else $contentParts[$k] = '&lt;'.$tok;
+                                       if (!strcmp($tagList, '') || in_array($tagName, $tagsArray)) {
+                                               $contentParts[$k] = '<' . $subparts[0] . '>' . $subparts[1];
+                                       } else {
+                                               $contentParts[$k] = '&lt;' . $tok;
+                                       }
+                               } else {
+                                       $contentParts[$k] = '&lt;' . $tok;
+                               }
+                       } else {
+                               $contentParts[$k] = '&lt;' . $tok;
+                       }
                }
 
                }
 
-               return implode('',$contentParts);
+               return implode('', $contentParts);
        }
 
        /**
        }
 
        /**
@@ -998,17 +1202,17 @@ class t3lib_parsehtml {
         * @return      string          Output value
         * @ignore
         */
         * @return      string          Output value
         * @ignore
         */
-       function stripTagsExcept($value,$tagList)       {
-               $tags=t3lib_div::trimExplode(',',$tagList,1);
-               $forthArr=array();
-               $backArr=array();
-               while(list(,$theTag)=each($tags))       {
-                       $forthArr[$theTag]=md5($theTag);
-                       $backArr[md5($theTag)]=$theTag;
+       function stripTagsExcept($value, $tagList) {
+               $tags = t3lib_div::trimExplode(',', $tagList, 1);
+               $forthArr = array();
+               $backArr = array();
+               foreach ($tags as $theTag) {
+                       $forthArr[$theTag] = md5($theTag);
+                       $backArr[md5($theTag)] = $theTag;
                }
                }
-                       $value = $this->mapTags($value,$forthArr,'<','_');
-                       $value=strip_tags($value);
-                       $value = $this->mapTags($value,$backArr,'_','<');
+               $value = $this->mapTags($value, $forthArr, '<', '_');
+               $value = strip_tags($value);
+               $value = $this->mapTags($value, $backArr, '_', '<');
                return $value;
        }
 
                return $value;
        }
 
@@ -1016,23 +1220,30 @@ class t3lib_parsehtml {
         * Internal function for case shifting of a string or whole array
         *
         * @param       mixed           Input string/array
         * Internal function for case shifting of a string or whole array
         *
         * @param       mixed           Input string/array
-        * @param       boolean         If $str is a string AND this boolean is true, the string is returned in uppercase
+        * @param       boolean         If $str is a string AND this boolean(caseSensitive) is false, the string is returned in uppercase
         * @param       string          Key string used for internal caching of the results. Could be an MD5 hash of the serialized version of the input $str if that is an array.
         * @return      string          Output string, processed
         * @access private
         */
         * @param       string          Key string used for internal caching of the results. Could be an MD5 hash of the serialized version of the input $str if that is an array.
         * @return      string          Output string, processed
         * @access private
         */
-       function caseShift($str,$flag,$cacheKey='')     {
-               if (is_array($str))     {
-                       if (!$cacheKey || !isset($this->caseShift_cache[$cacheKey]))    {
+       function caseShift($str, $flag, $cacheKey = '') {
+               $cacheKey .= $flag ? 1 : 0;
+               if (is_array($str)) {
+                       if (!$cacheKey || !isset($this->caseShift_cache[$cacheKey])) {
                                reset($str);
                                reset($str);
-                               while(list($k)=each($str))      {
-                                       $str[$k] = strtoupper($str[$k]);
+                               foreach ($str as $k => $v) {
+                                       if (!$flag) {
+                                               $str[$k] = strtoupper($v);
+                                       }
+                               }
+                               if ($cacheKey) {
+                                       $this->caseShift_cache[$cacheKey] = $str;
                                }
                                }
-                               if ($cacheKey)  $this->caseShift_cache[$cacheKey]=$str;
                        } else {
                                $str = $this->caseShift_cache[$cacheKey];
                        }
                        } else {
                                $str = $this->caseShift_cache[$cacheKey];
                        }
-               } elseif (!$flag)       $str = strtoupper($str);
+               } elseif (!$flag) {
+                       $str = strtoupper($str);
+               }
                return $str;
        }
 
                return $str;
        }
 
@@ -1045,25 +1256,24 @@ class t3lib_parsehtml {
         * @return      string          Imploded attributes, eg: 'attribute="value" attrib2="value2"'
         * @access private
         */
         * @return      string          Imploded attributes, eg: 'attribute="value" attrib2="value2"'
         * @access private
         */
-       function compileTagAttribs($tagAttrib,$meta=array(), $xhtmlClean=0)     {
-               $accu=array();
-               reset($tagAttrib);
-               while(list($k,$v)=each($tagAttrib))     {
-                       if ($xhtmlClean)        {
-                               $attr=strtolower($k);
-                               if (strcmp($v,'') || isset($meta[$k]['dashType']))      {
-                                       $attr.='="'.htmlspecialchars($v).'"';
+       function compileTagAttribs($tagAttrib, $meta = array(), $xhtmlClean = 0) {
+               $accu = array();
+               foreach ($tagAttrib as $k => $v) {
+                       if ($xhtmlClean) {
+                               $attr = strtolower($k);
+                               if (strcmp($v, '') || isset($meta[$k]['dashType'])) {
+                                       $attr .= '="' . htmlspecialchars($v) . '"';
                                }
                        } else {
                                }
                        } else {
-                               $attr=$meta[$k]['origTag']?$meta[$k]['origTag']:$k;
-                               if (strcmp($v,'') || isset($meta[$k]['dashType']))      {
-                                       $dash=$meta[$k]['dashType']?$meta[$k]['dashType']:(t3lib_div::testInt($v)?'':'"');
-                                       $attr.='='.$dash.$v.$dash;
+                               $attr = $meta[$k]['origTag'] ? $meta[$k]['origTag'] : $k;
+                               if (strcmp($v, '') || isset($meta[$k]['dashType'])) {
+                                       $dash = $meta[$k]['dashType'] ? $meta[$k]['dashType'] : (t3lib_div::testInt($v) ? '' : '"');
+                                       $attr .= '=' . $dash . $v . $dash;
                                }
                        }
                                }
                        }
-                       $accu[]=$attr;
+                       $accu[] = $attr;
                }
                }
-               return implode(' ',$accu);
+               return implode(' ', $accu);
        }
 
        /**
        }
 
        /**
@@ -1074,9 +1284,9 @@ class t3lib_parsehtml {
         * @return      array
         * @access private
         */
         * @return      array
         * @access private
         */
-       function get_tag_attributes_classic($tag,$deHSC=0)      {
-               $attr=$this->get_tag_attributes($tag,$deHSC);
-               return is_array($attr[0])?$attr[0]:array();
+       function get_tag_attributes_classic($tag, $deHSC = 0) {
+               $attr = $this->get_tag_attributes($tag, $deHSC);
+               return is_array($attr[0]) ? $attr[0] : array();
        }
 
        /**
        }
 
        /**
@@ -1087,13 +1297,13 @@ class t3lib_parsehtml {
         * @param       string          Indent character/string
         * @return      string          Indented code (typ. HTML)
         */
         * @param       string          Indent character/string
         * @return      string          Indented code (typ. HTML)
         */
-       function indentLines($content, $number=1, $indentChar="\t")     {
-               $preTab = str_pad('', $number*strlen($indentChar), $indentChar);
-               $lines = explode(chr(10),str_replace(chr(13),'',$content));
-               while(list($k,$v) = each($lines))       {
-                       $lines[$k] = $preTab.$v;
+       function indentLines($content, $number = 1, $indentChar = TAB) {
+               $preTab = str_pad('', $number * strlen($indentChar), $indentChar);
+               $lines = explode(LF, str_replace(CR, '', $content));
+               foreach ($lines as $k => $v) {
+                       $lines[$k] = $preTab . $v;
                }
                }
-               return implode(chr(10), $lines);
+               return implode(LF, $lines);
        }
 
        /**
        }
 
        /**
@@ -1104,100 +1314,113 @@ class t3lib_parsehtml {
         * @return      array
         * @access private
         */
         * @return      array
         * @access private
         */
-       function HTMLparserConfig($TSconfig,$keepTags=array())  {
+       function HTMLparserConfig($TSconfig, $keepTags = array()) {
                        // Allow tags (base list, merged with incoming array)
                        // Allow tags (base list, merged with incoming array)
-               $alTags = array_flip(t3lib_div::trimExplode(',',strtolower($TSconfig['allowTags']),1));
-               $keepTags = array_merge($alTags,$keepTags);
+               $alTags = array_flip(t3lib_div::trimExplode(',', strtolower($TSconfig['allowTags']), 1));
+               $keepTags = array_merge($alTags, $keepTags);
 
                        // Set config properties.
 
                        // Set config properties.
-               if (is_array($TSconfig['tags.']))       {
-                       reset($TSconfig['tags.']);
-                       while(list($key,$tagC)=each($TSconfig['tags.']))        {
-                               if (!is_array($tagC) && $key==strtolower($key)) {
-                                       if (!strcmp($tagC,'0')) unset($keepTags[$key]);
-                                       if (!strcmp($tagC,'1') && !isset($keepTags[$key]))      $keepTags[$key]=1;
+               if (is_array($TSconfig['tags.'])) {
+                       foreach ($TSconfig['tags.'] as $key => $tagC) {
+                               if (!is_array($tagC) && $key == strtolower($key)) {
+                                       if (!strcmp($tagC, '0')) {
+                                               unset($keepTags[$key]);
+                                       }
+                                       if (!strcmp($tagC, '1') && !isset($keepTags[$key])) {
+                                               $keepTags[$key] = 1;
+                                       }
                                }
                        }
 
                                }
                        }
 
-                       reset($TSconfig['tags.']);
-                       while(list($key,$tagC)=each($TSconfig['tags.']))        {
-                               if (is_array($tagC) && $key==strtolower($key))  {
-                                       $key=substr($key,0,-1);
-                                       if (!is_array($keepTags[$key])) $keepTags[$key]=array();
-                                       if (is_array($tagC['fixAttrib.']))      {
-                                               reset($tagC['fixAttrib.']);
-                                               while(list($atName,$atConfig)=each($tagC['fixAttrib.']))        {
-                                                       if (is_array($atConfig))        {
-                                                               $atName=substr($atName,0,-1);
-                                                               if (!is_array($keepTags[$key]['fixAttrib'][$atName]))   {
-                                                                       $keepTags[$key]['fixAttrib'][$atName]=array();
+                       foreach ($TSconfig['tags.'] as $key => $tagC) {
+                               if (is_array($tagC) && $key == strtolower($key)) {
+                                       $key = substr($key, 0, -1);
+                                       if (!is_array($keepTags[$key])) {
+                                               $keepTags[$key] = array();
+                                       }
+                                       if (is_array($tagC['fixAttrib.'])) {
+                                               foreach ($tagC['fixAttrib.'] as $atName => $atConfig) {
+                                                       if (is_array($atConfig)) {
+                                                               $atName = substr($atName, 0, -1);
+                                                               if (!is_array($keepTags[$key]['fixAttrib'][$atName])) {
+                                                                       $keepTags[$key]['fixAttrib'][$atName] = array();
+                                                               }
+                                                               $keepTags[$key]['fixAttrib'][$atName] = array_merge($keepTags[$key]['fixAttrib'][$atName], $atConfig); // Candidate for t3lib_div::array_merge() if integer-keys will some day make trouble...
+                                                               if (strcmp($keepTags[$key]['fixAttrib'][$atName]['range'], '')) {
+                                                                       $keepTags[$key]['fixAttrib'][$atName]['range'] = t3lib_div::trimExplode(',', $keepTags[$key]['fixAttrib'][$atName]['range']);
+                                                               }
+                                                               if (strcmp($keepTags[$key]['fixAttrib'][$atName]['list'], '')) {
+                                                                       $keepTags[$key]['fixAttrib'][$atName]['list'] = t3lib_div::trimExplode(',', $keepTags[$key]['fixAttrib'][$atName]['list']);
                                                                }
                                                                }
-                                                               $keepTags[$key]['fixAttrib'][$atName] = array_merge($keepTags[$key]['fixAttrib'][$atName],$atConfig);           // Candidate for t3lib_div::array_merge() if integer-keys will some day make trouble...
-                                                               if (strcmp($keepTags[$key]['fixAttrib'][$atName]['range'],''))  $keepTags[$key]['fixAttrib'][$atName]['range'] = t3lib_div::trimExplode(',',$keepTags[$key]['fixAttrib'][$atName]['range']);
-                                                               if (strcmp($keepTags[$key]['fixAttrib'][$atName]['list'],''))   $keepTags[$key]['fixAttrib'][$atName]['list'] = t3lib_div::trimExplode(',',$keepTags[$key]['fixAttrib'][$atName]['list']);
                                                        }
                                                }
                                        }
                                        unset($tagC['fixAttrib.']);
                                        unset($tagC['fixAttrib']);
                                                        }
                                                }
                                        }
                                        unset($tagC['fixAttrib.']);
                                        unset($tagC['fixAttrib']);
-                                       $keepTags[$key] = array_merge($keepTags[$key],$tagC);                   // Candidate for t3lib_div::array_merge() if integer-keys will some day make trouble...
+                                       $keepTags[$key] = array_merge($keepTags[$key], $tagC); // Candidate for t3lib_div::array_merge() if integer-keys will some day make trouble...
                                }
                        }
                }
                        // localNesting
                                }
                        }
                }
                        // localNesting
-               if ($TSconfig['localNesting'])  {
-                       $lN = t3lib_div::trimExplode(',',strtolower($TSconfig['localNesting']),1);
-                       while(list(,$tn)=each($lN))     {
-                               if (isset($keepTags[$tn]))      {
-                                       $keepTags[$tn]['nesting']=1;
+               if ($TSconfig['localNesting']) {
+                       $lN = t3lib_div::trimExplode(',', strtolower($TSconfig['localNesting']), 1);
+                       foreach ($lN as $tn) {
+                               if (isset($keepTags[$tn])) {
+                                       $keepTags[$tn]['nesting'] = 1;
                                }
                        }
                }
                                }
                        }
                }
-               if ($TSconfig['globalNesting']) {
-                       $lN = t3lib_div::trimExplode(',',strtolower($TSconfig['globalNesting']),1);
-                       while(list(,$tn)=each($lN))     {
-                               if (isset($keepTags[$tn]))      {
-                                       if (!is_array($keepTags[$tn]))  $keepTags[$tn]=array();
-                                       $keepTags[$tn]['nesting']='global';
+               if ($TSconfig['globalNesting']) {
+                       $lN = t3lib_div::trimExplode(',', strtolower($TSconfig['globalNesting']), 1);
+                       foreach ($lN as $tn) {
+                               if (isset($keepTags[$tn])) {
+                                       if (!is_array($keepTags[$tn])) {
+                                               $keepTags[$tn] = array();
+                                       }
+                                       $keepTags[$tn]['nesting'] = 'global';
                                }
                        }
                }
                                }
                        }
                }
-               if ($TSconfig['rmTagIfNoAttrib'])       {
-                       $lN = t3lib_div::trimExplode(',',strtolower($TSconfig['rmTagIfNoAttrib']),1);
-                       while(list(,$tn)=each($lN))     {
-                               if (isset($keepTags[$tn]))      {
-                                       if (!is_array($keepTags[$tn]))  $keepTags[$tn]=array();
-                                       $keepTags[$tn]['rmTagIfNoAttrib']=1;
+               if ($TSconfig['rmTagIfNoAttrib']) {
+                       $lN = t3lib_div::trimExplode(',', strtolower($TSconfig['rmTagIfNoAttrib']), 1);
+                       foreach ($lN as $tn) {
+                               if (isset($keepTags[$tn])) {
+                                       if (!is_array($keepTags[$tn])) {
+                                               $keepTags[$tn] = array();
+                                       }
+                                       $keepTags[$tn]['rmTagIfNoAttrib'] = 1;
                                }
                        }
                }
                                }
                        }
                }
-               if ($TSconfig['noAttrib'])      {
-                       $lN = t3lib_div::trimExplode(',',strtolower($TSconfig['noAttrib']),1);
-                       while(list(,$tn)=each($lN))     {
-                               if (isset($keepTags[$tn]))      {
-                                       if (!is_array($keepTags[$tn]))  $keepTags[$tn]=array();
-                                       $keepTags[$tn]['allowedAttribs']=0;
+               if ($TSconfig['noAttrib']) {
+                       $lN = t3lib_div::trimExplode(',', strtolower($TSconfig['noAttrib']), 1);
+                       foreach ($lN as $tn) {
+                               if (isset($keepTags[$tn])) {
+                                       if (!is_array($keepTags[$tn])) {
+                                               $keepTags[$tn] = array();
+                                       }
+                                       $keepTags[$tn]['allowedAttribs'] = 0;
                                }
                        }
                }
                                }
                        }
                }
-               if ($TSconfig['removeTags'])    {
-                       $lN = t3lib_div::trimExplode(',',strtolower($TSconfig['removeTags']),1);
-                       while(list(,$tn)=each($lN))     {
-                               $keepTags[$tn]=array();
-                               $keepTags[$tn]['allowedAttribs']=0;
-                               $keepTags[$tn]['rmTagIfNoAttrib']=1;
+               if ($TSconfig['removeTags']) {
+                       $lN = t3lib_div::trimExplode(',', strtolower($TSconfig['removeTags']), 1);
+                       foreach ($lN as $tn) {
+                               $keepTags[$tn] = array();
+                               $keepTags[$tn]['allowedAttribs'] = 0;
+                               $keepTags[$tn]['rmTagIfNoAttrib'] = 1;
                        }
                }
 
                        // Create additional configuration:
                        }
                }
 
                        // Create additional configuration:
-               $addConfig=array();
-               if ($TSconfig['xhtml_cleaning'])        {
-                       $addConfig['xhtml']=1;
+               $addConfig = array();
+               if ($TSconfig['xhtml_cleaning']) {
+                       $addConfig['xhtml'] = 1;
                }
 
                return array(
                        $keepTags,
                }
 
                return array(
                        $keepTags,
-                       ''.$TSconfig['keepNonMatchedTags'],
+                       '' . $TSconfig['keepNonMatchedTags'],
                        intval($TSconfig['htmlSpecialChars']),
                        $addConfig
                );
                        intval($TSconfig['htmlSpecialChars']),
                        $addConfig
                );
@@ -1207,33 +1430,33 @@ class t3lib_parsehtml {
         * Tries to convert the content to be XHTML compliant and other stuff like that.
         * STILL EXPERIMENTAL. See comments below.
         *
         * Tries to convert the content to be XHTML compliant and other stuff like that.
         * STILL EXPERIMENTAL. See comments below.
         *
-        *                      What it does NOT do (yet) according to XHTML specs.:
-        *                      - Wellformedness: Nesting is NOT checked
-        *                      - name/id attribute issue is not observed at this point.
-        *                      - Certain nesting of elements not allowed. Most interesting, <PRE> cannot contain img, big,small,sub,sup ...
-        *                      - Wrapping scripts and style element contents in CDATA - or alternatively they should have entitites converted.
-        *                      - Setting charsets may put some special requirements on both XML declaration/ meta-http-equiv. (C.9)
-        *                      - UTF-8 encoding is in fact expected by XML!!
-        *                      - stylesheet element and attribute names are NOT converted to lowercase
-        *                      - ampersands (and entities in general I think) MUST be converted to an entity reference! (&amps;). This may mean further conversion of non-tag content before output to page. May be related to the charset issue as a whole.
-        *                      - Minimized values not allowed: Must do this: selected="selected"
+        *                       What it does NOT do (yet) according to XHTML specs.:
+        *                       - Wellformedness: Nesting is NOT checked
+        *                       - name/id attribute issue is not observed at this point.
+        *                       - Certain nesting of elements not allowed. Most interesting, <PRE> cannot contain img, big,small,sub,sup ...
+        *                       - Wrapping scripts and style element contents in CDATA - or alternatively they should have entitites converted.
+        *                       - Setting charsets may put some special requirements on both XML declaration/ meta-http-equiv. (C.9)
+        *                       - UTF-8 encoding is in fact expected by XML!!
+        *                       - stylesheet element and attribute names are NOT converted to lowercase
+        *                       - ampersands (and entities in general I think) MUST be converted to an entity reference! (&amps;). This may mean further conversion of non-tag content before output to page. May be related to the charset issue as a whole.
+        *                       - Minimized values not allowed: Must do this: selected="selected"
         *
         *
-        *                      What it does at this point:
-        *                      - All tags (frame,base,meta,link + img,br,hr,area,input) is ended with "/>" - others?
-        *                      - Lowercase for elements and attributes
-        *                      - All attributes in quotes
-        *                      - Add "alt" attribute to img-tags if it's not there already.
+        *                       What it does at this point:
+        *                       - All tags (frame,base,meta,link + img,br,hr,area,input) is ended with "/>" - others?
+        *                       - Lowercase for elements and attributes
+        *                       - All attributes in quotes
+        *                       - Add "alt" attribute to img-tags if it's not there already.
         *
         * @param       string          Content to clean up
         * @return      string          Cleaned up content returned.
         * @access private
         */
         *
         * @param       string          Content to clean up
         * @return      string          Cleaned up content returned.
         * @access private
         */
-       function XHTML_clean($content)  {
+       function XHTML_clean($content) {
                $content = $this->HTMLcleaner(
                        $content,
                $content = $this->HTMLcleaner(
                        $content,
-                       array(),        // No tags treated specially
-                       1,                      // Keep ALL tags.
-                       0,                      // All content is htmlspecialchar()'ed (or ??) - if we do, <script> content will break...
+                       array(), // No tags treated specially
+                       1, // Keep ALL tags.
+                       0, // All content is htmlspecialchar()'ed (or ??) - if we do, <script> content will break...
                        array('xhtml' => 1)
                );
                return $content;
                        array('xhtml' => 1)
                );
                return $content;
@@ -1250,35 +1473,40 @@ class t3lib_parsehtml {
         * @return      string          Processed value.
         * @access private
         */
         * @return      string          Processed value.
         * @access private
         */
-       function processTag($value,$conf,$endTag,$protected=0)  {
+       function processTag($value, $conf, $endTag, $protected = 0) {
                        // Return immediately if protected or no parameters
                        // Return immediately if protected or no parameters
-               if ($protected || !count($conf))        return $value;
+               if ($protected || !count($conf)) {
+                       return $value;
+               }
                        // OK then, begin processing for XHTML output:
                        // STILL VERY EXPERIMENTAL!!
                        // OK then, begin processing for XHTML output:
                        // STILL VERY EXPERIMENTAL!!
-               if ($conf['xhtml'])     {
-                       if ($endTag)    {       // Endtags are just set lowercase right away
+               if ($conf['xhtml']) {
+                       if ($endTag) { // Endtags are just set lowercase right away
                                $value = strtolower($value);
                                $value = strtolower($value);
-                       } elseif (substr($value,0,2)!='<!') {   // ... and comments are ignored.
-                               $inValue = substr($value,1,(substr($value,-2)=='/>'?-2:-1));    // Finding inner value with out < >
-                               list($tagName,$tagP)=split('[[:space:]]',$inValue,2);   // Separate attributes and tagname
+                       } elseif (substr($value, 0, 4) != '<!--') { // ... and comments are ignored.
+                               $inValue = substr($value, 1, (substr($value, -2) == '/>' ? -2 : -1)); // Finding inner value with out < >
+                               list($tagName, $tagP) = preg_split('/\s+/s', $inValue, 2); // Separate attributes and tagname
                                $tagName = strtolower($tagName);
 
                                $tagName = strtolower($tagName);
 
-                                       // Process attributes
+                               // Process attributes
                                $tagAttrib = $this->get_tag_attributes($tagP);
                                $tagAttrib = $this->get_tag_attributes($tagP);
-                               if (!strcmp($tagName,'img') && !isset($tagAttrib[0]['alt']))            $tagAttrib[0]['alt']='';        // Set alt attribute for all images (not XHTML though...)
-                               if (!strcmp($tagName,'script') && !isset($tagAttrib[0]['type']))        $tagAttrib[0]['type']='text/javascript';        // Set type attribute for all script-tags
-                               $outA=array();
-                               reset($tagAttrib[0]);
-                               while(list($attrib_name,$attrib_value)=each($tagAttrib[0]))     {
+                               if (!strcmp($tagName, 'img') && !isset($tagAttrib[0]['alt'])) {
+                                       $tagAttrib[0]['alt'] = '';
+                               } // Set alt attribute for all images (not XHTML though...)
+                               if (!strcmp($tagName, 'script') && !isset($tagAttrib[0]['type'])) {
+                                       $tagAttrib[0]['type'] = 'text/javascript';
+                               } // Set type attribute for all script-tags
+                               $outA = array();
+                               foreach ($tagAttrib[0] as $attrib_name => $attrib_value) {
                                                // Set attributes: lowercase, always in quotes, with htmlspecialchars converted.
                                                // Set attributes: lowercase, always in quotes, with htmlspecialchars converted.
-                                       $outA[]=$attrib_name.'="'.$this->bidir_htmlspecialchars($attrib_value,2).'"';
+                                       $outA[] = $attrib_name . '="' . $this->bidir_htmlspecialchars($attrib_value, 2) . '"';
                                }
                                }
-                               $newTag='<'.trim($tagName.' '.implode(' ',$outA));
+                               $newTag = '<' . trim($tagName . ' ' . implode(' ', $outA));
                                        // All tags that are standalone (not wrapping, not having endtags) should be ended with '/>'
                                        // All tags that are standalone (not wrapping, not having endtags) should be ended with '/>'
-                               if (t3lib_div::inList('img,br,hr,meta,link,base,area,input,param,col',$tagName) || substr($value,-2)=='/>')     {
-                                       $newTag.=' />';
+                               if (t3lib_div::inList('img,br,hr,meta,link,base,area,input,param,col', $tagName) || substr($value, -2) == '/>') {
+                                       $newTag .= ' />';
                                } else {
                                } else {
-                                       $newTag.='>';
+                                       $newTag .= '>';
                                }
                                $value = $newTag;
                        }
                                }
                                $value = $newTag;
                        }
@@ -1296,15 +1524,17 @@ class t3lib_parsehtml {
         * @return      string          The processed value.
         * @access private
         */
         * @return      string          The processed value.
         * @access private
         */
-       function processContent($value,$dir,$conf)      {
-               if ($dir!=0)    $value = $this->bidir_htmlspecialchars($value,$dir);
+       function processContent($value, $dir, $conf) {
+               if ($dir != 0) {
+                       $value = $this->bidir_htmlspecialchars($value, $dir);
+               }
                return $value;
        }
 }
 
 
                return $value;
        }
 }
 
 
-
-if (defined('TYPO3_MODE') && $TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['t3lib/class.t3lib_parsehtml.php'])        {
-       include_once($TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['t3lib/class.t3lib_parsehtml.php']);
+if (defined('TYPO3_MODE') && isset($GLOBALS['TYPO3_CONF_VARS'][TYPO3_MODE]['XCLASS']['t3lib/class.t3lib_parsehtml.php'])) {
+       include_once($GLOBALS['TYPO3_CONF_VARS'][TYPO3_MODE]['XCLASS']['t3lib/class.t3lib_parsehtml.php']);
 }
 }
-?>
+
+?>
\ No newline at end of file