eZ Publish  [trunk]
ezfilehandler.php
Go to the documentation of this file.
00001 <?php
00002 /**
00003  * File containing the eZFileHandler class.
00004  *
00005  * @copyright Copyright (C) 1999-2012 eZ Systems AS. All rights reserved.
00006  * @license http://www.gnu.org/licenses/gpl-2.0.txt GNU General Public License v2
00007  * @version //autogentag//
00008  * @package lib
00009  */
00010 
00011 /*!
00012   \class eZFileHandler ezfilehandler.php
00013   \brief Interface for file handlers
00014 
00015   Generic interface for all file handlers.
00016 
00017   Using this class i divided into five areas, they are:
00018 
00019   File handling using open(), close(), read(), write() and flush().
00020 
00021   File position handling using seek(), tell(), rewind() and eof().
00022 
00023   Quick output of the file using passtrough().
00024 
00025   Error handling with error(), errorString() and errorNumber().
00026 
00027   \h1 Creating specific handlers
00028 
00029   The file handlers must inherit from this class and reimplement
00030   some virtual functions.
00031 
00032   For dealing with files the following functions must be reimplemented.
00033   doOpen(), doClose(), doRead(), doWrite() and doFlush().
00034 
00035   For dealing with file positions the following functions must be reimplemented.
00036   doSeek(), doTell(), doRewind() and doEOF().
00037 
00038   For dealing with quick output the passtrough() function must be reimplemented,
00039   if not reimplemented the default implemententation will simply read n bytes
00040   using read() and output it with print.
00041 
00042   Also the errorString() and errorNumber() functions must be reimplemented
00043   to provide proper error handler. The error() function is not required
00044   to be implemented since it has a default implementation, for speed
00045   it might be wise to implement the function.
00046 
00047   This class will handle most of the generic logic, like checking that
00048   the filename is correct and if the open succeded, and give error
00049   messages based on this.
00050   The actual implementations will only have to execute the specific
00051   code and return a result.
00052 
00053 */
00054 
00055 class eZFileHandler
00056 {
00057     /*!
00058      Initializes the handler. Optionally the parameters \a $filename
00059      and \a $mode may be provided to automatically open the file.
00060     */
00061     function eZFileHandler( $handlerIdentifier = false, $handlerName = false )
00062     {
00063         if ( !$handlerIdentifier )
00064         {
00065             $handlerIdentifier = 'plain';
00066             $handlerName = 'Plain';
00067         }
00068         $this->Name = $handlerName;
00069         $this->Identifier = $handlerIdentifier;
00070         $this->FileName = false;
00071         $this->FileHandler = false;
00072         $this->Mode = false;
00073         $this->IsOpen = false;
00074         $this->IsBinary = false;
00075     }
00076 
00077     /*!
00078      \return \c true if a file is opened, \c false otherwise.
00079     */
00080     function isOpen()
00081     {
00082         return $this->IsOpen;
00083     }
00084 
00085     /*!
00086      \return \c true if the file was opened in binary mode.
00087     */
00088     function isBinaryMode()
00089     {
00090         return $this->IsBinary;
00091     }
00092 
00093     /*!
00094      \return the filename currently in use.
00095     */
00096     function filename()
00097     {
00098         return $this->FileName;
00099     }
00100 
00101     /*!
00102      \return the mode which was used to open the currently used file.
00103     */
00104     function mode()
00105     {
00106         return $this->Mode;
00107     }
00108 
00109     /*!
00110      \return the name of current handler.
00111      \sa identifier
00112     */
00113     function name()
00114     {
00115         return $this->Name;
00116     }
00117 
00118     /*!
00119      \return the identifier of the current handler.
00120      \sa name
00121     */
00122     function identifier()
00123     {
00124         return $this->Identifier;
00125     }
00126 
00127     /*!
00128      \return true if this handler can be used.
00129      \note The default implementation is to return \c true for all handlers.
00130     */
00131     static function isAvailable()
00132     {
00133         return true;
00134     }
00135 
00136     /*!
00137      Links the file \a $sourceFilename to \a $destinationFilename.
00138      If \a $destinationFilename is a directory then the filename is taken from \a $sourceFilename and appended to the destination.
00139      It will use symbolic links for the operating system that support it and file copy for all others.
00140      \param $symbolicLink if \c true then the files will be made as symbolic links, otherwise as hard links.
00141      \return \c true if sucessful or \c false if the copy failed.
00142     */
00143     static function linkCopy( $sourceFilename, $destinationFilename, $symbolicLink = true )
00144     {
00145         if ( in_array( eZSys::osType(),
00146                        array( 'unix', 'linux', 'mac' ) ) )
00147         {
00148             if ( $symbolicLink )
00149                 $result = eZFileHandler::symlink( $sourceFilename, $destinationFilename );
00150             else
00151                 $result = eZFileHandler::link( $sourceFilename, $destinationFilename );
00152             if ( $result )
00153                 return $result;
00154             return eZFileHandler::copy( $sourceFilename, $destinationFilename );
00155         }
00156         else
00157         {
00158             return eZFileHandler::copy( $sourceFilename, $destinationFilename );
00159         }
00160     }
00161 
00162     /*!
00163      Creates a symbolic link to the file \a $sourceFilename on the destination \a $destinationFilename.
00164      This means that if someone tries to open \a $destinationFilename they will infact open \a $sourceFilename.
00165      If \a $destinationFilename is a directory then the filename is taken from \a $sourceFilename and appended to the destination.
00166      It will first try to rename the file and if that does not work copy the file and unlink.
00167      \return \c true if sucessful or \c false if the copy failed.
00168     */
00169     static function symlink( $sourceFilename, $destinationFilename )
00170     {
00171         if ( !file_exists( $sourceFilename ) and
00172              !is_link( $sourceFilename ) )
00173         {
00174             eZDebug::writeError( "Cannot symbolicly link to file $sourceFilename, it does not exist", __METHOD__ );
00175             return false;
00176         }
00177         $isDir = false;
00178         if ( is_dir( $destinationFilename ) )
00179         {
00180             $isDir = true;
00181             $dirPosition = strrpos( $sourceFilename, '/' );
00182             $filePosition = 0;
00183             if ( $dirPosition !== false )
00184                 $filePosition = $dirPosition + 1;
00185             if ( strlen( $destinationFilename ) > 0 and
00186                  $destinationFilename[strlen( $destinationFilename ) - 1] == '/' )
00187                 $destinationFilename .= substr( $sourceFilename, $filePosition );
00188             else
00189                 $destinationFilename .= '/' . substr( $sourceFilename, $filePosition );
00190         }
00191         $destinationFilename = preg_replace( "#/+#", '/', $destinationFilename );
00192         $sourceDir = $sourceFilename;
00193         $sourceName = false;
00194         $sourceDirPos = strrpos( $sourceDir, '/' );
00195         if ( $sourceDirPos !== false )
00196         {
00197             $sourceName = substr( $sourceDir, $sourceDirPos + 1 );
00198             $sourceDir = substr( $sourceDir, 0, $sourceDirPos );
00199         }
00200         $commonOffset = 0;
00201         for ( $i = 0; $i < strlen( $sourceFilename ) and $i < strlen( $sourceDir ); ++$i )
00202         {
00203             if ( $sourceFilename[$i] != $sourceDir[$i] )
00204                 break;
00205             $commonOffset = $i;
00206         }
00207         if ( $commonOffset > 0 )
00208             $sourceDir = substr( $sourceDir, $commonOffset + 1 );
00209         $directoryCount = substr_count( $sourceDir, '/' );
00210         $cdupText = str_repeat( '../', $directoryCount );
00211         if ( file_exists( $destinationFilename ) and
00212              !is_dir( $destinationFilename ) )
00213         {
00214             if ( !@unlink( $destinationFilename ) )
00215             {
00216                 eZDebug::writeError( "Cannot symbolicly link to file $sourceFilename on destination $destinationFilename, destination file cannot be removed", __METHOD__ );
00217                 return false;
00218             }
00219         }
00220         if ( $sourceDir )
00221             $sourceDir = $sourceDir . '/' . $sourceName;
00222         else
00223             $sourceDir = $sourceName;
00224         if ( symlink( $cdupText . $sourceDir, $destinationFilename ) )
00225         {
00226             return true;
00227         }
00228         eZDebug::writeError( "Failed to symbolicly link to $sourceFilename on destination $destinationFilename", __METHOD__ );
00229         return false;
00230     }
00231 
00232     /*!
00233      Creates a symbolic link to the file \a $sourceFilename on the destination \a $destinationFilename.
00234      This means that if someone tries to open \a $destinationFilename they will infact open \a $sourceFilename.
00235      If \a $destinationFilename is a directory then the filename is taken from \a $sourceFilename and appended to the destination.
00236      It will first try to rename the file and if that does not work copy the file and unlink.
00237      \return \c true if sucessful or \c false if the copy failed.
00238     */
00239     static function link( $sourceFilename, $destinationFilename )
00240     {
00241         if ( !file_exists( $sourceFilename ) and
00242              !is_link( $sourceFilename ) )
00243         {
00244             eZDebug::writeError( "Cannot link to file $sourceFilename, it does not exist", __METHOD__ );
00245             return false;
00246         }
00247         $isDir = false;
00248         if ( is_dir( $destinationFilename ) )
00249         {
00250             $isDir = true;
00251             $dirPosition = strrpos( $sourceFilename, '/' );
00252             $filePosition = 0;
00253             if ( $dirPosition !== false )
00254                 $filePosition = $dirPosition + 1;
00255             if ( strlen( $destinationFilename ) > 0 and
00256                  $destinationFilename[strlen( $destinationFilename ) - 1] == '/' )
00257                 $destinationFilename .= substr( $sourceFilename, $filePosition );
00258             else
00259                 $destinationFilename .= '/' . substr( $sourceFilename, $filePosition );
00260         }
00261         $destinationFilename = preg_replace( "#/+#", '/', $destinationFilename );
00262         if ( file_exists( $destinationFilename ) and
00263              !is_dir( $destinationFilename ) )
00264         {
00265             if ( !@unlink( $destinationFilename ) )
00266             {
00267                 eZDebug::writeError( "Cannot link to file $sourceFilename on destination $destinationFilename, destination file cannot be removed", __METHOD__ );
00268                 return false;
00269             }
00270         }
00271         if ( link( $sourceFilename, $destinationFilename ) )
00272         {
00273             return true;
00274         }
00275         eZDebug::writeError( "Failed to link to $sourceFilename on destination $destinationFilename", __METHOD__ );
00276         return false;
00277     }
00278 
00279     /*!
00280      Moves the file \a $sourceFilename to \a $destinationFilename.
00281      If \a $destinationFilename is a directory then the filename is taken from \a $sourceFilename and appended to the destination.
00282      It will first try to rename the file and if that does not work copy the file and unlink.
00283      \return \c true if sucessful or \c false if the copy failed.
00284     */
00285     static function move( $sourceFilename, $destinationFilename )
00286     {
00287         if ( !file_exists( $sourceFilename ) and
00288              !is_link( $sourceFilename ) )
00289         {
00290             eZDebug::writeError( "Cannot rename file $sourceFilename, it does not exist", __METHOD__ );
00291             return false;
00292         }
00293         $isDir = false;
00294         if ( is_dir( $destinationFilename ) )
00295         {
00296             $isDir = true;
00297             $dirPosition = strrpos( $sourceFilename, '/' );
00298             $filePosition = 0;
00299             if ( $dirPosition !== false )
00300                 $filePosition = $dirPosition + 1;
00301             if ( strlen( $destinationFilename ) > 0 and
00302                  $destinationFilename[strlen( $destinationFilename ) - 1] == '/' )
00303                 $destinationFilename .= substr( $sourceFilename, $filePosition );
00304             else
00305                 $destinationFilename .= '/' . substr( $sourceFilename, $filePosition );
00306         }
00307 
00308 
00309         // If source and destination are the same files we just return true
00310         if ( $sourceFilename == $destinationFilename )
00311         {
00312             return true;
00313         }
00314 
00315         if ( file_exists( $destinationFilename ) and
00316              !is_dir( $destinationFilename ) )
00317         {
00318             if ( !@unlink( $destinationFilename ) )
00319             {
00320                 eZDebug::writeError( "Cannot move file $sourceFilename to destination $destinationFilename, destination file cannot be removed", __METHOD__ );
00321                 return false;
00322             }
00323         }
00324         $isLink = false;
00325         if ( is_link( $sourceFilename ) )
00326         {
00327             $isLink = true;
00328         }
00329         if ( !$isLink and
00330              eZFile::rename( $sourceFilename, $destinationFilename ) )
00331         {
00332             return true;
00333         }
00334         if ( eZFileHandler::copy( $sourceFilename, $destinationFilename ) )
00335         {
00336             if ( !@unlink( $sourceFilename ) )
00337             {
00338                 eZDebug::writeError( "Cannot remove source file $sourceFilename, file was not succesfully moved", __METHOD__ );
00339                 @unlink( $destinationFilename );
00340                 return false;
00341             }
00342             return true;
00343         }
00344                 eZDebug::writeError( "Failed to copy $sourceFilename to $destinationFilename, file was not succesfully moved", __METHOD__ );
00345         return false;
00346     }
00347 
00348     /*!
00349      Copies the file \a $sourceFilename to \a $destinationFilename.
00350      \return \c true if sucessful or \c false if the copy failed.
00351     */
00352     static function copy( $sourceFilename, $destinationFilename )
00353     {
00354         if ( is_dir( $sourceFilename ) )
00355         {
00356             eZDebug::writeError( "Unable to copy directory $sourceFilename, use eZDir::copy instead", __METHOD__ );
00357             return false;
00358         }
00359         $sourceFD = @fopen( $sourceFilename, 'rb' );
00360         if ( !$sourceFD )
00361         {
00362             eZDebug::writeError( "Unable to open source file $sourceFilename in read mode", __METHOD__ );
00363             return false;
00364         }
00365         if ( is_dir( $destinationFilename ) )
00366         {
00367             $dirPosition = strrpos( $sourceFilename, '/' );
00368             $filePosition = 0;
00369             if ( $dirPosition !== false )
00370                 $filePosition = $dirPosition + 1;
00371             if ( strlen( $destinationFilename ) > 0 and
00372                  $destinationFilename[strlen( $destinationFilename ) - 1] == '/' )
00373                 $destinationFilename .= substr( $sourceFilename, $filePosition );
00374             else
00375                 $destinationFilename .= '/' . substr( $sourceFilename, $filePosition );
00376         }
00377 
00378         // If source and destination are the same files we just return true
00379         if ( $sourceFilename == $destinationFilename )
00380         {
00381             @fclose( $sourceFD );
00382             return true;
00383         }
00384 
00385         $destinationFD = fopen( $destinationFilename, 'wb' );
00386         chmod( $destinationFilename, octdec( eZINI::instance()->variable( 'FileSettings', 'StorageFilePermissions' ) ) );
00387         if ( !$destinationFD )
00388         {
00389             @fclose( $sourceFD );
00390             eZDebug::writeError( "Unable to open destination file $destinationFilename in write mode", __METHOD__ );
00391             return false;
00392         }
00393         $bytesCopied = 0;
00394         do
00395         {
00396             $data = fread( $sourceFD, 4096 );
00397             if ( strlen( $data ) == 0 )
00398                 break;
00399             fwrite( $destinationFD, $data );
00400             $bytesCopied += strlen( $data );
00401         } while( true );
00402 
00403         @fclose( $sourceFD );
00404         @fclose( $destinationFD );
00405         return true;
00406     }
00407 
00408     /*!
00409      \return \c true if the filename \a $filename exists.
00410      If \a $filename is not specified the filename is taken from the one used in open().
00411     */
00412     function exists( $filename = false )
00413     {
00414         if ( !$filename )
00415             $filename = $this->FileName;
00416         return $this->doExists( $filename );
00417     }
00418 
00419     /*!
00420      \return \c true if \a $filename is a directory.
00421     */
00422     function isDirectory( $filename = false )
00423     {
00424         if ( !$filename )
00425             $filename = $this->FileName;
00426         return $this->doIsDirectory( $filename );
00427     }
00428 
00429     /*!
00430      \return \c true if \a $filename is executable.
00431     */
00432     function isExecutable( $filename = false )
00433     {
00434         if ( !$filename )
00435             $filename = $this->FileName;
00436         return $this->doIsExecutable( $filename );
00437     }
00438 
00439     /*!
00440      \return \c true if \a $filename is a file.
00441     */
00442     function isFile( $filename = false )
00443     {
00444         if ( !$filename )
00445             $filename = $this->FileName;
00446         return $this->doIsFile( $filename );
00447     }
00448 
00449     /*!
00450      \return \c true if \a $filename is a link.
00451     */
00452     function isLink( $filename = false )
00453     {
00454         if ( !$filename )
00455             $filename = $this->FileName;
00456         return $this->doIsLink( $filename );
00457     }
00458 
00459     /*!
00460      \return \c true if \a $filename is readable.
00461     */
00462     function isReadable( $filename = false )
00463     {
00464         if ( !$filename )
00465             $filename = $this->FileName;
00466         return $this->doIsReadable( $filename );
00467     }
00468 
00469     /*!
00470      \return \c true if \a $filename is writeable.
00471     */
00472     function isWriteable( $filename = false )
00473     {
00474         if ( !$filename )
00475             $filename = $this->FileName;
00476         return $this->doIsWriteable( $filename );
00477     }
00478 
00479     /*!
00480      \return the statitistics for the file \a $filename.
00481     */
00482     function statistics( $filename = false )
00483     {
00484         if ( !$filename )
00485             $filename = $this->FileName;
00486         return $this->doStatistics( $filename );
00487     }
00488 
00489     /*!
00490      Tries to open the file \a $filename with mode \a $mode and returns
00491      the file resource if succesful.
00492      \return \c false if the file could not be opened.
00493      \param $mode If false the file will be opened in read mode using 'r'
00494      \param $binaryFile If true file will be opened in binary mode (default),
00495                         otherwise text mode is used.
00496      \note Parameter $binaryFile will only have effect on the Windows operating system.
00497     */
00498     function open( $filename, $mode, $binaryFile = true )
00499     {
00500         if ( $this->isOpen() )
00501         {
00502             eZDebug::writeError( "A file is already open (" . $this->FileName . "), close the file before opening a new one.",
00503                                  'eZFileHandler::open' );
00504             return false;
00505         }
00506         if ( !$filename and
00507              !$this->FileName )
00508         {
00509             eZDebug::writeError( "The supplied filename is empty and no filename set for object, cannot open any file", __METHOD__ );
00510             return false;
00511         }
00512         if ( !$filename )
00513             $filename = $this->FileName;
00514         if ( !$mode )
00515             $mode = 'r';
00516         if ( strpos( $mode, 'b' ) !== false )
00517             $binaryFile = true;
00518         $mode = str_replace( 'b', '', $mode );
00519         if ( $binaryFile )
00520             $mode .= 'b';
00521         $this->IsBinary = $binaryFile;
00522         $result = $this->doOpen( $filename, $mode );
00523         if ( $result )
00524         {
00525 //             eZDebugSetting::writeNotice( 'lib-ezfile-openclose',
00526 //                                          "Opened file $filename with mode '$mode'",
00527 //                                          'eZFileHandler::open' );
00528             $this->FileName = $filename;
00529             $this->Mode = $mode;
00530             $this->IsOpen = true;
00531         }
00532         else
00533             eZDebug::writeError( "Failed opening file $filename with mode $mode", __METHOD__ );
00534         return $result;
00535     }
00536 
00537     /*!
00538      Tries to close an open file and returns \c true if succesful, \c false otherwise.
00539     */
00540     function close()
00541     {
00542         if ( !$this->isOpen() )
00543         {
00544             eZDebug::writeError( "A file is not currently opened, cannot close.", __METHOD__ );
00545             return false;
00546         }
00547 //         eZDebugSetting::writeNotice( 'lib-ezfile-openclose',
00548 //                                      "Closing file " . $this->filename() . " with previously opened mode '" . $this->mode() . "'",
00549 //                                      'eZFileHandler::close' );
00550         $result = $this->doClose();
00551         if ( !$result )
00552             eZDebug::writeError( "Failed closing file " . $this->FileName . " opened with mode " . $this->Mode, __METHOD__ );
00553         else
00554             $this->IsOpen = false;
00555         return $result;
00556     }
00557 
00558     /*!
00559      Tries to unlink the file from the file system.
00560     */
00561     function unlink( $filename = false )
00562     {
00563         if ( !$filename )
00564         {
00565             if ( $this->isOpen() )
00566                 $this->close();
00567             $filename = $this->FileName;
00568         }
00569         $result = eZFileHandler::doUnlink( $filename );
00570         if ( !$result )
00571             eZDebug::writeError( "Failed unlinking file " . $filename, __METHOD__ );
00572         return $result;
00573     }
00574 
00575     /*!
00576      Renames the file \a $sourceFilename to \a $destinationFilename.
00577      If \a $sourceFilename is not supplied then filename() is used,
00578      it will also close the current file connection and reopen it again if
00579      was already open.
00580     */
00581     function rename( $destinationFilename, $sourceFilename = false )
00582     {
00583         if ( !$sourceFilename )
00584         {
00585             $wasOpen = $this->isOpen();
00586             if ( $wasOpen )
00587                 $this->close();
00588             $result = $this->doRename( $destinationFilename, $this->filename() );
00589             if ( $wasOpen and
00590                  $result )
00591                 $this->open( $destinationFilename, $this->mode() );
00592         }
00593         else
00594             $result = $this->doRename( $destinationFilename, $sourceFilename );
00595         return $result;
00596     }
00597 
00598     /*!
00599      Reads up to \a $length bytes from file. Reading stops when
00600      \a $length has been read or \c EOF is reached, whichever comes first.
00601      If the optional parameter \a $length is not specified it will
00602      read bytes until \c EOF is reached.
00603      \return a \c string or \c false if something fails.
00604     */
00605     function read( $length = false )
00606     {
00607         if ( !$this->isOpen() )
00608         {
00609             eZDebug::writeError( "A file is not currently opened, cannot read.", __METHOD__ );
00610             return false;
00611         }
00612         if ( $length < 0 )
00613         {
00614             eZDebug::writeError( "length cannot be negative ($length)", __METHOD__ );
00615             return false;
00616         }
00617         if ( $length )
00618         {
00619             return $this->doRead( $length );
00620         }
00621         else
00622         {
00623             $string = '';
00624             $data = false;
00625             do
00626             {
00627                 $data = $this->doRead( 1024 );
00628                 if ( $data )
00629                     $string .= $data;
00630             } while( $data );
00631             return $string;
00632         }
00633     }
00634 
00635     /*!
00636      Writes the content of the string \a $data to the file.
00637      If optional \c $length parameter is supplied writing will stop after
00638      length is reached or the end of the string is reached, whichever comes first.
00639      \return the number of bytes that was written.
00640     */
00641     function write( $data, $length = false )
00642     {
00643         if ( !$this->isOpen() )
00644         {
00645             eZDebug::writeError( "A file is not currently opened, cannot write.", __METHOD__ );
00646             return false;
00647         }
00648         if ( $length < 0 )
00649         {
00650             eZDebug::writeError( "length cannot be negative ($length)", __METHOD__ );
00651             return false;
00652         }
00653         return $this->doWrite( $data, $length );
00654     }
00655 
00656     /*!
00657      Force a write of all buffered data.
00658      \return \c true if succesful or \c false if something failed.
00659     */
00660     function flush()
00661     {
00662         if ( !$this->isOpen() )
00663         {
00664             eZDebug::writeError( "A file is not currently opened, cannot flush.", __METHOD__ );
00665             return false;
00666         }
00667         return $this->doFlush();
00668     }
00669 
00670     /*!
00671      Seeks to position in file determined by \a $offset and \a $whence.
00672      - SEEK_SET - Set position equal to offset bytes.
00673      - SEEK_CUR - Set position to current location plus offset.
00674      - SEEK_END - Set position to end-of-file plus offset. (To move to a position before the end-of-file, you need to pass a negative value in offset.)
00675 
00676      \note Not all handlers supports all types for \a $whence
00677      \return \c 0 if succesful or \c -1 if something failed.
00678     */
00679     function seek( $offset, $whence = SEEK_SET )
00680     {
00681         if ( !$this->isOpen() )
00682         {
00683             eZDebug::writeError( "A file is not currently opened, cannot seek.", __METHOD__ );
00684             return false;
00685         }
00686         return $this->doSeek( $offset, $whence );
00687     }
00688 
00689     /*!
00690      Rewinds the file position to the beginning of the file.
00691      \return \c 0 if something went wrong.
00692     */
00693     function rewind()
00694     {
00695         if ( !$this->isOpen() )
00696         {
00697             eZDebug::writeError( "A file is not currently opened, cannot rewind.", __METHOD__ );
00698             return false;
00699         }
00700         return $this->doRewind();
00701     }
00702 
00703     /*!
00704      Tells the current file position.
00705      \return \c false if something failed.
00706     */
00707     function tell()
00708     {
00709         if ( !$this->isOpen() )
00710         {
00711             eZDebug::writeError( "A file is not currently opened, cannot tell position.", __METHOD__ );
00712             return false;
00713         }
00714         return $this->doTell();
00715     }
00716 
00717     /*!
00718      \return \c true if the file pointer is at the end of the file or an error occured, otherwise \c false.
00719     */
00720     function eof()
00721     {
00722         if ( !$this->isOpen() )
00723         {
00724             eZDebug::writeError( "A file is not currently opened, cannot report EOF status.", __METHOD__ );
00725             return false;
00726         }
00727         return $this->doEOF();
00728     }
00729 
00730     /*!
00731      Passes the data from the file to the standard output.
00732      \param $closeFile If \c true the file will be closed after output is done.
00733      \return \c false if something failed.
00734     */
00735     function passtrough( $closeFile = true )
00736     {
00737         if ( !$this->isOpen() )
00738         {
00739             eZDebug::writeError( "A file is not currently opened, cannot do a data passtrough.", __METHOD__ );
00740             return false;
00741         }
00742         return $this->doPasstrough( $closeFile );
00743     }
00744 
00745     /*!
00746      \pure
00747      Does the actual file opening.
00748      \sa open
00749     */
00750     function doOpen( $filename, $mode )
00751     {
00752         $this->FileHandler = @fopen( $filename, $mode );
00753         return $this->FileHandler;
00754     }
00755 
00756     /*!
00757      \pure
00758      Does the actual file closing.
00759      \sa close
00760     */
00761     function doClose()
00762     {
00763         $result = @fclose( $this->FileHandler );
00764         $this->FileHandler = false;
00765         return $result;
00766     }
00767 
00768     /*!
00769      \pure
00770      Does the actual file unlinking.
00771      \sa unlink
00772     */
00773     static function doUnlink( $filename )
00774     {
00775         return @unlink( $filename );
00776     }
00777 
00778     /*!
00779      \pure
00780      Does the actual file exists checking.
00781      \sa exists
00782     */
00783     static function doExists( $filename )
00784     {
00785         return file_exists( $filename );
00786     }
00787 
00788     /*!
00789      \pure
00790      Does the actual directory checking.
00791      \sa isDirectory
00792     */
00793     static function doIsDirectory( $filename )
00794     {
00795         return is_dir( $filename );
00796     }
00797 
00798     /*!
00799      \pure
00800      Does the actual executable checking.
00801      \sa isExecutable
00802     */
00803     static function doIsExecutable( $filename )
00804     {
00805         return is_executable( $filename );
00806     }
00807 
00808     /*!
00809      \pure
00810      Does the actual file checking.
00811      \sa isFile
00812     */
00813     static function doIsFile( $filename )
00814     {
00815         return is_file( $filename );
00816     }
00817 
00818     /*!
00819      \pure
00820      Does the actual link checking.
00821      \sa isLink
00822     */
00823     static function doIsLink( $filename )
00824     {
00825         return is_link( $filename );
00826     }
00827 
00828     /*!
00829      \pure
00830      Does the actual readable checking.
00831      \sa isReadable
00832     */
00833     static function doIsReadable( $filename )
00834     {
00835         return is_readable( $filename );
00836     }
00837 
00838     /*!
00839      \pure
00840      Does the actual writeable checking.
00841      \sa isWriteable
00842     */
00843     static function doIsWriteable( $filename )
00844     {
00845         return is_writable( $filename );
00846     }
00847 
00848     /*!
00849      \pure
00850      Does the actual writeable checking.
00851      \sa isWriteable
00852     */
00853     static function doStatistics( $filename )
00854     {
00855         return @stat( $filename );
00856     }
00857 
00858     /*!
00859      \pure
00860      Does the actual file seek.
00861      \sa seek
00862     */
00863     function doSeek( $offset, $whence )
00864     {
00865         return @fseek( $this->FileHandler, $offset, $whence );
00866     }
00867 
00868     /*!
00869      Does the actual file rewind.
00870      \sa rewind
00871      \note Default implementation calls seek with offset set to 0 from the file start.
00872     */
00873     function doRewind()
00874     {
00875         $this->doSeek( 0, SEEK_SET );
00876     }
00877 
00878     /*!
00879      \pure
00880      Does the actual file telling.
00881      \sa tell
00882     */
00883     function doTell()
00884     {
00885         return @ftell( $this->FileHandler );
00886     }
00887 
00888     /*!
00889      \pure
00890      Does the actual file eof detection.
00891      \sa eof
00892     */
00893     function doEOF()
00894     {
00895         return @feof( $this->FileHandler );
00896     }
00897 
00898     /*!
00899      \pure
00900      Does the actual file passtrough.
00901      \sa eof
00902     */
00903     function doPasstrough( $closeFile = true )
00904     {
00905         $result = @fpassthru( $this->FileHandler );
00906         if ( $closeFile )
00907         {
00908             @fclose( $this->FileHandler );
00909             $this->FileHandler = false;
00910         }
00911     }
00912 
00913     /*!
00914      \pure
00915      Does the actual file reading.
00916      \sa read
00917     */
00918     function doRead( $length = false )
00919     {
00920         return @fread( $this->FileHandler, $length );
00921     }
00922 
00923     /*!
00924      \pure
00925      Does the actual file writing.
00926      \sa write
00927     */
00928     function doWrite( $data, $length = false )
00929     {
00930         if ( $length === false )
00931             return @fwrite( $this->FileHandler, $data );
00932         else
00933             return @fwrite( $this->FileHandler, $data, $length );
00934     }
00935 
00936     /*!
00937      \pure
00938      Does the actual file flushing.
00939      \sa flush
00940     */
00941     function doFlush()
00942     {
00943         return @fflush( $this->FileHandler );
00944     }
00945 
00946     /*!
00947      \pure
00948      Does the actual file renaming.
00949      \sa rename
00950     */
00951     static function doRename( $destinationFilename, $sourceFilename )
00952     {
00953         return eZFile::rename( $sourceFilename, $destinationFilename );
00954     }
00955 
00956     /*!
00957      Returns error data as an associative array, the array contains:
00958      - string - The error string
00959      - number - The error number
00960      \note The default implementation calls errorString() and errorNumber().
00961     */
00962     function error()
00963     {
00964         return array( 'string' => $this->errorString(),
00965                       'number' => $this->errorNumber() );
00966     }
00967 
00968     /*!
00969      \pure
00970      \return the error string from the last error that occured.
00971     */
00972     function errorString()
00973     {
00974         return false;
00975     }
00976 
00977     /*!
00978      \pure
00979      \return the error number from the last error that occured.
00980     */
00981     function errorNumber()
00982     {
00983         return false;
00984     }
00985 
00986     /*!
00987      Creates a copy of the current handler and returns a reference to the copy.
00988      \note The default does a simple copy of \c $this, this method must be reimplemented for specific handlers.
00989     */
00990     function duplicate()
00991     {
00992         $copy = clone $this;
00993         return $copy;
00994     }
00995 
00996     /*!
00997      Returns the handler for the identifier \a $identifier.
00998              The parameters \a $filename, \a $mode and \a $binaryFile is passed to the handler.
00999      \return \c false if the handler could not be created.
01000     */
01001     /**
01002      * Returns a shared instance of the eZFileHandler class.
01003      * $identifier if set is used to specify specific file handlers as
01004      * defined in file.ini [FileSettings]Handlers.
01005      * If $filename and later params are set, then file is opened straigt away.
01006      *
01007      * @param string|false $identifier Global eZFileHandler used if false
01008      * @param string|false $filename
01009      * @param string|false $mode set to 'r' if false
01010      * @param bool $binaryFile Binary or text mode, default true.
01011      * @return eZFileHandler|false
01012      */
01013     static function instance( $identifier, $filename = false, $mode = false, $binaryFile = true )
01014     {
01015         $ini = eZINI::instance( 'file.ini' );
01016         $handlers = $ini->variable( 'FileSettings', 'Handlers' );
01017         $instance = false;
01018         if ( !$identifier )
01019         {
01020             $instance = new eZFileHandler();
01021         }
01022         else if ( isset( $handlers[$identifier] ) )
01023         {
01024             $className = $handlers[$identifier];
01025             $includeFile = 'lib/ezfile/classes/' . $className . '.php';
01026             include_once( $includeFile );
01027             $instance = new $className();
01028             if ( $instance->isAvailable() )
01029             {
01030                 if ( $filename )
01031                     $instance->open( $filename, $mode, $binaryFile );
01032             }
01033             else
01034             {
01035                 unset( $instance );
01036                 $instance = false;
01037             }
01038         }
01039         return $instance;
01040     }
01041 
01042     /// \privatesection
01043     public $Name;
01044     public $FileName;
01045     public $Mode;
01046     public $IsBinary;
01047     public $IsOpen;
01048 }
01049 
01050 ?>