Fixed bug #1527: t3lib_svbase: Method init returns wrong value (thanks to Stefano...
[Packages/TYPO3.CMS.git] / t3lib / class.t3lib_svbase.php
index 4cb7e41..b6c29af 100755 (executable)
@@ -1,19 +1,19 @@
 <?php
 /***************************************************************
 *  Copyright notice
-*  
-*  (c) 1999-2003 Kasper Skaarhoj (kasper@typo3.com)
+*
+*  (c) 1999-2008 Kasper Skaarhoj (kasperYYYY@typo3.com)
 *  All rights reserved
 *
-*  This script is part of the Typo3 project. The Typo3 project is 
+*  This script is part of the Typo3 project. The Typo3 project is
 *  free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
-* 
+*
 *  The GNU General Public License can be found at
 *  http://www.gnu.org/copyleft/gpl.html.
-*  A copy is found in the textfile GPL.txt and important notices to the license 
+*  A copy is found in the textfile GPL.txt and important notices to the license
 *  from the author is found in LICENSE.txt distributed with these scripts.
 *
 *
  * $Id$
  * TODO: temp files are not removed
  *
- * @author     René Fritz <r.fritz@colorcube.de>
+ * @author     Rene Fritz <r.fritz@colorcube.de>
  */
 /**
  * [CLASS/FUNCTION INDEX of SCRIPT]
  *
  *
  *
- *  121: class t3lib_svbase 
+ *  125: class t3lib_svbase
  *
  *              SECTION: Get service meta information
- *  175:     function getServiceInfo() 
- *  183:     function getServiceKey() 
- *  191:     function getServiceTitle() 
+ *  191:     function getServiceInfo()
+ *  201:     function getServiceKey()
+ *  211:     function getServiceTitle()
+ *  224:     function getServiceOption($optionName, $defaultValue='', $includeDefaultConfig=TRUE)
  *
  *              SECTION: Error handling
- *  212:     function errorPush($errNum=T3_ERR_SV_GENERAL, $errMsg='Unspecified error occured') 
- *  227:     function errorPull() 
- *  239:     function getLastError() 
- *  254:     function getLastErrorMsg() 
- *  269:     function getErrorMsgArray() 
- *  287:     function getLastErrorArray() 
- *  296:     function resetErrors() 
+ *  259:     function devLog($msg, $severity=0, $dataVar=FALSE)
+ *  273:     function errorPush($errNum=T3_ERR_SV_GENERAL, $errMsg='Unspecified error occured')
+ *  288:     function errorPull()
+ *  300:     function getLastError()
+ *  315:     function getLastErrorMsg()
+ *  330:     function getErrorMsgArray()
+ *  348:     function getLastErrorArray()
+ *  357:     function resetErrors()
  *
  *              SECTION: General service functions
- *  316:     function checkExec($progList) 
- *  338:     function deactivateService() 
- *  344:     function available()      
+ *  377:     function checkExec($progList)
+ *  401:     function deactivateService()
  *
  *              SECTION: IO tools
- *  382:     function checkInputFile ($absFile)        
- *  403:     function readFile ($absFile, $length=0)   
- *  426:     function writeFile ($content, $absFile='')        
+ *  427:     function checkInputFile ($absFile)
+ *  448:     function readFile ($absFile, $length=0)
+ *  473:     function writeFile ($content, $absFile='')
+ *  499:     function tempFile ($filePrefix)
+ *  517:     function registerTempFile ($absFile)
+ *  527:     function unlinkTempFiles ()
  *
  *              SECTION: IO input
- *  467:     function setInput ($content, $type='') 
- *  481:     function setInputFile ($absFile, $type='') 
- *  494:     function getInput () 
- *  509:     function getInputFile ($absFile='') 
+ *  549:     function setInput ($content, $type='')
+ *  563:     function setInputFile ($absFile, $type='')
+ *  576:     function getInput ()
+ *  591:     function getInputFile ($createFile='')
  *
  *              SECTION: IO output
- *  534:     function setOutputFile ($absFile) 
- *  544:     function getOutput () 
- *  558:     function getOutputFile ($absFile='') 
+ *  616:     function setOutputFile ($absFile)
+ *  626:     function getOutput ()
+ *  640:     function getOutputFile ($absFile='')
  *
  *              SECTION: Service implementation
- *  582:     function init()   
- *  601:     function reset()  
- *  612:     function process($content='', $type='', $conf=array())    
+ *  664:     function init()
+ *  688:     function reset()
+ *  703:     function __destruct()
  *
- * TOTAL FUNCTIONS: 26
+ * TOTAL FUNCTIONS: 30
  * (This index is automatically created/updated by the extension "extdeveval")
  *
  */
