Added argument to debugRows() so it can return HTML instead of echo'ing
[Packages/TYPO3.CMS.git] / t3lib / class.t3lib_div.php
index 60d584d..bfa3888 100755 (executable)
@@ -2,7 +2,7 @@
 /***************************************************************
 *  Copyright notice
 *
-*  (c) 1999-2006 Kasper Skaarhoj (kasperYYYY@typo3.com)
+*  (c) 1999-2007 Kasper Skaarhoj (kasperYYYY@typo3.com)
 *  All rights reserved
 *
 *  This script is part of the TYPO3 project. The TYPO3 project is
@@ -487,13 +487,13 @@ class t3lib_div {
         * Truncate string
         * Returns a new string of max. $chars length.
         * If the string is longer, it will be truncated and appended with '...'.
-        * DEPRECATED. Works ONLY for single-byte charsets! USE t3lib_div::fixed_lgd_cs() instead
         * Usage: 39
         *
         * @param       string          string to truncate
         * @param       integer         must be an integer with an absolute value of at least 4. if negative the string is cropped from the right end.
         * @param       string          String to append to the output if it is truncated, default is '...'
         * @return      string          new string
+        * @deprecated          Works ONLY for single-byte charsets! USE t3lib_div::fixed_lgd_cs() instead
         * @see fixed_lgd_pre()
         */
        function fixed_lgd($string,$origChars,$preStr='...')    {
@@ -513,12 +513,12 @@ class t3lib_div {
         * Returns a new string of max. $chars length.
         * If the string is longer, it will be truncated and prepended with '...'.
         * This works like fixed_lgd, but is truncated in the start of the string instead of the end
-        * DEPRECATED. Use either fixed_lgd() or fixed_lgd_cs() (with negative input value for $chars)
         * Usage: 6
         *
         * @param       string          string to truncate
         * @param       integer         must be an integer of at least 4
         * @return      string          new string
+        * @deprecated          Use either fixed_lgd() or fixed_lgd_cs() (with negative input value for $chars)
         * @see fixed_lgd()
         */
        function fixed_lgd_pre($string,$chars)  {
@@ -550,13 +550,14 @@ class t3lib_div {
         * @param       string          The string to break up
         * @param       string          The string to implode the broken lines with (default/typically \n)
         * @param       integer         The line length
+        * @deprecated          Use PHP function wordwrap()
         * @return      string
         */
        function breakTextForEmail($str,$implChar="\n",$charWidth=76)   {
                $lines = explode(chr(10),$str);
                $outArr=array();
                while(list(,$lStr)=each($lines))        {
-                       $outArr = array_merge($outArr,t3lib_div::breakLinesForEmail($lStr,$implChar,$charWidth));
+                       $outArr[] = t3lib_div::breakLinesForEmail($lStr,$implChar,$charWidth);
                }
                return implode(chr(10),$outArr);
        }
@@ -1082,11 +1083,11 @@ class t3lib_div {
 
        /**
         * strtoupper which converts danish (and other characters) characters as well
-        * (DEPRECATED, use t3lib_cs::conv_case() instead or for HTML output, wrap your content in <span class="uppercase">...</span>)
         * Usage: 0
         *
         * @param       string          String to process
         * @return      string
+        * @deprecated          Use t3lib_cs::conv_case() instead or for HTML output, wrap your content in <span class="uppercase">...</span>)
         * @ignore
         */
        function danish_strtoupper($string)     {
@@ -1097,11 +1098,11 @@ class t3lib_div {
        /**
         * Change umlaut characters to plain ASCII with normally two character target
         * Only known characters will be converted, so don't expect a result for any character.
-        * (DEPRECATED: Works only for western europe single-byte charsets! Use t3lib_cs::specCharsToASCII() instead!)
         *
         * ä => ae, Ö => Oe
         *
         * @param       string          String to convert.
+        * @deprecated          Works only for western europe single-byte charsets! Use t3lib_cs::specCharsToASCII() instead!
         * @return      string
         */
        function convUmlauts($str)      {
@@ -1463,13 +1464,12 @@ class t3lib_div {
 
        /**
         * Remove duplicate values from an array
-        * This function is deprecated, use the PHP function array_unique instead
         * Usage: 0
         *
         * @param       array           Array of values to make unique
         * @return      array
         * @ignore
-        * @deprecated
+        * @deprecated          Use the PHP function array_unique instead
         */
        function uniqueArray($valueArray)       {
                return array_unique($valueArray);
@@ -1646,7 +1646,7 @@ class t3lib_div {
         * @param       array           First array
         * @param       array           Second array, overruling the first array
         * @param       boolean         If set, keys that are NOT found in $arr0 (first array) will not be set. Thus only existing value can/will be overruled from second array.
-        * @param       boolean         If set, values from $arr1 will overrule if they are empty. Default: true
+        * @param       boolean         If set, values from $arr1 will overrule if they are empty or zero. Default: true
         * @return      array           Resulting array where $arr1 values has overruled $arr0 values
         */
        function array_merge_recursive_overrule($arr0,$arr1,$notAddKeys=0,$includeEmtpyValues=true) {
@@ -1654,17 +1654,17 @@ class t3lib_div {
                while(list($key,$val) = each($arr1)) {
                        if(is_array($arr0[$key])) {
                                if (is_array($arr1[$key]))      {
-                                       $arr0[$key] = t3lib_div::array_merge_recursive_overrule($arr0[$key],$arr1[$key],$notAddKeys);
+                                       $arr0[$key] = t3lib_div::array_merge_recursive_overrule($arr0[$key],$arr1[$key],$notAddKeys,$includeEmtpyValues);
                                }
                        } else {
                                if ($notAddKeys) {
                                        if (isset($arr0[$key])) {
-                                               if ($includeEmtpyValues OR $val) {
+                                               if ($includeEmtpyValues || $val) {
                                                        $arr0[$key] = $val;
                                                }
                                        }
                                } else {
-                                       if ($includeEmtpyValues OR $val) {
+                                       if ($includeEmtpyValues || $val) {
                                                $arr0[$key] = $val;
                                        }
                                }
@@ -1698,15 +1698,35 @@ class t3lib_div {
        function csvValues($row,$delim=',',$quote='"')  {
                reset($row);
                $out=array();
-               while(list(,$value)=each($row)) {
-                       list($valPart) = explode(chr(10),$value);
-                       $valPart = trim($valPart);
-                       $out[]=str_replace($quote,$quote.$quote,$valPart);
+               foreach ($row as $value) {
+                       $out[] = str_replace($quote, $quote.$quote, $value);
                }
                $str = $quote.implode($quote.$delim.$quote,$out).$quote;
                return $str;
        }
 
+       /**
+        * Removes dots "." from end of a key identifier of TypoScript styled array.
+        * array('key.' => array('property.' => 'value')) --> array('key' => array('property' => 'value'))
+        *
+        * @param       array   $ts: TypoScript configuration array
+        * @return      array   TypoScript configuration array without dots at the end of all keys
+        */
+       function removeDotsFromTS($ts) {
+               $out = array();
+               if (is_array($ts)) {
+                       foreach ($ts as $key => $value) {
+                               if (is_array($value)) {
+                                       $key = rtrim($key, '.');
+                                       $out[$key] = t3lib_div::removeDotsFromTS($value);
+                               } else {
+                                       $out[$key] = $value;
+                               }
+                       }
+               }
+               return $out;
+       }
+
 
 
 
@@ -1992,7 +2012,7 @@ class t3lib_div {
         * @param       string          tag-prefix, eg. a namespace prefix like "T3:"
         * @param       integer         Current recursion level. Don't change, stay at zero!
         * @param       string          Alternative document tag. Default is "phparray".
-        * @param       integer         If greater then zero, than number of spaces corresponding to this number is used for indenting, if less than zero - no indentation, if zero - a single chr(9) (TAB) is used
+        * @param       integer         If greater than zero, then the number of spaces corresponding to this number is used for indenting, if less than zero - no indentation, if zero - a single chr(9) (TAB) is used
         * @param       array           Options for the compilation. Key "useNindex" => 0/1 (boolean: whether to use "n0, n1, n2" for num. indexes); Key "useIndexTagForNum" => "[tag for numerical indexes]"; Key "useIndexTagForAssoc" => "[tag for associative indexes"; Key "parentTagMap" => array('parentTag' => 'thisLevelTag')
         * @param       string          Stack data. Don't touch.
         * @return      string          An XML string made from the input content in the array.
@@ -2079,7 +2099,8 @@ class t3lib_div {
                                } else {        // Just a value:
 
                                                // Look for binary chars:
-                                       if (strcspn($v,$binaryChars) != strlen($v))     {       // Go for base64 encoding if the initial segment NOT matching any binary char has the same length as the whole string!
+                                       $vLen = strlen($v);     // check for length, because PHP 5.2.0 may crash when first argument of strcspn is empty
+                                       if ($vLen && strcspn($v,$binaryChars) != $vLen) {       // Go for base64 encoding if the initial segment NOT matching any binary char has the same length as the whole string!
                                                        // If the value contained binary chars then we base64-encode it an set an attribute to notify this situation:
                                                $content = $nl.chunk_split(base64_encode($v));
                                                $attr.=' base64="1"';
@@ -2087,7 +2108,13 @@ class t3lib_div {
                                                        // Otherwise, just htmlspecialchar the stuff:
                                                $content = htmlspecialchars($v);
                                                $dType = gettype($v);
-                                               if ($dType!='string' && !$options['disableTypeAttrib']) { $attr.=' type="'.$dType.'"'; }
+                                               if ($dType == 'string') {
+                                                       if ($options['useCDATA'] && $content != $v) {
+                                                               $content = '<![CDATA[' . $v . ']]>';
+                                                       }
+                                               } elseif (!$options['disableTypeAttrib']) {
+                                                       $attr.= ' type="'.$dType.'"';
+                                               }
                                        }
                                }
 
@@ -2129,14 +2156,18 @@ class t3lib_div {
                xml_parser_set_option($parser, XML_OPTION_CASE_FOLDING, 0);
                xml_parser_set_option($parser, XML_OPTION_SKIP_WHITE, 0);
 
-                       // PHP5 fix of charset awareness:
-                       // Problem is: PHP5 apparently detects the charset of the XML file (or defaults to utf-8) and will AUTOMATICALLY convert the content to either utf-8, iso-8859-1 or us-ascii. PHP4 just passed the content through without taking action regarding the charset.
-                       // In TYPO3 we expect that the charset of XML content is NOT handled in the parser but internally in TYPO3 instead. Therefore it would be very nice if PHP5 could be configured to NOT process the charset of the files. But this is not possible for now.
-                       // What we do here fixes the problem but ONLY if the charset is utf-8, iso-8859-1 or us-ascii. That should work for most TYPO3 installations, in particular if people use utf-8 which we highly recommend.
-               if ((double)phpversion()>=5)    {
-                       $ereg_result = array();
-                       ereg('^[[:space:]]*<\?xml[^>]*encoding[[:space:]]*=[[:space:]]*"([^"]*)"',substr($string,0,200),$ereg_result);
-                       $theCharset = $ereg_result[1] ? $ereg_result[1] : ($TYPO3_CONF_VARS['BE']['forceCharset'] ? $TYPO3_CONF_VARS['BE']['forceCharset'] : 'iso-8859-1');
+                       //  PHP4 doesn't like Unicode byte order marks (BOM), so we have to check for them
+                       // The BOM check comes first, so that the PHP5 preg_match() below doesn't have to check for it
+               if(substr($string,0,3)=="\xEF\xBB\xBF") {
+                       xml_parser_set_option($parser, XML_OPTION_TARGET_ENCODING, 'utf-8');
+               }
+                       // PHP 4.x: output charset is the same as the input charset, charsets are handled transparently if not specified in xml_parser_create()
+                       // PHP 5.0.0 & 5.0.1: default output charset is ISO-8859-1, only ASCII, ISO-8859-1 and UTF-8 are supported!!!
+                       // PHP 5.0.2+: default output charset is UTF-8  , only ASCII, ISO-8859-1 and UTF-8 are supported!!!
+               elseif ((double)phpversion()>=5)        {
+                       $match = array();
+                       preg_match('/^[[:space:]]*<\?xml[^>]*encoding[[:space:]]*=[[:space:]]*"([^"]*)"/',substr($string,0,200),$match);
+                       $theCharset = $match[1] ? $match[1] : ($TYPO3_CONF_VARS['BE']['forceCharset'] ? $TYPO3_CONF_VARS['BE']['forceCharset'] : 'iso-8859-1');
                        xml_parser_set_option($parser, XML_OPTION_TARGET_ENCODING, $theCharset);  // us-ascii / utf-8 / iso-8859-1
                }
 
@@ -2366,36 +2397,27 @@ class t3lib_div {
                        }
                        fclose($fp);
 
-               } elseif (is_array($requestHeaders) && function_exists('stream_context_create'))        {
-
+               } elseif (is_array($requestHeaders))    {
                        $ctx = stream_context_create(array(
                                                'http' => array(
                                                        'header' => implode("\r\n", $requestHeaders)
                                                )
                                        )
                                );
-
-                       if (function_exists('file_get_contents') && version_compare(phpversion(), '5.0', '>=')) {
+                       if (version_compare(phpversion(), '5.0', '>=')) {
                                $content = @file_get_contents($url, false, $ctx);
                        }
                        elseif (false !== ($fd = @fopen($url, 'rb', false, $ctx)))      {
                                $content = '';
                                while (!feof($fd))      {
-                                       $content .= fread($fd, 4096);
+                                       $content.= @fread($fd, 4096);
                                }
                                fclose($fd);
                        }
                }
-               elseif (function_exists('file_get_contents'))   {
+               else    {
                        $content = @file_get_contents($url);
                }
-               elseif (false !== ($fd = @fopen($url, 'rb')))   {
-                       $content = '';
-                       while (!feof($fd))      {
-                               $content .= fread($fd, 4096);
-                       }
-                       fclose($fd);
-               }
 
                return $content;
        }
@@ -2527,6 +2549,40 @@ class t3lib_div {
        }
 
        /**
+        * Wrapper function for rmdir, allowing recursive deletion of folders and files
+        *
+        * @param       string          Absolute path to folder, see PHP rmdir() function. Removes trailing slash internally.
+        * @param       boolean         Allow deletion of non-empty directories
+        * @return      boolean         true if @rmdir went well!
+        */
+       function rmdir($path,$removeNonEmpty=false)     {
+               $OK = false;
+               $path = preg_replace('|/$|','',$path);  // Remove trailing slash
+
+               if (file_exists($path)) {
+                       $OK = true;
+
+                       if (is_dir($path))      {
+                               if ($removeNonEmpty==true && $handle = opendir($path))  {
+                                       while ($OK && false !== ($file = readdir($handle)))     {
+                                               if ($file=='.' || $file=='..') continue;
+                                               $OK = t3lib_div::rmdir($path.'/'.$file,$removeNonEmpty);
+                                       }
+                                       closedir($handle);
+                               }
+                               if ($OK)        { $OK = rmdir($path); }
+
+                       } else {        // If $dirname is a file, simply remove it
+                               $OK = unlink($path);
+                       }
+
+                       clearstatcache();
+               }
+
+               return $OK;
+       }
+
+       /**
         * Returns an array with the names of folders in a specific path
         * Will return 'error' (string) if there were an error with reading directory content.
         * Usage: 11
@@ -2557,9 +2613,10 @@ class t3lib_div {
         * @param       string          $extensionList is the comma list of extensions to read only (blank = all)
         * @param       boolean         If set, then the path is prepended the filenames. Otherwise only the filenames are returned in the array
         * @param       string          $order is sorting: 1= sort alphabetically, 'mtime' = sort by modification time.
+        * @param       string          A comma seperated list of filenames to exclude, no wildcards
         * @return      array           Array of the files found
         */
-       function getFilesInDir($path,$extensionList='',$prependPath=0,$order='')        {
+       function getFilesInDir($path,$extensionList='',$prependPath=0,$order='',$excludePattern='')     {
 
                        // Initialize variabels:
                $filearray = array();
@@ -2575,9 +2632,9 @@ class t3lib_div {
                                        if (@is_file($path.'/'.$entry)) {
                                                $fI = pathinfo($entry);
                                                $key = md5($path.'/'.$entry);   // Don't change this ever - extensions may depend on the fact that the hash is an md5 of the path! (import/export extension)
-                                               if (!$extensionList || t3lib_div::inList($extensionList,strtolower($fI['extension'])))  {
+                                               if ((!strlen($extensionList) || t3lib_div::inList($extensionList,strtolower($fI['extension']))) && (!strlen($excludePattern) || !preg_match('/^'.$excludePattern.'$/',$entry))) {
                                                    $filearray[$key]=($prependPath?$path.'/':'').$entry;
-                                                       if ($order=='mtime') {$sortarray[$key]=filemtime($path.'/'.$entry);}
+                                                               if ($order=='mtime') {$sortarray[$key]=filemtime($path.'/'.$entry);}
                                                                elseif ($order) {$sortarray[$key]=$entry;}
                                                }
                                        }
@@ -2611,17 +2668,18 @@ class t3lib_div {
         * @param       string          $extList: Comma list of file extensions: Only files with extensions in this list (if applicable) will be selected.
         * @param       boolean         $regDirs: If set, directories are also included in output.
         * @param       integer         $recursivityLevels: The number of levels to dig down...
+        * @param string                $excludePattern: regex pattern of files/directories to exclude
         * @return      array           An array with the found files/directories.
         */
-       function getAllFilesAndFoldersInPath($fileArr,$path,$extList='',$regDirs=0,$recursivityLevels=99)       {
+       function getAllFilesAndFoldersInPath($fileArr,$path,$extList='',$regDirs=0,$recursivityLevels=99,$excludePattern='')    {
                if ($regDirs)   $fileArr[] = $path;
-               $fileArr = array_merge($fileArr, t3lib_div::getFilesInDir($path,$extList,1,1));
+               $fileArr = array_merge($fileArr, t3lib_div::getFilesInDir($path,$extList,1,1,$excludePattern));
 
                $dirs = t3lib_div::get_dirs($path);
                if (is_array($dirs) && $recursivityLevels>0)    {
                        foreach ($dirs as $subdirs)     {
-                               if ((string)$subdirs!=''      {
-                                       $fileArr = t3lib_div::getAllFilesAndFoldersInPath($fileArr,$path.$subdirs.'/',$extList,$regDirs,$recursivityLevels-1);
+                               if ((string)$subdirs!='' && (!strlen($excludePattern) || !preg_match('/^'.$excludePattern.'$/',$subdirs)))      {
+                                       $fileArr = t3lib_div::getAllFilesAndFoldersInPath($fileArr,$path.$subdirs.'/',$extList,$regDirs,$recursivityLevels-1,$excludePattern);
                                }
                        }
                }
@@ -2763,7 +2821,11 @@ class t3lib_div {
                        }
                        $result.= '</table>';
                } else  {
-                       $result  = false;
+                       $result  = '<table border="1" cellpadding="1" cellspacing="0" bgcolor="white">
+                               <tr>
+                                       <td><font face="Verdana,Arial" size="1" color="red">'.nl2br(htmlspecialchars((string)$array_in)).'<br /></font></td>
+                               </tr>
+                       </table>';      // Output it as a string.
                }
                return $result;
        }
@@ -2824,18 +2886,16 @@ class t3lib_div {
         * @return      string
         */
        function debug_trail()  {
-               if (function_exists('debug_backtrace')) {
-                       $trail = debug_backtrace();
-                       $trail = array_reverse($trail);
-                       array_pop($trail);
-
-                       $path = array();
-                       foreach($trail as $dat) {
-                               $path[] = $dat['class'].$dat['type'].$dat['function'];
-                       }
+               $trail = debug_backtrace();
+               $trail = array_reverse($trail);
+               array_pop($trail);
+
+               $path = array();
+               foreach($trail as $dat) {
+                       $path[] = $dat['class'].$dat['type'].$dat['function'];
+               }
 
-                       return implode(' // ',$path);
-               } else return 'N/A';
+               return implode(' // ',$path);
        }
 
        /**
@@ -2843,9 +2903,10 @@ class t3lib_div {
         *
         * @param       array           Array of arrays with similar keys
         * @param       string          Table header
+        * @param       boolean         If TRUE, will return content instead of echo'ing out.
         * @return      void            Outputs to browser.
         */
-       function debugRows($rows,$header='')    {
+       function debugRows($rows,$header='',$returnHTML=FALSE)  {
                if (is_array($rows))    {
                        reset($rows);
                        $firstEl = current($rows);
@@ -2869,7 +2930,7 @@ class t3lib_div {
                                        $tCells = array();
                                        foreach($headerColumns as $key) {
                                                $tCells[] = '
-                                                       <td><font face="Verdana,Arial" size="1">'.htmlspecialchars($singleRow[$key]).'</font></td>';
+                                                       <td><font face="Verdana,Arial" size="1">'.(is_array($singleRow[$key]) ? t3lib_div::debugRows($singleRow[$key],'',TRUE) : htmlspecialchars($singleRow[$key])).'</font></td>';
                                        }
                                        $tRows[] = '
                                                <tr>'.implode('',$tCells).'
@@ -2879,7 +2940,7 @@ class t3lib_div {
                                $table = '
                                        <table border="1" cellpadding="1" cellspacing="0" bgcolor="white">'.implode('',$tRows).'
                                        </table>';
-                               echo $table;
+                               if ($returnHTML)        return $table; else echo $table;
                        } else debug('Empty array of rows',$header);
                } else debug('No array of rows',$header);
        }
@@ -3027,15 +3088,16 @@ class t3lib_div {
                                SCRIPT_FILENAME =       Absolute filename of script             (Differs between windows/unix). On windows 'C:\\blabla\\blabl\\' will be converted to 'C:/blabla/blabl/'
 
                        Special extras:
-                               TYPO3_HOST_ONLY =               [host]                  = 192.168.1.4
-                               TYPO3_PORT              =               [port]                  = 8080 (blank if 80, taken from host value)
+                               TYPO3_HOST_ONLY =               [host] = 192.168.1.4
+                               TYPO3_PORT =                    [port] = 8080 (blank if 80, taken from host value)
                                TYPO3_REQUEST_HOST =    [scheme]://[host][:[port]]
-                               TYPO3_REQUEST_URL =             [scheme]://[host][:[port]][path]?[query]        (sheme will by default be 'http' until we can detect if it's https -
+                               TYPO3_REQUEST_URL =             [scheme]://[host][:[port]][path]?[query] (scheme will by default be "http" until we can detect something different)
                                TYPO3_REQUEST_SCRIPT =  [scheme]://[host][:[port]][path_script]
                                TYPO3_REQUEST_DIR =             [scheme]://[host][:[port]][path_dir]
                                TYPO3_SITE_URL =                [scheme]://[host][:[port]][path_dir] of the TYPO3 website frontend
                                TYPO3_SITE_SCRIPT =     [script / Speaking URL] of the TYPO3 website
-                               TYPO3_DOCUMENT_ROOT     =       Absolute path of root of documents:     TYPO3_DOCUMENT_ROOT.SCRIPT_NAME = SCRIPT_FILENAME (typically)
+                               TYPO3_DOCUMENT_ROOT =   Absolute path of root of documents: TYPO3_DOCUMENT_ROOT.SCRIPT_NAME = SCRIPT_FILENAME (typically)
+                               TYPO3_SSL =                     Returns TRUE if this session uses SSL (HTTPS)
 
                        Notice: [fragment] is apparently NEVER available to the script!
 
@@ -3051,7 +3113,7 @@ class t3lib_div {
 
                $retVal = '';
 
-               switch((string)$getEnvName)     {
+               switch ((string)$getEnvName)    {
                        case 'SCRIPT_NAME':
                                $retVal = (php_sapi_name()=='cgi'||php_sapi_name()=='cgi-fcgi')&&($_SERVER['ORIG_PATH_INFO']?$_SERVER['ORIG_PATH_INFO']:$_SERVER['PATH_INFO']) ? ($_SERVER['ORIG_PATH_INFO']?$_SERVER['ORIG_PATH_INFO']:$_SERVER['PATH_INFO']) : ($_SERVER['ORIG_SCRIPT_NAME']?$_SERVER['ORIG_SCRIPT_NAME']:$_SERVER['SCRIPT_NAME']);
                        break;
@@ -3060,7 +3122,10 @@ class t3lib_div {
                        break;
                        case 'REQUEST_URI':
                                        // Typical application of REQUEST_URI is return urls, forms submitting to itself etc. Example: returnUrl='.rawurlencode(t3lib_div::getIndpEnv('REQUEST_URI'))
-                               if (!$_SERVER['REQUEST_URI'])   {       // This is for ISS/CGI which does not have the REQUEST_URI available.
+                               if ($GLOBALS['TYPO3_CONF_VARS']['SYS']['requestURIvar'])        {       // This is for URL rewriters that store the original URI in a server variable (eg ISAPI_Rewriter for IIS: HTTP_X_REWRITE_URL)
+                                       list($v,$n) = explode('|',$GLOBALS['TYPO3_CONF_VARS']['SYS']['requestURIvar']);
+                                       $retVal = $GLOBALS[$v][$n];
+                               } elseif (!$_SERVER['REQUEST_URI'])     {       // This is for ISS/CGI which does not have the REQUEST_URI available.
                                        $retVal = '/'.ereg_replace('^/','',t3lib_div::getIndpEnv('SCRIPT_NAME')).
                                                ($_SERVER['QUERY_STRING']?'?'.$_SERVER['QUERY_STRING']:'');
                                } else $retVal = $_SERVER['REQUEST_URI'];
@@ -3200,7 +3265,7 @@ class t3lib_div {
                        $bInfo['BROWSER']= 'konqu';
                } elseif (strstr($useragent,'Opera'))   {
                        $bInfo['BROWSER']= 'opera';
-               } elseif (strstr($useragent,'MSIE 4') || strstr($useragent,'MSIE 5') || strstr($useragent,'MSIE 6'))    {
+               } elseif (preg_match('/MSIE [4567]/', $useragent))      {
                        $bInfo['BROWSER']= 'msie';
                } elseif (strstr($useragent,'Mozilla/4') || strstr($useragent,'Mozilla/5'))     {
                        $bInfo['BROWSER']='net';
@@ -3210,7 +3275,8 @@ class t3lib_div {
                        switch($bInfo['BROWSER'])       {
                                case 'net':
                                        $bInfo['VERSION']= doubleval(substr($useragent,8));
-                                       if (strstr($useragent,'Netscape6/')) {$bInfo['VERSION']=doubleval(substr(strstr($useragent,'Netscape6/'),10));}
+                                       if (strstr($useragent,'Netscape6/')) {$bInfo['VERSION'] = doubleval(substr(strstr($useragent,'Netscape6/'),10));}       // Will we ever know if this was a typo or intention...?! :-(
+                                       if (strstr($useragent,'Netscape/6')) {$bInfo['VERSION'] = doubleval(substr(strstr($useragent,'Netscape/6'),10));}
                                        if (strstr($useragent,'Netscape/7')) {$bInfo['VERSION']=doubleval(substr(strstr($useragent,'Netscape/7'),9));}
                                break;
                                case 'msie':
@@ -3504,7 +3570,7 @@ class t3lib_div {
         * Used to create the cHash value
         *
         * @param       string          Query-parameters: "&xxx=yyy&zzz=uuu"
-        * @return      array           Array with key/value pairs of query-parameters WITHOUT a certain list of variable names (like id, type, no_cache etc) and WITH a variable, encryptionKey, specific for this server/installation
+        * @return      array           Array with key/value pairs of query-parameters WITHOUT a certain list of variable names (like id, type, no_cache etc.) and WITH a variable, encryptionKey, specific for this server/installation
         * @see tslib_fe::makeCacheHash(), tslib_cObj::typoLink()
         */
        function cHashParams($addQueryParams) {
@@ -3514,7 +3580,7 @@ class t3lib_div {
                $pA = array();
                foreach($params as $theP)       {
                        $pKV = explode('=', $theP);     // Splitting single param by '=' sign
-                       if (!t3lib_div::inList('id,type,no_cache,cHash,MP,ftu',$pKV[0]))        {
+                       if (!t3lib_div::inList('id,type,no_cache,cHash,MP,ftu',$pKV[0]) && !preg_match('/TSFE_ADMIN_PANEL\[.*?\]/',$pKV[0]))    {
                                $pA[rawurldecode($pKV[0])] = (string)rawurldecode($pKV[1]);
                        }
                }
@@ -3622,7 +3688,7 @@ class t3lib_div {
                                                // If no entry is found for the language key, then force a value depending on meta-data setting. By default an automated filename will be used:
                                        if (!isset($xmlContent['data'][$langKey]))      {
                                                $LOCAL_LANG[$langKey] = t3lib_div::llXmlAutoFileName($fileRef, $langKey);
-                                       } else {
+                                       } else {
                                                $LOCAL_LANG[$langKey] = $xmlContent['data'][$langKey];
                                        }
 
@@ -3698,16 +3764,15 @@ class t3lib_div {
         * @return      string          Returns the filename reference for the language unless error occured (or local mode is used) in which case it will be NULL
         */
        function llXmlAutoFileName($fileRef,$language)  {
-
                        // Analyse file reference:
                $location = 'typo3conf/l10n/'.$language.'/';    // Default location of translations
-               if (t3lib_div::isFirstPartOfStr($fileRef,PATH_site.TYPO3_mainDir.'sysext/'))    {       // Is system:
-                       $validatedPrefix = PATH_site.TYPO3_mainDir.'sysext/';
+               if (t3lib_div::isFirstPartOfStr($fileRef,PATH_typo3.'sysext/')) {       // Is system:
+                       $validatedPrefix = PATH_typo3.'sysext/';
                        #$location = 'EXT:csh_'.$language.'/';  // For system extensions translations are found in "csh_*" extensions (language packs)
-               } elseif (t3lib_div::isFirstPartOfStr($fileRef,PATH_site.TYPO3_mainDir.'ext/')) {       // Is global:
-                       $validatedPrefix = PATH_site.TYPO3_mainDir.'ext/';
-               } elseif (t3lib_div::isFirstPartOfStr($fileRef,PATH_site.'typo3conf/ext/'))     {       // Is local:
-                       $validatedPrefix = PATH_site.'typo3conf/ext/';
+               } elseif (t3lib_div::isFirstPartOfStr($fileRef,PATH_typo3.'ext/'))      {       // Is global:
+                       $validatedPrefix = PATH_typo3.'ext/';
+               } elseif (t3lib_div::isFirstPartOfStr($fileRef,PATH_typo3conf.'ext/'))  {       // Is local:
+                       $validatedPrefix = PATH_typo3conf.'ext/';
                } else {
                        $validatedPrefix = '';
                }
@@ -3843,7 +3908,7 @@ class t3lib_div {
                if (strstr($funcName,':'))      {
                        list($file,$funcRef) = t3lib_div::revExplode(':',$funcName,2);
                        $requireFile = t3lib_div::getFileAbsFileName($file);
-                       if ($requireFile) require_once($requireFile);
+                       if ($requireFile) t3lib_div::requireOnce($requireFile);
                } else {
                        $funcRef = $funcName;
                }
@@ -3934,7 +3999,7 @@ class t3lib_div {
                        if (strstr($classRef,':'))      {
                                list($file,$class) = t3lib_div::revExplode(':',$classRef,2);
                                $requireFile = t3lib_div::getFileAbsFileName($file);
-                               if ($requireFile)       require_once($requireFile);
+                               if ($requireFile)       t3lib_div::requireOnce($requireFile);
                        } else {
                                $class = $classRef;
                        }
@@ -3979,9 +4044,18 @@ class t3lib_div {
         * Usage: 447
         *
         * @param       string          Class name to instantiate
-        * @return      object          The object
+        * @return      object          A reference to the object
         */
        function &makeInstance($className)      {
+
+                       // Load class file if not found:
+               if (!class_exists($className))  {
+                       if (substr($className,0,6)=='t3lib_')   {
+                               t3lib_div::requireOnce(PATH_t3lib.'class.'.strtolower($className).'.php');
+                       }
+               }
+
+                       // Return object.
                return class_exists('ux_'.$className) ? t3lib_div::makeInstance('ux_'.$className) : new $className;
        }
 
@@ -4027,7 +4101,7 @@ class t3lib_div {
                        } else {
                                $requireFile = t3lib_div::getFileAbsFileName($info['classFile']);
                                if (@is_file($requireFile)) {
-                                       require_once ($requireFile);
+                                       t3lib_div::requireOnce ($requireFile);
                                        $obj = t3lib_div::makeInstance($info['className']);
                                        if (is_object($obj)) {
                                                if(!@is_callable(array($obj,'init')))   {
@@ -4057,6 +4131,16 @@ class t3lib_div {
        }
 
        /**
+        * Require a class for TYPO3
+        * Useful to require classes from inside other classes (not global scope). A limited set of global variables are available (see function)
+        */
+       function requireOnce($requireFile)      {
+               global $T3_SERVICES, $T3_VAR, $TYPO3_CONF_VARS;
+
+               require_once ($requireFile);
+       }
+
+       /**
         * Simple substitute for the PHP function mail() which allows you to specify encoding and character set
         * The fifth parameter ($encoding) will allow you to specify 'base64' encryption for the output (set $encoding=base64)
         * Further the output has the charset set to ISO-8859-1 by default.
@@ -4069,7 +4153,7 @@ class t3lib_div {
         * @param       string          Encoding type: "base64", "quoted-printable", "8bit". Default value is "quoted-printable".
         * @param       string          Charset used in encoding-headers (only if $encoding is set to a valid value which produces such a header)
         * @param       boolean         If set, the header content will not be encoded.
-        * @return      void
+        * @return      boolean         True if mail was accepted for delivery, false otherwise
         */
        function plainMailEncoded($email,$subject,$message,$headers='',$encoding='quoted-printable',$charset='',$dontEncodeHeader=false)        {
                if (!$charset)  {
@@ -4128,7 +4212,11 @@ class t3lib_div {
 
                $headers=trim(implode($linebreak,t3lib_div::trimExplode(chr(10),$headers,1)));  // Make sure no empty lines are there.
 
-               mail($email,$subject,$message,$headers);
+               $ret = @mail($email,$subject,$message,$headers);
+               if (!$ret)      {
+                       t3lib_div::sysLog('Mail to "'.$email.'" could not be sent (Subject: "'.$subject.'").', 'Core', 3);
+               }
+               return $ret;
        }
 
        /**
@@ -4234,25 +4322,28 @@ class t3lib_div {
         */
        function substUrlsInPlainText($message,$urlmode='76',$index_script_url='')      {
                        // Substitute URLs with shorter links:
-               $urlSplit=explode('http://',$message);
-               reset($urlSplit);
-               while(list($c,$v)=each($urlSplit))      {
-                       if ($c) {
-                               $newParts = preg_split('/\s|[<>"{}|\\\^`()\']/', $v, 2);
-                               $newURL='http://'.$newParts[0];
-                                       switch((string)$urlmode)        {
+               foreach (array('http','https') as $protocol)    {
+                       $urlSplit = explode($protocol.'://',$message);
+                       reset($urlSplit);
+                       while (list($c,$v) = each($urlSplit))   {
+                               if ($c) {
+                                       $newParts = preg_split('/\s|[<>"{}|\\\^`()\']/', $v, 2);
+                                       $newURL = $protocol.'://'.$newParts[0];
+
+                                       switch ((string)$urlmode)       {
                                                case 'all':
-                                                       $newURL=t3lib_div::makeRedirectUrl($newURL,0,$index_script_url);
+                                                       $newURL = t3lib_div::makeRedirectUrl($newURL,0,$index_script_url);
                                                break;
                                                case '76':
-                                                       $newURL=t3lib_div::makeRedirectUrl($newURL,76,$index_script_url);
+                                                       $newURL = t3lib_div::makeRedirectUrl($newURL,76,$index_script_url);
                                                break;
                                        }
-                               $urlSplit[$c]=$newURL.substr($v,strlen($newParts[0]));
+                                       $urlSplit[$c] = $newURL . substr($v,strlen($newParts[0]));
+                               }
                        }
+                       $message = implode('',$urlSplit);
                }
 
-               $message=implode('',$urlSplit);
                return $message;
        }
 
@@ -4283,6 +4374,7 @@ class t3lib_div {
                        $inUrl=($index_script_url ? $index_script_url : t3lib_div::getIndpEnv('TYPO3_REQUEST_DIR').'index.php').
                                '?RDCT='.$md5;
                }
+
                return $inUrl;
        }
 
@@ -4370,10 +4462,7 @@ class t3lib_div {
 
                        // do custom logging
                if (is_array($TYPO3_CONF_VARS['SC_OPTIONS']['t3lib/class.t3lib_div.php']['systemLog'])) {
-                       $params = array('msg'=>$msg, 'extKey'=>$extKey);
-                       if (function_exists('debug_backtrace')) {
-                               $params['backTrace'] = debug_backtrace();
-                       }
+                       $params = array('msg'=>$msg, 'extKey'=>$extKey, 'backTrace'=>debug_backtrace());
                        $fakeThis = FALSE;
                        foreach ($TYPO3_CONF_VARS['SC_OPTIONS']['t3lib/class.t3lib_div.php']['systemLog'] as $hookMethod)       {
                                t3lib_div::callUserFunction($hookMethod,$params,$fakeThis);
@@ -4383,6 +4472,9 @@ class t3lib_div {
                        // TYPO3 logging enabled?
                if (!$TYPO3_CONF_VARS['SYS']['systemLog'])      return;
 
+               $dateFormat = $GLOBALS['TYPO3_CONF_VARS']['SYS']['ddmmyy'];
+               $timeFormat = $GLOBALS['TYPO3_CONF_VARS']['SYS']['hhmm'];
+
                        // use all configured logging options
                foreach (explode(';',$TYPO3_CONF_VARS['SYS']['systemLog'],2) as $log)   {
                        list($type,$destination,$level) = explode(',',$log,4);
@@ -4397,7 +4489,7 @@ class t3lib_div {
                                $file = fopen($destination, 'a');
                                if ($file)     {
                                        flock($file, LOCK_EX);  // try locking, but ignore if not available (eg. on NFS and FAT)
-                                       fwrite($file, date('d/m/Y i:H').$msgLine.chr(10));
+                                       fwrite($file, date($dateFormat.' '.$timeFormat).$msgLine.chr(10));
                                        flock($file, LOCK_UN);    // release the lock
                                        fclose($file);
                                }
@@ -4558,7 +4650,7 @@ class t3lib_div {
 
 
        /**
-        * Quotes a string for usage as JS parameter. Depends wheter the value is used in script tags (it doesn't need/must not get htmlspecialchared in this case)
+        * Quotes a string for usage as JS parameter. Depends wheter the value is used in script tags (it doesn't need/must not get htmlspecialchar'ed in this case)
         *
         * @param       string          The string to encode.
         * @param       boolean         If the values get's used in <script> tags.