[BUGFIX] Using datetime field with datepicker the time information gets lost
[Packages/TYPO3.CMS.git] / t3lib / class.t3lib_div.php
index f74b56b..c25d124 100644 (file)
@@ -2,7 +2,7 @@
 /***************************************************************
  *  Copyright notice
  *
- *  (c) 1999-2010 Kasper Skårhøj (kasperYYYY@typo3.com)
+ *  (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
@@ -236,6 +236,27 @@ final class t3lib_div {
        const SYSLOG_SEVERITY_ERROR = 3;
        const SYSLOG_SEVERITY_FATAL = 4;
 
+       /**
+        * Singleton instances returned by makeInstance, using the class names as
+        * array keys
+        *
+        * @var array<t3lib_Singleton>
+        */
+       protected static $singletonInstances = array();
+
+       /**
+        * Instances returned by makeInstance, using the class names as array keys
+        *
+        * @var array<array><object>
+        */
+       protected static $nonSingletonInstances = array();
+
+       /**
+        * Register for makeInstance with given class name and final class names to reduce number of class_exists() calls
+        *
+        * @var array Given class name => final class name
+        */
+       protected static $finalClassNameRegister = array();
 
        /*************************
         *
@@ -474,15 +495,27 @@ final class t3lib_div {
                $returnCode = '';
                if ($gfxConf['gif_compress'] && strtolower(substr($theFile, -4, 4)) == '.gif') { // GIF...
                        if (($type == 'IM' || !$type) && $gfxConf['im'] && $gfxConf['im_path_lzw']) { // IM
-                               $cmd = self::imageMagickCommand('convert', '"' . $theFile . '" "' . $theFile . '"', $gfxConf['im_path_lzw']);
-                               exec($cmd);
+                                       // use temporary file to prevent problems with read and write lock on same file on network file systems
+                               $temporaryName  =  dirname($theFile) . '/' . md5(uniqid()) . '.gif';
+                                       // rename could fail, if a simultaneous thread is currently working on the same thing
+                               if (@rename($theFile, $temporaryName)) {
+                                       $cmd = self::imageMagickCommand('convert', '"' . $temporaryName . '" "' . $theFile . '"', $gfxConf['im_path_lzw']);
+                                       t3lib_utility_Command::exec($cmd);
+                                       unlink($temporaryName);
+                               }
 
                                $returnCode = 'IM';
+                               if (@is_file($theFile)) {
+                                       self::fixPermissions($theFile);
+                               }
                        } elseif (($type == 'GD' || !$type) && $gfxConf['gdlib'] && !$gfxConf['gdlib_png']) { // GD
                                $tempImage = imageCreateFromGif($theFile);
                                imageGif($tempImage, $theFile);
                                imageDestroy($tempImage);
                                $returnCode = 'GD';
+                               if (@is_file($theFile)) {
+                                       self::fixPermissions($theFile);
+                               }
                        }
                }
                return $returnCode;
@@ -504,8 +537,11 @@ final class t3lib_div {
                                && @is_file($theFile)) { // IM
                        $newFile = substr($theFile, 0, -4) . '.gif';
                        $cmd = self::imageMagickCommand('convert', '"' . $theFile . '" "' . $newFile . '"', $GLOBALS['TYPO3_CONF_VARS']['GFX']['im_path_lzw']);
-                       exec($cmd);
+                       t3lib_utility_Command::exec($cmd);
                        $theFile = $newFile;
+                       if (@is_file($newFile)) {
+                               self::fixPermissions($newFile);
+                       }
                                // unlink old file?? May be bad idea bacause TYPO3 would then recreate the file every time as TYPO3 thinks the file is not generated because it's missing!! So do not unlink $theFile here!!
                }
                return $theFile;
@@ -531,8 +567,9 @@ final class t3lib_div {
                        } else {
                                $newFile = PATH_site . 'typo3temp/readPG_' . md5($theFile . '|' . filemtime($theFile)) . ($output_png ? '.png' : '.gif');
                                $cmd = self::imageMagickCommand('convert', '"' . $theFile . '" "' . $newFile . '"', $GLOBALS['TYPO3_CONF_VARS']['GFX']['im_path']);
-                               exec($cmd);
+                               t3lib_utility_Command::exec($cmd);
                                if (@is_file($newFile)) {
+                                       self::fixPermissions($newFile);
                                        return $newFile;
                                }
                        }
@@ -3108,13 +3145,19 @@ final class t3lib_div {
        /**
         * Sets the file system mode and group ownership of a file or a folder.
         *
-        * @param   string   Absolute filepath of file or folder, must not be escaped.
+        * @param   string   Path of file or folder, must not be escaped. Path can be absolute or relative
         * @param   boolean  If set, also fixes permissions of files and folders in the folder (if $path is a folder)
         * @return  mixed       TRUE on success, FALSE on error, always TRUE on Windows OS
         */
        public static function fixPermissions($path, $recursive = FALSE) {
                if (TYPO3_OS != 'WIN') {
                        $result = FALSE;
+
+                               // Make path absolute
+                       if (!self::isAbsPath($path)) {
+                               $path = self::getFileAbsFileName($path, FALSE);
+                       }
+
                        if (self::isAllowedAbsPath($path)) {
                                if (@is_file($path)) {
                                                // "@" is there because file is not necessarily OWNED by the user
@@ -3163,7 +3206,7 @@ final class t3lib_div {
         *
         * @param       string          Absolute filepath to write to inside "typo3temp/". First part of this string must match PATH_site."typo3temp/"
         * @param       string          Content string to write
-        * @return      string          Returns false on success, otherwise an error string telling about the problem.
+        * @return      string          Returns NULL on success, otherwise an error string telling about the problem.
         */
        public static function writeFileToTypo3tempDir($filepath, $content) {
 
@@ -3635,6 +3678,9 @@ final class t3lib_div {
         *
         *************************/
 
+       /* Deprecated since 4.5, use t3lib_utility_Debug */
+
+
        /**
         * Returns a string with a list of ascii-values for the first $characters characters in $string
         * Usage: 0
@@ -3642,15 +3688,11 @@ final class t3lib_div {
         * @param       string          String to show ASCII value for
         * @param       integer         Number of characters to show
         * @return      string          The string with ASCII values in separated by a space char.
+        * @deprecated since TYPO3 4.5 - Use t3lib_utility_Debug::ordinalValue instead
         */
        public static function debug_ordvalue($string, $characters = 100) {
-               if (strlen($string) < $characters) {
-                       $characters = strlen($string);
-               }
-               for ($i = 0; $i < $characters; $i++) {
-                       $valuestring .= ' ' . ord(substr($string, $i, 1));
-               }
-               return trim($valuestring);
+               self::logDeprecatedFunction();
+               return t3lib_utility_Debug::ordinalValue($string, $characters);
        }
 
        /**
@@ -3661,49 +3703,11 @@ final class t3lib_div {
         *
         * @param       mixed           Array to view
         * @return      string          HTML output
+        * @deprecated since TYPO3 4.5 - Use t3lib_utility_Debug::viewArray instead
         */
        public static function view_array($array_in) {
-               if (is_array($array_in)) {
-                       $result = '
-                       <table border="1" cellpadding="1" cellspacing="0" bgcolor="white">';
-                       if (count($array_in) == 0) {
-                               $result .= '<tr><td><font face="Verdana,Arial" size="1"><strong>EMPTY!</strong></font></td></tr>';
-                       } else {
-                               foreach ($array_in as $key => $val) {
-                                       $result .= '<tr>
-                                               <td valign="top"><font face="Verdana,Arial" size="1">' . htmlspecialchars((string) $key) . '</font></td>
-                                               <td>';
-                                       if (is_array($val)) {
-                                               $result .= self::view_array($val);
-                                       } elseif (is_object($val)) {
-                                               $string = '';
-                                               if (method_exists($val, '__toString')) {
-                                                       $string .= get_class($val) . ': ' . (string) $val;
-                                               } else {
-                                                       $string .= print_r($val, TRUE);
-                                               }
-                                               $result .= '<font face="Verdana,Arial" size="1" color="red">' . nl2br(htmlspecialchars($string)) . '<br /></font>';
-                                       } else {
-                                               if (gettype($val) == 'object') {
-                                                       $string = 'Unknown object';
-                                               } else {
-                                                       $string = (string) $val;
-                                               }
-                                               $result .= '<font face="Verdana,Arial" size="1" color="red">' . nl2br(htmlspecialchars($string)) . '<br /></font>';
-                                       }
-                                       $result .= '</td>
-                                       </tr>';
-                               }
-                       }
-                       $result .= '</table>';
-               } else {
-                       $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;
+               self::logDeprecatedFunction();
+               return t3lib_utility_Debug::viewArray($array_in);
        }
 
        /**
@@ -3713,9 +3717,11 @@ final class t3lib_div {
         * @param       mixed           Array to print visually (in a table).
         * @return      void
         * @see view_array()
+        * @deprecated since TYPO3 4.5 - Use t3lib_utility_Debug::printArray instead
         */
        public static function print_array($array_in) {
-               echo self::view_array($array_in);
+               self::logDeprecatedFunction();
+               t3lib_utility_Debug::printArray($array_in);
        }
 
        /**
@@ -3729,122 +3735,22 @@ final class t3lib_div {
         * @param       string          The header.
         * @param       string          Group for the debug console
         * @return      void
+        * @deprecated since TYPO3 4.5 - Use t3lib_utility_Debug::debug instead
         */
        public static function debug($var = '', $header = '', $group = 'Debug') {
-                       // buffer the output of debug if no buffering started before
-               if (ob_get_level() == 0) {
-                       ob_start();
-               }
-               $debug = '';
-
-               if ($header) {
-                       $debug .= '
-                       <table class="typo3-debug" border="0" cellpadding="0" cellspacing="0" bgcolor="white" style="border:0px; margin-top:3px; margin-bottom:3px;">
-                               <tr>
-                                       <td style="background-color:#bbbbbb; font-family: verdana,arial; font-weight: bold; font-size: 10px;">' .
-                                       htmlspecialchars((string) $header) .
-                                       '</td>
-                               </tr>
-                               <tr>
-                                       <td>';
-               }
-
-               if (is_array($var)) {
-                       $debug .= self::view_array($var);
-               } elseif (is_object($var)) {
-                       $debug .= '<strong>|Object:<pre>';
-                       $debug .= print_r($var, TRUE);
-                       $debug .= '</pre>|</strong>';
-               } elseif ((string) $var !== '') {
-                       $debug .= '<strong>|' . htmlspecialchars((string) $var) . '|</strong>';
-               } else {
-                       $debug .= '<strong>| debug |</strong>';
-               }
-
-               if ($header) {
-                       $debug .= '
-                                       </td>
-                               </tr>
-                       </table>';
-               }
-
-               if (TYPO3_MODE === 'BE') {
-                       $group = htmlspecialchars($group);
-
-                       if ($header !== '') {
-                               $tabHeader = htmlspecialchars($header);
-                       } else {
-                               $tabHeader = 'Debug';
-                       }
-
-                       if (is_object($var)) {
-                               $debug = str_replace(
-                                       array('"', '/', '<', "\n", "\r"),
-                                       array('\"', '\/', '\<', '<br />', ''),
-                                       $debug
-                               );
-                       } else {
-                               $debug = str_replace(
-                                       array('"', '/', '<', "\n", "\r"),
-                                       array('\"', '\/', '\<', '', ''),
-                                       $debug
-                               );
-                       }
-
-                       $script = '
-                               (function debug() {
-                                       var debugMessage = "' . $debug . '";
-                                       var header = "' . $tabHeader . '";
-                                       var group = "' . $group . '";
-
-                                       if (typeof Ext !== "object" && (top && typeof top.Ext !== "object")) {
-                                               document.write(debugMessage);
-                                               return;
-                                       }
-
-                                       if (top && typeof Ext !== "object") {
-                                               Ext = top.Ext;
-                                       }
-
-                                       Ext.onReady(function() {
-                                               var TYPO3ViewportInstance = null;
-
-                                               if (top && top.TYPO3 && typeof top.TYPO3.Backend === "object") {
-                                                       TYPO3ViewportInstance = top.TYPO3.Backend;
-                                               } else if (typeof TYPO3 === "object" && typeof TYPO3.Backend === "object") {
-                                                       TYPO3ViewportInstance = TYPO3.Backend;
-                                               }
-
-                                               if (TYPO3ViewportInstance !== null) {
-                                                       TYPO3ViewportInstance.DebugConsole.addTab(debugMessage, header, group);
-                                               } else {
-                                                       document.write(debugMessage);
-                                               }
-                                       });
-                               })();
-                       ';
-                       echo self::wrapJS($script);
-               } else {
-                       echo $debug;
-               }
+               self::logDeprecatedFunction();
+               t3lib_utility_Debug::debug($var, $header, $group);
        }
 
        /**
         * Displays the "path" of the function call stack in a string, using debug_backtrace
         *
         * @return      string
+        * @deprecated since TYPO3 4.5 - Use t3lib_utility_Debug::debugTrail instead
         */
        public static function debug_trail() {
-               $trail = debug_backtrace();
-               $trail = array_reverse($trail);
-               array_pop($trail);
-
-               $path = array();
-               foreach ($trail as $dat) {
-                       $path[] = $dat['class'] . $dat['type'] . $dat['function'] . '#' . $dat['line'];
-               }
-
-               return implode(' // ', $path);
+               self::logDeprecatedFunction();
+               return t3lib_utility_Debug::debugTrail();
        }
 
        /**
@@ -3854,52 +3760,11 @@ final class t3lib_div {
         * @param       string          Table header
         * @param       boolean         If TRUE, will return content instead of echo'ing out.
         * @return      void            Outputs to browser.
+        * @deprecated since TYPO3 4.5 - Use t3lib_utility_Debug::debugRows instead
         */
        public static function debugRows($rows, $header = '', $returnHTML = FALSE) {
-               if (is_array($rows)) {
-                       reset($rows);
-                       $firstEl = current($rows);
-                       if (is_array($firstEl)) {
-                               $headerColumns = array_keys($firstEl);
-                               $tRows = array();
-
-                                       // Header:
-                               $tRows[] = '<tr><td colspan="' . count($headerColumns) . '" style="background-color:#bbbbbb; font-family: verdana,arial; font-weight: bold; font-size: 10px;"><strong>' . htmlspecialchars($header) . '</strong></td></tr>';
-                               $tCells = array();
-                               foreach ($headerColumns as $key) {
-                                       $tCells[] = '
-                                                       <td><font face="Verdana,Arial" size="1"><strong>' . htmlspecialchars($key) . '</strong></font></td>';
-                               }
-                               $tRows[] = '
-                                               <tr>' . implode('', $tCells) . '
-                                               </tr>';
-
-                                       // Rows:
-                               foreach ($rows as $singleRow) {
-                                       $tCells = array();
-                                       foreach ($headerColumns as $key) {
-                                               $tCells[] = '
-                                                       <td><font face="Verdana,Arial" size="1">' . (is_array($singleRow[$key]) ? self::debugRows($singleRow[$key], '', TRUE) : htmlspecialchars($singleRow[$key])) . '</font></td>';
-                                       }
-                                       $tRows[] = '
-                                               <tr>' . implode('', $tCells) . '
-                                               </tr>';
-                               }
-
-                               $table = '
-                                       <table border="1" cellpadding="1" cellspacing="0" bgcolor="white">' . implode('', $tRows) . '
-                                       </table>';
-                               if ($returnHTML) {
-                                       return $table;
-                               } else {
-                                       echo $table;
-                               }
-                       } else {
-                               debug('Empty array of rows', $header);
-                       }
-               } else {
-                       debug('No array of rows', $header);
-               }
+               self::logDeprecatedFunction();
+               t3lib_utility_Debug::debugRows($rows, $header, $returnHTML);
        }
 
 
@@ -4183,12 +4048,14 @@ final class t3lib_div {
                                $retVal = $DR;
                                break;
                        case 'TYPO3_HOST_ONLY':
-                               $p = explode(':', self::getIndpEnv('HTTP_HOST'));
-                               $retVal = $p[0];
+                               $httpHost = self::getIndpEnv('HTTP_HOST');
+                               $httpHostBracketPosition = strpos($httpHost, ']');
+                               $retVal = ($httpHostBracketPosition !== FALSE) ? substr($httpHost, 0, ($httpHostBracketPosition + 1)) : array_shift(explode(':', $httpHost));
                                break;
                        case 'TYPO3_PORT':
-                               $p = explode(':', self::getIndpEnv('HTTP_HOST'));
-                               $retVal = $p[1];
+                               $httpHost = self::getIndpEnv('HTTP_HOST');
+                               $httpHostOnly = self::getIndpEnv('TYPO3_HOST_ONLY');
+                               $retVal = (strlen($httpHost) > strlen($httpHostOnly)) ? substr($httpHost, strlen($httpHostOnly) + 1) : '';
                                break;
                        case 'TYPO3_REQUEST_HOST':
                                $retVal = (self::getIndpEnv('TYPO3_SSL') ? 'https://' : 'http://') .
@@ -4431,17 +4298,19 @@ final class t3lib_div {
 
        /**
         * Checks for malicious file paths.
-        * Returns true if no '//', '..' or '\' is in the $theFile
+        *
+        * Returns TRUE if no '//', '..', '\' or control characters are found in the $theFile.
         * This should make sure that the path is not pointing 'backwards' and further doesn't contain double/back slashes.
         * So it's compatible with the UNIX style path strings valid for TYPO3 internally.
         * Usage: 14
         *
         * @param       string          Filepath to evaluate
-        * @return      boolean         True, if no '//', '\', '/../' is in the $theFile and $theFile doesn't begin with '../'
+        * @return      boolean         TRUE, $theFile is allowed path string
+        * @see         http://php.net/manual/en/security.filesystem.nullbytes.php
         * @todo        Possible improvement: Should it rawurldecode the string first to check if any of these characters is encoded ?
         */
        public static function validPathStr($theFile) {
-               if (strpos($theFile, '//') === FALSE && strpos($theFile, '\\') === FALSE && !preg_match('#(?:^\.\.|/\.\./)#', $theFile)) {
+               if (strpos($theFile, '//') === FALSE && strpos($theFile, '\\') === FALSE && !preg_match('#(?:^\.\.|/\.\./|[[:cntrl:]])#', $theFile)) {
                        return TRUE;
                }
        }
@@ -4484,6 +4353,11 @@ final class t3lib_div {
         * @return      boolean
         */
        public static function verifyFilenameAgainstDenyPattern($filename) {
+                       // Filenames are not allowed to contain control characters
+               if (preg_match('/[[:cntrl:]]/', $filename)) {
+                       return FALSE;
+               }
+
                if (strcmp($filename, '') && strcmp($GLOBALS['TYPO3_CONF_VARS']['BE']['fileDenyPattern'], '')) {
                        $result = preg_match('/' . $GLOBALS['TYPO3_CONF_VARS']['BE']['fileDenyPattern'] . '/i', $filename);
                        if ($result) {
@@ -5359,39 +5233,53 @@ final class t3lib_div {
         * Creates an instance of a class taking into account the class-extensions
         * API of TYPO3. USE THIS method instead of the PHP "new" keyword.
         * Eg. "$obj = new myclass;" should be "$obj = t3lib_div::makeInstance("myclass")" instead!
+        *
         * You can also pass arguments for a constructor:
-        *       t3lib_div::makeInstance('myClass', $arg1, $arg2,  ..., $argN)
+        *              t3lib_div::makeInstance('myClass', $arg1, $arg2,  ..., $argN)
         *
-        * @param       string          Class name to instantiate
-        * @return      object          A reference to the object
+        * @throws      InvalidArgumentException if classname is an empty string
+        * @param       string          $className
+        *                      name of the class to instantiate, must not be empty
+        * @return      object          the created instance
         */
        public static function makeInstance($className) {
-                       // holds references of singletons
-               static $instances = array();
+               if ($className === '') {
+                       throw new InvalidArgumentException('$classname must not be empty.', 1288965219);
+               }
+
+                       // Determine final class name which must be instantiated, this takes XCLASS handling
+                       // into account. Cache in a local array to save some cycles for consecutive calls.
+               if (!isset(self::$finalClassNameRegister[$className])) {
+                       self::$finalClassNameRegister[$className] = self::getClassName($className);
+               }
+               $finalClassName = self::$finalClassNameRegister[$className];
+
+                       // Return singleton instance if it is already registered
+               if (isset(self::$singletonInstances[$finalClassName])) {
+                       return self::$singletonInstances[$finalClassName];
+               }
+
+                       // Return instance if it has been injected by addInstance()
+               if (isset(self::$nonSingletonInstances[$finalClassName])
+                       && !empty(self::$nonSingletonInstances[$finalClassName])
+               ) {
+                       return array_shift(self::$nonSingletonInstances[$finalClassName]);
+               }
 
-                       // Get final classname
-               $className = self::getClassName($className);
+                       // Create new instance and call constructor with parameters
+               if (func_num_args() > 1) {
+                       $constructorArguments = func_get_args();
+                       array_shift($constructorArguments);
 
-               if (isset($instances[$className])) {
-                               // it's a singleton, get the existing instance
-                       $instance = $instances[$className];
+                       $reflectedClass = new ReflectionClass($finalClassName);
+                       $instance = $reflectedClass->newInstanceArgs($constructorArguments);
                } else {
-                       if (func_num_args() > 1) {
-                                       // getting the constructor arguments by removing this
-                                       // method's first argument (the class name)
-                               $constructorArguments = func_get_args();
-                               array_shift($constructorArguments);
-
-                               $reflectedClass = new ReflectionClass($className);
-                               $instance = $reflectedClass->newInstanceArgs($constructorArguments);
-                       } else {
-                               $instance = new $className;
-                       }
+                       $instance = new $finalClassName;
+               }
 
-                       if ($instance instanceof t3lib_Singleton) {
-                                       // it's a singleton, save the instance for later reuse
-                               $instances[$className] = $instance;
-                       }
+                       // Register new singleton instance
+               if ($instance instanceof t3lib_Singleton) {
+                       self::$singletonInstances[$finalClassName] = $instance;
                }
 
                return $instance;
@@ -5420,7 +5308,104 @@ final class t3lib_div {
         * @return      string          Final class name to instantiate with "new [classname]"
         */
        protected function getClassName($className) {
-               return (class_exists($className) && class_exists('ux_' . $className, FALSE) ? self::getClassName('ux_' . $className) : $className);
+               if (class_exists($className)) {
+                       while (class_exists('ux_' . $className, FALSE)) {
+                               $className = 'ux_' . $className;
+                       }
+               }
+
+               return $className;
+       }
+
+       /**
+        * Sets the instance of a singleton class to be returned by makeInstance.
+        *
+        * If this function is called multiple times for the same $className,
+        * makeInstance will return the last set instance.
+        *
+        * Warning: This is a helper method for unit tests. Do not call this directly in production code!
+        *
+        * @see makeInstance
+        * @param string $className
+        *        the name of the class to set, must not be empty
+        * @param t3lib_Singleton $instance
+        *        the instance to set, must be an instance of $className
+        * @return void
+        */
+       public static function setSingletonInstance($className, t3lib_Singleton $instance) {
+               self::checkInstanceClassName($className, $instance);
+               self::$singletonInstances[$className] = $instance;
+       }
+
+       /**
+        * Sets the instance of a non-singleton class to be returned by makeInstance.
+        *
+        * If this function is called multiple times for the same $className,
+        * makeInstance will return the instances in the order in which they have
+        * been added (FIFO).
+        *
+        * Warning: This is a helper method for unit tests. Do not call this directly in production code!
+        *
+        * @see makeInstance
+        * @throws InvalidArgumentException if class extends t3lib_Singleton
+        * @param string $className
+        *        the name of the class to set, must not be empty
+        * @param object $instance
+        *        the instance to set, must be an instance of $className
+        * @return void
+        */
+       public static function addInstance($className, $instance) {
+               self::checkInstanceClassName($className, $instance);
+
+               if ($instance instanceof t3lib_Singleton) {
+                       throw new InvalidArgumentException(
+                               '$instance must not be an instance of t3lib_Singleton. ' .
+                                       'For setting singletons, please use setSingletonInstance.',
+                               1288969325
+                       );
+               }
+
+               if (!isset(self::$nonSingletonInstances[$className])) {
+                       self::$nonSingletonInstances[$className] = array();
+               }
+               self::$nonSingletonInstances[$className][] = $instance;
+       }
+
+       /**
+        * Checks that $className is non-empty and that $instance is an instance of
+        * $className.
+        *
+        * @throws InvalidArgumentException if $className is empty or if $instance is no instance of $className
+        * @param string $className a class name
+        * @param object $instance an object
+        * @return void
+        */
+       protected static function checkInstanceClassName($className, $instance) {
+               if ($className === '') {
+                       throw new InvalidArgumentException('$className must not be empty.', 1288967479);
+               }
+               if (!($instance instanceof $className)) {
+                       throw new InvalidArgumentException(
+                               '$instance must be an instance of ' . $className . ', but actually is an instance of ' . get_class($instance) . '.',
+                               1288967686
+                       );
+               }
+       }
+
+       /**
+        * Purge all instances returned by makeInstance.
+        *
+        * This function is most useful when called from tearDown in a testcase
+        * to drop any instances that have been created by the tests.
+        *
+        * Warning: This is a helper method for unit tests. Do not call this directly in production code!
+        *
+        * @see makeInstance
+        * @return void
+        */
+       public static function purgeInstances() {
+               self::$singletonInstances = array();
+               self::$nonSingletonInstances = array();
        }
 
        /**
@@ -5458,7 +5443,7 @@ final class t3lib_div {
                                        if (is_object($obj)) {
                                                if (!@is_callable(array($obj, 'init'))) {
                                                                // use silent logging??? I don't think so.
-                                                       die ('Broken service:' . self::view_array($info));
+                                                       die ('Broken service:' . t3lib_utility_Debug::viewArray($info));
                                                }
                                                $obj->info = $info;
                                                if ($obj->init()) { // service available?
@@ -5875,18 +5860,26 @@ final class t3lib_div {
                                        fwrite($file, date($dateFormat . ' ' . $timeFormat) . $msgLine . LF);
                                        flock($file, LOCK_UN); // release the lock
                                        fclose($file);
+                                       self::fixPermissions($destination);
                                }
                        }
                                // send message per mail
                        elseif ($type == 'mail') {
                                list($to, $from) = explode('/', $destination);
-                               t3lib_utility_Mail::mail($to, 'Warning - error in TYPO3 installation',
-                                               'Host: ' . $TYPO3_CONF_VARS['SC_OPTIONS']['t3lib/class.t3lib_div.php']['systemLogHost'] . LF .
+                               if (!t3lib_div::validEmail($from)) {
+                                       $from = t3lib_utility_Mail::getSystemFrom();
+                               }
+                               /** @var $mail t3lib_mail_Message */
+                               $mail = t3lib_div::makeInstance('t3lib_mail_Message');
+                               $mail->setTo($to)
+                                               ->setFrom($from)
+                                               ->setSubject('Warning - error in TYPO3 installation')
+                                               ->setBody('Host: ' . $TYPO3_CONF_VARS['SC_OPTIONS']['t3lib/class.t3lib_div.php']['systemLogHost'] . LF .
                                                                'Extension: ' . $extKey . LF .
                                                                'Severity: ' . $severity . LF .
-                                                               LF . $msg,
-                                       ($from ? 'From: ' . $from : '')
+                                                               LF . $msg
                                );
+                               $mail->send();
                        }
                                // use the PHP error log
                        elseif ($type == 'error_log') {
@@ -5954,6 +5947,7 @@ final class t3lib_div {
                                @fwrite($file, $date . $msg . LF);
                                flock($file, LOCK_UN); // release the lock
                                @fclose($file);
+                               self::fixPermissions($destination);
                        }
                }
 
@@ -5964,7 +5958,7 @@ final class t3lib_div {
 
                        // do not use console in login screen
                if (stripos($log, 'console') !== FALSE && isset($GLOBALS['BE_USER']->user['uid'])) {
-                       self::debug($msg, $date, 'Deprecation Log');
+                       t3lib_utility_Debug::debug($msg, $date, 'Deprecation Log');
                }
        }
 
@@ -6014,7 +6008,7 @@ final class t3lib_div {
 
                        // write a longer message to the deprecation log: <function> <annotion> - <trace> (<source>)
                $logMsg = $trail[1]['class'] . $trail[1]['type'] . $trail[1]['function'];
-               $logMsg .= '() - ' . $msg . ' - ' . self::debug_trail();
+               $logMsg .= '() - ' . $msg.' - ' . t3lib_utility_Debug::debugTrail();
                $logMsg .= ' (' . substr($function->getFileName(), strlen(PATH_site)) . '#' . $function->getStartLine() . ')';
                self::deprecationLog($logMsg);
        }
@@ -6051,60 +6045,7 @@ final class t3lib_div {
         * @return      string          Compiled command that deals with IM6 & GraphicsMagick
         */
        public static function imageMagickCommand($command, $parameters, $path = '') {
-               $gfxConf = $GLOBALS['TYPO3_CONF_VARS']['GFX'];
-               $isExt = (TYPO3_OS == 'WIN' ? '.exe' : '');
-               $switchCompositeParameters = FALSE;
-
-               if (!$path) {
-                       $path = $gfxConf['im_path'];
-               }
-               $path = self::fixWindowsFilePath($path);
-
-               $im_version = strtolower($gfxConf['im_version_5']);
-               $combineScript = $gfxConf['im_combine_filename'] ? trim($gfxConf['im_combine_filename']) : 'combine';
-
-               if ($command === 'combine') { // This is only used internally, has no effect outside
-                       $command = 'composite';
-               }
-
-                       // Compile the path & command
-               if ($im_version === 'gm') {
-                       $switchCompositeParameters = TRUE;
-                       $path = escapeshellarg($path . 'gm' . $isExt) . ' ' . $command;
-               } else {
-                       if ($im_version === 'im6') {
-                               $switchCompositeParameters = TRUE;
-                       }
-                       $path = escapeshellarg($path . (($command == 'composite') ? $combineScript : $command) . $isExt);
-               }
-
-                       // strip profile information for thumbnails and reduce their size
-               if ($parameters && $command != 'identify' && $gfxConf['im_useStripProfileByDefault'] && $gfxConf['im_stripProfileCommand'] != '') {
-                       if (strpos($parameters, $gfxConf['im_stripProfileCommand']) === FALSE) {
-                                       // Determine whether the strip profile action has be disabled by TypoScript:
-                               if ($parameters !== '-version' && strpos($parameters, '###SkipStripProfile###') === FALSE) {
-                                       $parameters = $gfxConf['im_stripProfileCommand'] . ' ' . $parameters;
-                               } else {
-                                       $parameters = str_replace('###SkipStripProfile###', '', $parameters);
-                               }
-                       }
-               }
-
-               $cmdLine = $path . ' ' . $parameters;
-
-               if ($command == 'composite' && $switchCompositeParameters) { // Because of some weird incompatibilities between ImageMagick 4 and 6 (plus GraphicsMagick), it is needed to change the parameters order under some preconditions
-                       $paramsArr = self::unQuoteFilenames($parameters);
-
-                       if (count($paramsArr) > 5) { // The mask image has been specified => swap the parameters
-                               $tmp = $paramsArr[count($paramsArr) - 3];
-                               $paramsArr[count($paramsArr) - 3] = $paramsArr[count($paramsArr) - 4];
-                               $paramsArr[count($paramsArr) - 4] = $tmp;
-                       }
-
-                       $cmdLine = $path . ' ' . implode(' ', $paramsArr);
-               }
-
-               return $cmdLine;
+               return t3lib_utility_Command::imageMagickCommand($command, $parameters, $path);
        }
 
        /**
@@ -6122,14 +6063,13 @@ final class t3lib_div {
                        if ($quoteActive > -1) {
                                $paramsArr[$quoteActive] .= ' ' . $v;
                                unset($paramsArr[$k]);
-                               if (preg_match('/"$/', $v)) {
+                               if (substr($v, -1) === $paramsArr[$quoteActive][0]) {
                                        $quoteActive = -1;
                                }
-
                        } elseif (!trim($v)) {
                                unset($paramsArr[$k]); // Remove empty elements
 
-                       } elseif (preg_match('/^"/', $v)) {
+                       } elseif (preg_match('/^(["\'])/', $v) && substr($v, -1) !== $v[0]) {
                                $quoteActive = $k;
                        }
                }
@@ -6137,6 +6077,8 @@ final class t3lib_div {
                if ($unQuote) {
                        foreach ($paramsArr as $key => &$val) {
                                $val = preg_replace('/(^"|"$)/', '', $val);
+                               $val = preg_replace('/(^\'|\'$)/', '', $val);
+
                        }
                }
                        // return reindexed array
@@ -6210,4 +6152,4 @@ final class t3lib_div {
        }
 }
 
-?>
\ No newline at end of file
+?>