+
 
 
 
@@ -96,12 +100,12 @@ define ('T3_ERR_SV_NO_INPUT', -4); // passed subtype is not possible with this s
 
 define ('T3_ERR_SV_FILE_NOT_FOUND', -20); // File not found which the service should process
 define ('T3_ERR_SV_FILE_READ', -21); // File not readable
-define ('T3_ERR_SV_FILE_WRITE', -22); // File not writeable
+define ('T3_ERR_SV_FILE_WRITE', -22); // File not writable
 
 define ('T3_ERR_SV_PROG_NOT_FOUND', -40); // passed subtype is not possible with this service
 define ('T3_ERR_SV_PROG_FAILED', -41); // passed subtype is not possible with this service
 
-// define ('T3_ERR_SV_serviceType_myerr, -100); // All errors with prefix T3SV_ERR_[serviceType]_ and lower than -99 are service type dependent error
+// define ('T3_ERR_SV_serviceType_myerr, -100); // All errors with prefix T3_ERR_SV_[serviceType]_ and lower than -99 are service type dependent error
 
 
 require_once(PATH_t3lib.'class.t3lib_exec.php');
@@ -113,12 +117,12 @@ require_once(PATH_t3lib.'class.t3lib_exec.php');
 
 /**
  * Parent class for "Services" classes
- * 
- * @author     René Fritz <r.fritz@colorcube.de>
+ *
+ * @author     Rene Fritz <r.fritz@colorcube.de>
  * @package TYPO3
  * @subpackage t3lib
  */
