Added argument to debugRows() so it can return HTML instead of echo'ing
[Packages/TYPO3.CMS.git] / t3lib / class.t3lib_div.php
index e1c9a3d..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
@@ -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;
+       }
+
 
 
 
@@ -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.'"';
+                                               }
                                        }
                                }
 
@@ -2370,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;
        }
@@ -2531,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
@@ -2834,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);
 
-                       return implode(' // ',$path);
-               } else return 'N/A';
+               $path = array();
+               foreach($trail as $dat) {
+                       $path[] = $dat['class'].$dat['type'].$dat['function'];
+               }
+
+               return implode(' // ',$path);
        }
 
        /**
@@ -2853,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);
@@ -2879,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).'
@@ -2889,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);
        }
@@ -3071,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'];
@@ -3211,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') || strstr($useragent,'MSIE 7'))     {
+               } elseif (preg_match('/MSIE [4567]/', $useragent))      {
                        $bInfo['BROWSER']= 'msie';
                } elseif (strstr($useragent,'Mozilla/4') || strstr($useragent,'Mozilla/5'))     {
                        $bInfo['BROWSER']='net';
@@ -3221,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':
@@ -3525,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]);
                        }
                }
@@ -3989,7 +4044,7 @@ 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)      {
 
@@ -3999,7 +4054,7 @@ class t3lib_div {
                                t3lib_div::requireOnce(PATH_t3lib.'class.'.strtolower($className).'.php');
                        }
                }
-               
+
                        // Return object.
                return class_exists('ux_'.$className) ? t3lib_div::makeInstance('ux_'.$className) : new $className;
        }
@@ -4074,16 +4129,16 @@ class t3lib_div {
                }
                return $error;
        }
-       
+
        /**
         * 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
@@ -4098,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)  {
@@ -4157,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;
        }
 
        /**
@@ -4403,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);
@@ -4416,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);
@@ -4430,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 H:i').$msgLine.chr(10));
+                                       fwrite($file, date($dateFormat.' '.$timeFormat).$msgLine.chr(10));
                                        flock($file, LOCK_UN);    // release the lock
                                        fclose($file);
                                }
@@ -4591,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.
@@ -4608,4 +4667,4 @@ class t3lib_div {
 
 }
 
-?>
\ No newline at end of file
+?>