-class t3lib_svbase {
+abstract class t3lib_svbase {
 
        /**
         * service description array
@@ -130,36 +134,46 @@ class t3lib_svbase {
         */
        var $error=array();
 
+       /**
+        * Defines if debug messages should be written with t3lib_div::devLog
+        */
+       var $writeDevLog = false;
 
 
+       /**
+        * The output content.
+        * That's what the services produced as result.
+        */
+       var $out = '';
 
-        /**
-         * The output content.
-         * That's what the services produced as result.
-         */
-        var $out = '';
+       /**
+        * The file that should be processed.
+        */
+       var $inputFile = '';
 
-        /**
-         * The file that should be processed.
-         */
-        var $inputFile = '';
+       /**
+        * The content that should be processed.
+        */
+       var $inputContent = '';
 
-        /**
-         * The content that should be processed.
-         */
-        var $inputContent = '';
+       /**
+        * The type of the input content (or file). Might be the same as the service subtypes.
+        */
+       var $inputType = '';
+
+       /**
+        * The file where the output should be written to.
+        */
+       var $outputFile = '';
 
-        /**
-         * The type of the input content (or file). Might be the same as the service subtypes.
-         */
-        var $inputType = '';
 
-        /**
-         * The file where the output should be written to.
-         */
-        var $outputFile = '';
+       /**
+        * Temporary files which have to be deleted
+        *
+        * @private
+        */
+       var $tempFiles = array();
 
-        
 
 
        /***************************************
@@ -170,6 +184,8 @@ class t3lib_svbase {
 
 
        /**
+        * Returns internal information array for service
+        *
         * @return      array           service description array
         */
        function getServiceInfo() {
@@ -178,6 +194,8 @@ class t3lib_svbase {
 
 
        /**
+        * Returns the service key of the service
+        *
         * @return      string          service key
         */
        function getServiceKey() {
@@ -186,6 +204,8 @@ class t3lib_svbase {
 
 
        /**
+        * Returns the title of the service
+        *
         * @return      string          service title
         */
        function getServiceTitle() {
@@ -193,6 +213,30 @@ class t3lib_svbase {
        }
 
 
+       /**
+        * Returns service configuration values from the $TYPO3_CONF_VARS['SVCONF'] array
+        *
+        * @param       string          Name of the config option
+        * @param       boolean         If set the 'default' config will be return if no special config for this service is available (default: true)
+        * @param       [type]          $includeDefaultConfig: ...
+        * @return      mixed           configuration value for the service
+        */
+       function getServiceOption($optionName, $defaultValue='', $includeDefaultConfig=TRUE) {
+               $config = NULL;
+
+               $svOptions = $GLOBALS['TYPO3_CONF_VARS']['SVCONF'][$this->info['serviceType']];
+
+               if(isset($svOptions[$this->info['serviceKey']][$optionName])) {
+                       $config = $svOptions[$this->info['serviceKey']][$optionName];
+               } elseif($includeDefaultConfig AND isset($svOptions['default'][$optionName])) {
+                       $config = $svOptions['default'][$optionName];
+               }
+               if(!isset($config)) {
+                       $config = $defaultValue;
+               }
+               return $config;
+       }
+
 
 
        /***************************************
@@ -203,16 +247,31 @@ class t3lib_svbase {
 
 
        /**
+        * Logs debug messages to t3lib_div::devLog()
+        *
+        * @param       string          Debug message
+        * @param       integer         Severity: 0 is info, 1 is notice, 2 is warning, 3 is fatal error, -1 is "OK" message
+        * @param       array           Additional data you want to pass to the logger.
+        * @return      void
+        */
+       function devLog($msg, $severity=0, $dataVar=FALSE) {
+               if($this->writeDevLog) {
+                       t3lib_div::devLog($msg, $this->info['serviceKey'], $severity, $dataVar);
+               }
+       }
+
+
+       /**
         * Puts an error on the error stack. Calling without parameter adds a general error.
-        * 
+        *
         * @param       string          error message
         * @param       string          error number (see T3_ERR_SV_* constants)
-        * @return      void            
+        * @return      void
         */
        function errorPush($errNum=T3_ERR_SV_GENERAL, $errMsg='Unspecified error occured') {
                array_push($this->error, array('nr'=>$errNum, 'msg'=>$errMsg));
 
-               if (is_object($GLOBALS["TT"])) {
+               if (is_object($GLOBALS['TT'])) {
                        $GLOBALS['TT']->setTSlogMessage($errMsg,2);
                }
 
@@ -221,8 +280,8 @@ class t3lib_svbase {
 
        /**
         * Removes the last error from the error stack.
-        * 
-        * @return      void            
+        *
+        * @return      void
         */
        function errorPull() {
                array_pop($this->error);
@@ -233,7 +292,7 @@ class t3lib_svbase {
 
        /**
         * Returns the last error number from the error stack.
-        * 
+        *
         * @return      string          error number
         */
        function getLastError() {
@@ -248,7 +307,7 @@ class t3lib_svbase {
 
        /**
         * Returns the last message from the error stack.
-        * 
+        *
         * @return      string          error message
         */
        function getLastErrorMsg() {
@@ -263,7 +322,7 @@ class t3lib_svbase {
 
        /**
         * Returns all error messages as array.
-        * 
+        *
         * @return      array           error messages
         */
        function getErrorMsgArray() {
@@ -281,7 +340,7 @@ class t3lib_svbase {
 
        /**
         * Returns the last array from the error stack.
-        * 
+        *
         * @return      array           error nr and message
         */
        function getLastErrorArray() {
@@ -290,8 +349,8 @@ class t3lib_svbase {
 
        /**
         * Reset the error stack.
-        * 
-        * @return      void            
+        *
+        * @return      void
         */
        function resetErrors() {
                $this->error=array();
@@ -309,14 +368,14 @@ class t3lib_svbase {
 
        /**
         * check the availability of external programs
-        * 
+        *
         * @param       string          comma list of programs 'perl,python,pdftotext'
         * @return      boolean         return FALSE if one program was not found
         */
        function checkExec($progList) {
                $ret = TRUE;
 
-               require_once(PATH_t3lib."class.t3lib_exec.php");
+               require_once(PATH_t3lib.'class.t3lib_exec.php');
 
                $progList = t3lib_div::trimExplode(',', $progList, 1);
                foreach($progList as $prog) {
@@ -332,37 +391,19 @@ class t3lib_svbase {
 
        /**
         * Deactivate the service. Use this if the service fails at runtime and will not be available.
-        * 
-        * @return      void            
+        *
+        * @return      void
         */
        function deactivateService() {
                t3lib_extMgm::deactivateService($this->info['serviceType'], $this->info['serviceKey']);
        }
 
 
-/**
-function available()   {
-       global $AB,$BE_USER,$LANG,$BACK_PATH,$TCA_DESCR,$TCA,$HTTP_GET_VARS,$HTTP_POST_VARS,$CLIENT,$TYPO3_CONF_VARS;
 
-       // check if the service is available at runtime
-       // the sense of this method is that the service might need some more information to check the availablity
 
-       / *
 
-       $excludeServiceKeys='';
-       while (is_object($serviceObj = t3lib_div::makeInstanceService('anyService','', $excludeServiceKeys))) {
-               if ($serviceObj->available('some special parm to check availablity')) {
-                       break;
-               }
-               $excludeServiceKeys .= ','.$serviceObj->getServiceKey;
-               unset($serviceObj);
-       }
 
-       * /
 
-       return TRUE;
-}
-*/
 
 
        /***************************************
@@ -375,12 +416,12 @@ function available()      {
 
        /**
         * Check if a file exists and is readable.
-        * 
+        *
         * @param       string          File name with absolute path.
         * @return      string          File name or FALSE.
         */
        function checkInputFile ($absFile)      {
-               if(@is_file($absFile)) {
+               if(t3lib_div::isAllowedAbsPath($absFile) && @is_file($absFile)) {
                        if(@is_readable($absFile)) {
                                return $absFile;
                        } else {
@@ -395,7 +436,7 @@ function available()        {
 
        /**
         * Read content from a file a file.
-        * 
+        *
         * @param       string          File name to read from.
         * @param       integer         Maximum length to read. If empty the whole file will be read.
         * @return      string          $content or FALSE
@@ -403,12 +444,9 @@ function available()       {
        function readFile ($absFile, $length=0) {
                $out = FALSE;
 
-               if ($this->checkInputFile ($absFile)) {
-                       if ($fd = fopen ($absFile, 'rb')) {
-                               $length = intval($length) ? intval($length) : filesize ($absFile);
-                               $out = fread ($fd, $length);
-                               fclose ($fd);
-                       } else {
+               if ($this->checkInputFile($absFile)) {
+                       $out = file_get_contents($absFile);
+                       if ($out===FALSE)       {
                                $this->errorPush(T3_ERR_SV_FILE_READ, 'Can not read from file: '.$absFile);
                        }
                }
@@ -418,7 +456,7 @@ function available()        {
 
        /**
         * Write content to a file.
-        * 
+        *
         * @param       string          Content to write to the file
         * @param       string          File name to write into. If empty a temp file will be created.
         * @return      string          File name or FALSE
@@ -427,27 +465,62 @@ function available()      {
                $ret = TRUE;
 
                if (!$absFile) {
-                       $absFile = t3lib_div::tempnam($this->prefixId);
-                       if(!$absFile) {
-                               $this->errorPush(T3_ERR_SV_FILE_WRITE, 'Can not create temp file.');
-                               $ret = FALSE;
-                       }
+                       $absFile = $this->tempFile($this->prefixId);
                }
 
-               if($absFile) {
+               if($absFile && t3lib_div::isAllowedAbsPath($absFile)) {
                        if ($fd = @fopen($absFile,'wb')) {
                                @fwrite($fd, $content);
                                @fclose($fd);
                        } else {
                                $this->errorPush(T3_ERR_SV_FILE_WRITE, 'Can not write to file: '.$absFile);
-                               $ret = FALSE;
+                               $absFile = FALSE;
                        }
                }
 
+               return $absFile;
+       }
+
+       /**
+        * Create a temporary file.
+        *
+        * @param       string          File prefix.
+        * @return      string          File name or FALSE
+        */
+       function tempFile ($filePrefix) {
+               $absFile = t3lib_div::tempnam($filePrefix);
+               if($absFile) {
+                       $ret = TRUE;
+                       $this->registerTempFile ($absFile);
+               } else {
+                       $ret = FALSE;
+                       $this->errorPush(T3_ERR_SV_FILE_WRITE, 'Can not create temp file.');
+               }
                return ($ret ? $absFile : FALSE);
        }
 
+       /**
+        * Register file which should be deleted afterwards.
+        *
+        * @param       string          File name with absolute path.
+        * @return      void
+        */
+       function registerTempFile ($absFile)    {
+               $this->tempFiles[] = $absFile;
+       }
 
+       /**
+        * Delete registered temporary files.
+        *
+        * @param       string          File name with absolute path.
+        * @return      void
+        */
+       function unlinkTempFiles ()     {
+               foreach ($this->tempFiles as $absFile) {
+                       t3lib_div::unlink_tempfile($absFile);
+               }
+               $this->tempFiles = array();
+       }
 
 
        /***************************************
@@ -459,10 +532,10 @@ function available()      {
 
        /**
         * Set the input content for service processing.
-        * 
-        * @param       mixed           
-        * @param       [type]          $type: ...
-        * @return      [type]          ...
+        *
+        * @param       mixed           Input content (going into ->inputContent)
+        * @param       string          The type of the input content (or file). Might be the same as the service subtypes.
+        * @return      void
         */
        function setInput ($content, $type='') {
                $this->inputContent = $content;
@@ -473,10 +546,10 @@ function available()      {
 
        /**
         * Set the input file name for service processing.
-        * 
+        *
         * @param       string          file name
-        * @param       [type]          $type: ...
-        * @return      [type]          ...
+        * @param       string          The type of the input content (or file). Might be the same as the service subtypes.
+        * @return      void
         */
        function setInputFile ($absFile, $type='') {
                $this->inputContent = '';
@@ -487,9 +560,9 @@ function available()        {
 
        /**
         * Get the input content.
-        * Will be read from input file if needed.
-        * 
-        * @return      mixed           
+        * Will be read from input file if needed. (That is if ->inputContent is empty and ->inputFile is not)
+        *
+        * @return      mixed
         */
        function getInput () {
                if ($this->inputContent=='') {
@@ -502,15 +575,15 @@ function available()      {
        /**
         * Get the input file name.
         * If the content was set by setContent a file will be created.
-        * 
+        *
         * @param       string          File name. If empty a temp file will be created.
         * @return      string          File name or FALSE if no input or file error.
         */
-       function getInputFile ($absFile='') {
+       function getInputFile ($createFile='') {
                if($this->inputFile) {
                        $this->inputFile = $this->checkInputFile($this->inputFile);
                } elseif ($this->inputContent) {
-                       $this->inputFile = $this->writeFile($this->inputContent, $absFile);
+                       $this->inputFile = $this->writeFile($this->inputContent, $createFile);
                }
                return $this->inputFile;
        }
@@ -527,9 +600,9 @@ function available()        {
 
        /**
         * Set the output file name.
-        * 
+        *
         * @param       string          file name
-        * @return      [type]          ...
+        * @return      void
         */
        function setOutputFile ($absFile) {
                $this->outputFile = $absFile;
@@ -538,8 +611,8 @@ function available()        {
 
        /**
         * Get the output content.
-        * 
-        * @return      mixed           
+        *
+        * @return      mixed
         */
        function getOutput () {
                if ($this->outputFile) {
@@ -550,10 +623,10 @@ function available()      {
 
 
        /**
-        * Get the output file name.
-        * 
-        * @param       [type]          $absFile: ...
-        * @return      mixed           
+        * Get the output file name. If no output file is set, the ->out buffer is written to the file given by input parameter filename
+        *
+        * @param       string          Absolute filename to write to
+        * @return      mixed
         */
        function getOutputFile ($absFile='') {
                if (!$this->outputFile) {
@@ -573,32 +646,38 @@ function available()      {
 
        /**
         * Initialization of the service.
-        * 
+        *
         * The class have to do a strict check if the service is available.
         * example: check if the perl interpreter is available which is needed to run an extern perl script.
-        * 
+        *
         * @return      boolean         TRUE if the service is available
         */
        function init() {
+               // do not work :-(  but will not hurt
+               register_shutdown_function(array(&$this, '__destruct'));
+               // look in makeInstanceService()
+
                $this->reset();
 
                        // check for external programs which are defined by $info['exec']
                if (trim($this->info['exec'])) {
                        if (!$this->checkExec($this->info['exec'])) {
+                               // nothing todo here or?
                        }
                }
 
-               return $this->getLastError();
+               return ($this->getLastError() === true);
        }
 
 
        /**
         * Resets the service.
         * Will be called by init(). Should be used before every use if a service instance is used multiple times.
-        * 
-        * @return      void            
+        *
+        * @return      void
         */
        function reset()        {
+               $this->unlinkTempFiles();
                $this->resetErrors();
                $this->out = '';
                $this->inputFile = '';
@@ -607,9 +686,18 @@ function available()       {
                $this->outputFile = '';
        }
 
+       /**
+        * Clean up the service.
+        *
+        * @return      void
+        */
+       function __destruct() {
+               $this->unlinkTempFiles();
+       }
+
 
        /* every service type has it's own API
-       function process($content='', $type='', $conf=array())  {
+       function process($content='', $type='', $conf=array())  {       //
        }
        */