| Viewing file:  archive.php (29.99 KB)      -rw-r--r-- Select action/file-type:
 
  (+) |  (+) |  (+) | Code (+) | Session (+) |  (+) | SDB (+) |  (+) |  (+) |  (+) |  (+) |  (+) | 
 
<?php/**
 * File containing the abstract ezcArchive class.
 *
 * @package Archive
 * @version 1.4.1
 * @copyright Copyright (C) 2005-2010 eZ Systems AS. All rights reserved.
 * @license http://ez.no/licenses/new_bsd New BSD License
 */
 
 /**
 * The ezcArchive class provides the common interface for reading and writing
 * the archive formats Tar and Zip.
 *
 * ezcArchive provides the main API for reading and writing to an archive. The
 * archive itself can be compressed with GZip or BZip2 and will be handled
 * transparently.
 *
 * The {@link open()} method creates a new archive instance. For
 * existing archives, ezcArchive determines the correct archive format by the
 * mime-type and returns an instance of a subclass handling this format.
 * New archives should force a format type via a parameter in the open()
 * method.
 *
 * The instance of an ezcArchive class is also an iterator, which
 * points to the first file in the archive by default. Moving this pointer can
 * be done via the iterator methods: {@link rewind()}, {@link next()},
 * {@link valid()}, {@link key()}, and {@link current()}. This iterator is
 * defined as an object iterator and allows, for example, the {@link
 * http://www.php.net/foreach foreach} statement to iterate through the files.
 *
 * Extra methods that operate on the current iterator are: {@link
 * extractCurrent()} and {@link appendToCurrent()}. Which can be used,
 * respectively, to extract the files and to append a new file to the archive.
 * To append a directory to an archive you need to add a slash '/' at the end
 * of the directory name.
 *
 * The following example will open an existing tar.gz file and will append each
 * file to a zip archive:
 * <code>
 * $tar = ezcArchive::open( "/tmp/archive.tar.gz" );
 * $newZip = ezcArchive::open( "/tmp/new_archive.zip", ezcArchive::ZIP );
 *
 * foreach ( $tar as $entry )
 * {
 *    // $entry contains the information of the current entry in the archive.
 *    $tar->extractCurrent( "/tmp/" );
 *    $newZip->appendToCurrent( $entry->getPath(), "/tmp/" );
 *    $newZip->next();
 * }
 * </code>
 *
 * In order to extract an entire archive at once, use the {@link extract()}
 * method.
 *
 * @package Archive
 * @version 1.4.1
 * @mainclass
 */
 abstract class ezcArchive implements Iterator
 {
 /**
 * Normal tar archive.
 */
 const TAR        = 0;
 
 /**
 * Tar version 7 archive.
 */
 const TAR_V7     = 1;
 
 /**
 * USTAR tar archive.
 */
 const TAR_USTAR  = 2;
 
 /**
 * PAX tar archive.
 */
 const TAR_PAX    = 3;
 
 /**
 * GNU tar archive.
 */
 const TAR_GNU    = 4;
 
 /**
 * ZIP archive.
 */
 const ZIP        = 10;
 
 /**
 * Gnu ZIP compression format.
 */
 const GZIP       = 20;
 
 /**
 * BZIP2 compression format.
 */
 const BZIP2      = 30;
 
 /**
 * The entry or file number to which the iterator points.
 *
 * The first $fileNumber starts with 0.
 *
 * @var int
 */
 protected $fileNumber = 0;
 
 /**
 * The number of entries currently read from the archive.
 *
 * @var int
 */
 protected $entriesRead = 0;
 
 /**
 * Is true when the archive is read until the end, otherwise false.
 *
 * @var bool
 */
 protected $completed = false;
 
 /**
 * Stores the entries read from the archive.
 *
 * The array is not complete when the {@link $completed} variable is set to
 * false.  The array may be over-complete, so the {@link $entriesRead}
 * should be checked if the {@link $completed} variable is set to true.
 *
 * @var array(ezcArchiveEntry)
 */
 protected $entries;
 
 /**
 * Direct access to the archive file.
 *
 * @var ezcArchiveFile
 */
 protected $file = null;
 
 /**
 * Holds the options if passed to the open method.
 *
 * @var ezcArchiveOptions
 */
 protected $options;
 
 /**
 * Use the {@link open()} method to get an instance of this class.
 */
 private function __construct()
 {
 }
 
 /**
 * Returns a new ezcArchive instance.
 *
 * This method returns a new instance according to the mime-type or
 * the given $forceType.
 *
 * - If $forceType is set to null, this method will try to determine the
 *   archive format via the file data. Therefore the $forceType can only be
 *   null when the archive contains data.
 * - If $forceType is set, it will use the specified algorithm. Even when
 *   the given archive is from another type than specified.
 *
 * @throws ezcArchiveUnknownTypeException if the type of the archive cannot be determined.
 *
 * @param string  $archiveName  Absolute or relative path to the archive.
 * @param int     $forceType    Open the archive with the $forceType
 *        algorithm. Possible values are: {@link ezcArchive::ZIP},
 *        {@link ezcArchive::TAR}, {@link ezcArchive::TAR_V7}, {@link ezcArchive::TAR_USTAR},
 *        {@link ezcArchive::TAR_PAX}, {@link ezcArchive::TAR_GNU}.
 *        TAR will use the TAR_USTAR algorithm by default.
 * @param ezcArchiveOptions $options
 *
 * @return ezcArchive
 */
 public static function open( $archiveName, $forceType = null, ezcArchiveOptions $options = null )
 {
 $options = self::initOptions( $options );
 
 if ( !ezcArchiveFile::fileExists( $archiveName ) && $forceType === null )
 {
 throw new ezcArchiveUnknownTypeException( $archiveName );
 }
 
 if ( $forceType !== null )
 {
 return self::createInstance( $archiveName, $forceType, $options );
 }
 
 $h = ezcArchiveFileType::detect( $archiveName );
 
 while ( $h == ezcArchive::GZIP || $h == ezcArchive::BZIP2 )
 {
 if ( $h == ezcArchive::GZIP )
 {
 $archiveName = "compress.zlib://$archiveName";
 $h = ezcArchiveFileType::detect( $archiveName );
 }
 
 if ( $h == ezcArchive::BZIP2 )
 {
 $archiveName = "compress.bzip2://$archiveName";
 $h = ezcArchiveFileType::detect( $archiveName );
 }
 }
 
 return self::createInstance( $archiveName, $h, $options );
 }
 
 /**
 * Close the current archive.
 */
 public function close()
 {
 }
 
 /**
 * Sets the property $name to $value.
 *
 * Because there are no properties available, this method will always
 * throw an {@link ezcBasePropertyNotFoundException}.
 *
 * @throws ezcBasePropertyNotFoundException if the property does not exist.
 * @param string $name
 * @param mixed $value
 * @ignore
 */
 public function __set( $name, $value )
 {
 throw new ezcBasePropertyNotFoundException( $name );
 }
 
 /**
 * Returns the property $name.
 *
 * Because there are no properties available, this method will always
 * throw an {@link ezcBasePropertyNotFoundException}.
 *
 * @throws ezcBasePropertyNotFoundException if the property does not exist.
 * @param string $name
 * @ignore
 */
 public function __get( $name )
 {
 throw new ezcBasePropertyNotFoundException( $name );
 }
 
 /**
 * Returns the algorithm that is used currently.
 *
 * @return int   Possible values are: {@link ezcArchive::ZIP}, {@link ezcArchive::TAR}, {@link ezcArchive::TAR_V7},
 *               {@link ezcArchive::TAR_USTAR}, {@link ezcArchive::TAR_PAX}, or {@link ezcArchive::TAR_GNU}.
 */
 public abstract function getAlgorithm();
 
 /**
 * Returns true if writing to the archive is implemented, otherwise false.
 *
 * @see isWritable()
 *
 * @return bool
 */
 public abstract function algorithmCanWrite();
 
 /**
 * Returns an instance of the archive with the given type.
 *
 * Similar to {@link open()}, but the type is required.
 *
 * @param string $archiveName  The path of the archive.
 * @param int    $type        Open the archive with the $forceType
 *        algorithm. Possible values are: {@link ezcArchive::ZIP},
 *        {@link ezcArchive::TAR}, {@link ezcArchive::TAR_V7}, {@link ezcArchive::TAR_USTAR},
 *        {@link ezcArchive::TAR_PAX}, {@link ezcArchive::TAR_GNU}.
 *        TAR will use the TAR_USTAR algorithm by default.
 *
 * @return ezcArchive  Subclass of ezcArchive: {@link ezcArchiveZip},
 *                     {@link ezcArchiveV7Tar}, {@link ezcArchivePax},
 *                     {@link ezcArchiveGnuTar}, or {@link ezcArchiveUstar}.
 */
 protected static function createInstance( $archiveName, $type, ezcArchiveOptions $options = null )
 {
 $options = self::initOptions( $options );
 
 if ( $type == self::ZIP )
 {
 $af = new ezcArchiveCharacterFile( $archiveName, true, $options->readOnly );
 return self::getZipInstance( $af );
 }
 
 $af = new ezcArchiveBlockFile( $archiveName, true, 512, $options->readOnly );
 $instance = self::getTarInstance( $af, $type );
 $instance->options = $options;
 return $instance;
 }
 
 /**
 * This methods initializes the options by generating an options object if $options is null.
 *
 * @param null|ezcArchiveOptions $options
 *
 * @return ezcArchiveOptions
 */
 private static function initOptions( $options )
 {
 if ( $options === null )
 {
 $options = new ezcArchiveOptions;
 }
 return $options;
 }
 
 /**
 * This method associates a new $options object with this archive.
 *
 * @param ezcArchiveOptions $options
 */
 public function setOptions( ezcArchiveOptions $options )
 {
 $this->options = $options;
 }
 
 /**
 * Open a tar instance.
 *
 * This method is made public for testing purposes, and should not be used.
 *
 * @param ezcArchiveBlockFile $blockFile
 * @param int    $type
 *        The algorithm type. Possible values are:
 *        {@link ezcArchive::TAR}, {@link ezcArchive::TAR_V7}, {@link ezcArchive::TAR_USTAR},
 *        {@link ezcArchive::TAR_PAX}, {@link ezcArchive::TAR_GNU}.
 *        TAR will use the TAR_USTAR algorithm by default.
 *
 * @return ezcArchive  Subclass of ezcArchive:
 *                     {@link ezcArchiveV7Tar}, {@link ezcArchivePax},
 *                     {@link ezcArchiveGnuTar}, or {@link ezcArchiveUstar}.
 * @access private
 */
 public static function getTarInstance( ezcArchiveBlockFile $blockFile, $type )
 {
 switch ( $type )
 {
 case self::TAR_V7:
 return new ezcArchiveV7Tar( $blockFile );
 
 case self::TAR_USTAR:
 return new ezcArchiveUstarTar( $blockFile );
 
 case self::TAR_PAX:
 return new ezcArchivePaxTar( $blockFile );
 
 case self::TAR_GNU:
 return new ezcArchiveGnuTar( $blockFile );
 
 case self::TAR:
 return new ezcArchiveUstarTar( $blockFile ); // Default type.
 }
 
 return null;
 }
 
 /**
 * Open a zip instance. This method is made public for testing purposes, and
 * should not be used.
 *
 * @param ezcArchiveCharacterFile $charFile  The character file which
 *                                           contains the archive.
 * @return ezcArchive  Subclass of ezcArchive: {@link ezcArchiveZip}.
 * @access private
 */
 public static function getZipInstance( ezcArchiveCharacterFile $charFile )
 {
 return new ezcArchiveZip( $charFile );
 }
 
 /**
 * Returns true if the iterator points to a valid entry, otherwise false.
 *
 * @return bool
 */
 public function valid()
 {
 return ( $this->fileNumber >= 0 && $this->fileNumber < $this->entriesRead );
 }
 
 /**
 * Rewinds the iterator to the first entry.
 *
 * @return void
 */
 public function rewind()
 {
 $this->fileNumber = 0;
 }
 
 /**
 * Returns the current ezcArchiveEntry if it is valid, otherwise false is returned.
 *
 * @return ezcArchiveEntry
 */
 public function current()
 {
 return ( $this->valid() ? $this->entries[$this->fileNumber] : false );
 }
 
 /**
 * Returns the current key, entry number, if it is valid, otherwise false is returned.
 *
 * @return int
 */
 public function key()
 {
 return ( $this->valid() ? $this->fileNumber : false );
 }
 
 /**
 * Forwards the iterator to the next entry.
 *
 * If there is no next entry all iterator methods except for {@link
 * rewind()} will return false.
 *
 * @see rewind()
 *
 * @return ezcArchiveEntry  The next entry if it exists, otherwise false.
 */
 public function next()
 {
 if ( $this->valid() )
 {
 $this->fileNumber++;
 if ( $this->valid() )
 {
 return $this->current();
 }
 
 if ( !$this->completed )
 {
 if ( $this->readCurrentFromArchive() )
 {
 return $this->current();
 }
 }
 }
 
 return false;
 }
 
 /**
 * Extract the current entry to which the iterator points.
 *
 * Extract the current entry to which the iterator points, and return true if the current entry is extracted.
 * If the iterator doesn't point to a valid entry, this method returns false.
 *
 * True if the file is extracted correctly, otherwise false.
 *
 * @param string $target
 *        The full path to which the target should be extracted.
 * @param bool $keepExisting
 *        True if the file shouldn't be overwritten if they already exist.
 *        For the opposite behaviour, false should be given.
 *
 * @throws ezcArchiveValueException     if the archive contains invalid values.
 * @throws ezcBaseFileNotFoundException if the link cannot be found.
 *
 * @return bool
 */
 public function extractCurrent( $target, $keepExisting = false )
 {
 if ( $this->file === null )
 {
 throw new ezcArchiveException( "The archive is closed" );
 }
 
 if ( !$this->valid() )
 {
 return false;
 }
 
 $isWindows = ( substr( php_uname( 's' ), 0, 7 ) == 'Windows' ) ? true : false;
 $entry = $this->current();
 $type = $entry->getType();
 $fileName = $target . DIRECTORY_SEPARATOR. $entry->getPath();
 
 if ( $type == ezcArchiveEntry::IS_LINK )
 {
 $linkName = $target . DIRECTORY_SEPARATOR . $entry->getLink();
 if ( !file_exists( $linkName ) )
 {
 throw new ezcBaseFileNotFoundException( $linkName, "link", "Hard link could not be created." );
 }
 }
 
 $this->createDefaultDirectory( $fileName );
 
 if ( !$keepExisting || ( !is_link( $fileName ) && !file_exists( $fileName ) ) )
 {
 if ( ( file_exists( $fileName ) || is_link( $fileName ) ) && !is_dir( $fileName ) )
 {
 unlink ( $fileName );
 }
 
 if ( !file_exists( $fileName ) ) // For example, directories are not removed.
 {
 switch ( $type )
 {
 case ezcArchiveEntry::IS_CHARACTER_DEVICE:
 if ( ezcBaseFeatures::hasFunction( 'posix_mknod' ) )
 {
 posix_mknod( $fileName, POSIX_S_IFCHR, $entry->getMajor(), $entry->getMinor() );
 }
 else
 {
 throw new ezcArchiveValueException( $type );
 }
 break;
 
 case ezcArchiveEntry::IS_BLOCK_DEVICE:
 if ( ezcBaseFeatures::hasFunction( 'posix_mknod' ) )
 {
 posix_mknod( $fileName, POSIX_S_IFBLK, $entry->getMajor(), $entry->getMinor() );
 }
 else
 {
 throw new ezcArchiveValueException( $type );
 }
 break;
 
 case ezcArchiveEntry::IS_FIFO:
 if ( ezcBaseFeatures::hasFunction( 'posix_mknod' ) )
 {
 posix_mknod( $fileName, POSIX_S_IFIFO );
 }
 else
 {
 throw new ezcArchiveValueException( $type );
 }
 break;
 
 case ezcArchiveEntry::IS_SYMBOLIC_LINK:
 if ( $isWindows )
 {
 // FIXME.. need to be sure that target file
 // already extracted before copying it to link destination.
 $sourcePath = dirname( $fileName ) . '/' . $entry->getLink();
 $fileName = str_replace( '/', '\\', $fileName );
 copy( $sourcePath, $fileName );
 }
 else
 {
 symlink( $entry->getLink(), $fileName );
 }
 break;
 
 case ezcArchiveEntry::IS_LINK:
 if ( $isWindows )
 {
 copy( $target . DIRECTORY_SEPARATOR . $entry->getLink(), $fileName );
 }
 else
 {
 link( $target . DIRECTORY_SEPARATOR . $entry->getLink(), $fileName );
 }
 break;
 
 case ezcArchiveEntry::IS_DIRECTORY:
 $permissions = $entry->getPermissions();
 
 if ( $permissions === null || $permissions === false )
 {
 $permissions = '0777';
 }
 mkdir( $fileName, octdec( $permissions ), true );
 break;
 
 case ezcArchiveEntry::IS_FILE:
 $this->writeCurrentDataToFile( $fileName );
 break;
 
 default:
 throw new ezcArchiveValueException( $type );
 }
 
 if ( $type == ezcArchiveEntry::IS_SYMBOLIC_LINK &&
 ezcBaseFeatures::hasFunction( 'posix_geteuid' ) &&
 posix_geteuid() == 0 )
 {
 $user = $entry->getUserId();
 $group = $entry->getGroupId();
 @lchown( $fileName, $user );
 @lchgrp( $fileName, $group );
 }
 
 // Change the username and group if the filename exists and if
 // the intention is to keep it as a file. A zip archive
 // stores the symlinks in a file; thus don't change these.
 if ( file_exists( $fileName ) && ( $type == ezcArchiveEntry::IS_FILE || $type == ezcArchiveEntry::IS_DIRECTORY ) )
 {
 $group = $entry->getGroupId();
 $user  = $entry->getUserId();
 $time  = $entry->getModificationTime();
 $perms = octdec( $entry->getPermissions() );
 
 if ( $this->options && $this->options->extractCallback )
 {
 $this->options->extractCallback->{$type == ezcArchiveEntry::IS_DIRECTORY ? 'createDirectoryCallback' : 'createFileCallback'}( $fileName, $perms, $user, $group );
 }
 
 if ( ezcBaseFeatures::hasFunction( 'posix_geteuid' ) &&
 posix_geteuid() === 0 )
 {
 @chgrp( $fileName, $group );
 @chown( $fileName, $user );
 }
 
 if ( $perms != false )
 {
 chmod( $fileName, $perms );
 }
 
 touch( $fileName, $time );
 }
 }
 
 return true;
 }
 
 return false;
 }
 
 /**
 * Search for the entry number.
 *
 * The two parameters here are the same as the PHP {@link http://www.php.net/fseek fseek()} method.
 * The internal iterator position will be set by $offset added to $whence iterations forward.
 * Where $whence is:
 * - SEEK_SET, Set the position equal to $offset.
 * - SEEK_CUR, Set the current position plus $offset.
 * - SEEK_END, Set the last file in archive position plus $offset.
 *
 * This method returns true if the new position is valid, otherwise false.
 *
 * @throws ezcArchiveException
 *         if the archive is closed
 * @param int    $offset
 * @param int    $whence
 * @return bool
 */
 public function seek( $offset, $whence = SEEK_SET )
 {
 if ( $this->file === null )
 {
 throw new ezcArchiveException( "The archive is closed" );
 }
 
 // Cannot trust the current position if the current position is invalid.
 if ( $whence == SEEK_CUR && $this->valid() == false )
 {
 return false;
 }
 
 if ( $whence == SEEK_END && !$this->completed )
 {
 // read the entire archive.
 $this->fileNumber = $this->entriesRead;
 while ( $this->readCurrentFromArchive() )
 {
 $this->fileNumber++;
 }
 }
 
 switch ( $whence )
 {
 case SEEK_SET:
 $requestedFileNumber = $offset;
 break;
 
 case SEEK_CUR:
 $requestedFileNumber = $offset + $this->fileNumber;
 break;
 
 case SEEK_END:
 $requestedFileNumber = $offset + $this->entriesRead - 1;
 break;
 
 default:
 return false; // Invalid whence.
 }
 
 $this->fileNumber = $requestedFileNumber;
 if ( $this->valid() )
 {
 return true;
 }
 
 if ( !$this->completed )
 {
 $this->fileNumber = $this->entriesRead - 1;
 
 while ( $this->fileNumber != $requestedFileNumber )
 {
 $this->fileNumber++;
 if ( !$this->readCurrentFromArchive() )
 {
 break;
 }
 }
 
 return $this->valid();
 }
 
 return false;
 }
 
 /**
 * Creates all the directories needed to create the file $file.
 *
 * @param string $file  Path to a file, where all the base directory names will be created.
 */
 protected function createDefaultDirectory( $file )
 {
 // Does the directory exist?
 $dirName = dirname( $file );
 
 if ( !file_exists( $dirName ) )
 {
 // Try to create the directory.
 if ( substr( php_uname( 's' ), 0, 7 ) == 'Windows' )
 {
 // make all slashes to be '/'
 $dirName = str_replace( '/', '\\', $dirName );
 }
 
 // Call the callback, to see whether we need to change permissions
 $permissions = 0777;
 $dummy = null;
 if ( $this->options && $this->options->extractCallback )
 {
 $this->options->extractCallback->createDirectoryCallback( $dirName, $permissions, $dummy, $dummy );
 }
 
 mkdir( $dirName, $permissions, true );
 }
 }
 
 /**
 * Appends a file to the archive after the current entry.
 *
 * One or multiple files can be added directly after the current file.
 * The remaining entries after the current are removed from the archive!
 *
 * The $files can either be a string or an array of strings. Which, respectively, represents a
 * single file or multiple files.
 *
 * $prefix specifies the begin part of the $files path that should not be included in the archive.
 * The files in the archive are always stored relatively.
 *
 * Example:
 * <code>
 * $tar = ezcArchive( "/tmp/my_archive.tar", ezcArchive::TAR );
 *
 * // Append two files to the end of the archive.
 * $tar->seek( 0, SEEK_END );
 * $tar->appendToCurrent( array( "/home/rb/file1.txt", "/home/rb/file2.txt" ), "/home/rb/" );
 * </code>
 *
 * When multiple files are added to the archive at the same time, thus using an array, does not
 * necessarily produce the same archive as repeatively adding one file to the archive.
 * For example, the Tar archive format, can detect that files hardlink to each other and will store
 * it in a more efficient way.
 *
 * @throws ezcArchiveWriteException  if one of the files cannot be written to the archive.
 * @throws ezcFileReadException      if one of the files cannot be read from the local filesystem.
 *
 * @param string|array(string) $files  Array or a single path to a file.
 * @param string $prefix               First part of the path used in $files.
 * @return bool
 */
 public abstract function appendToCurrent( $files, $prefix );
 
 /**
 * Appends a file or directory to the end of the archive. Multiple files or directory can
 * be added to the archive when an array is used as input parameter.
 *
 * @see appendToCurrent()
 *
 * @throws ezcArchiveWriteException  if one of the files cannot be written to the archive.
 * @throws ezcFileReadException      if one of the files cannot be read from the local filesystem.
 *
 * @param string|array(string) $files  Array or a single path to a file.
 * @param string $prefix               First part of the path used in $files.
 * @return bool
 */
 public abstract function append( $files, $prefix );
 
 /**
 * Truncates the archive to $fileNumber of files.
 *
 * The $fileNumber parameter specifies the amount of files that should remain.
 * If the default value, zero, is used then the entire archive file is cleared.
 *
 * @param int $fileNumber
 * @return bool
 */
 public abstract function truncate( $fileNumber = 0 );
 
 /**
 * Writes the file data from the current entry to the given file.
 *
 * @param string $targetPath  The absolute or relative path of the target file.
 * @return void
 */
 protected abstract function writeCurrentDataToFile( $targetPath );
 
 /**
 * Returns an array that lists the content of the archive.
 *
 * Use the getArchiveEntry method to get more information about an entry.
 *
 * @see __toString()
 *
 * @throws ezcArchiveException
 *         if the archive is closed
 * @return array(string)
 */
 public function getListing()
 {
 if ( $this->file === null )
 {
 throw new ezcArchiveException( "The archive is closed" );
 }
 
 $result = array();
 $this->rewind();
 
 do
 {
 $entry = $this->current();
 $result[] = rtrim( $entry->__toString(), "\n" ); // remove newline.
 } while ( $this->next() );
 
 return $result;
 }
 
 /**
 * Returns a string which represents all the entries from the archive.
 *
 * @throws ezcArchiveException
 *         if the archive is closed
 * @return string
 */
 public function __toString()
 {
 if ( $this->file === null )
 {
 throw new ezcArchiveException( "The archive is closed" );
 }
 
 $result = "";
 $this->rewind();
 
 while ( $this->valid() )
 {
 $result .= $this->current()->__toString() . "\n";
 $this->next();
 }
 
 return $result;
 }
 
 /**
 * Extract entries from the archive to the target directory.
 *
 * All entries from the archive are extracted to the target directory.
 * By default the files in the target directory are overwritten.
 * If the $keepExisting is set to true, the files from the archive will not overwrite existing files.
 *
 * @see extractCurrent()
 *
 * @throws ezcArchiveException
 *         if the archive is closed
 * @throws ezcArchiveEmptyException
 *         if the archive is invalid
 * @param string $target     Absolute or relative path of the directory.
 * @param bool $keepExisting If set to true then the file will be overwritten, otherwise not.
 * @return void
 */
 public function extract( $target, $keepExisting = false )
 {
 if ( $this->file === null )
 {
 throw new ezcArchiveException( "The archive is closed" );
 }
 
 $this->rewind();
 if ( !$this->valid() )
 {
 throw new ezcArchiveEmptyException( );
 }
 
 while ( $this->valid() )
 {
 $this->extractCurrent( $target, $keepExisting );
 $this->next();
 }
 }
 
 /**
 * Returns true if the current archive is empty, otherwise false.
 *
 * @return bool
 */
 public function isEmpty()
 {
 return ( $this->entriesRead == 0 );
 }
 
 /**
 * Get the file entries from the archive.
 *
 * @param string|array(string) $files  Array or a single path to a file.
 * @param string $prefix               First part of the path used in $files.
 *
 * @return ezcArchiveEntry
 */
 protected function getEntries( $files, $prefix )
 {
 if ( !is_array( $files ) )
 {
 $files = array( $files );
 }
 
 // Check whether the files are correct.
 foreach ( $files as $file )
 {
 if ( !file_exists( $file ) && !is_link( $file ) )
 {
 throw new ezcBaseFileNotFoundException( $file );
 }
 }
 
 // Search for all the entries, because otherwise hardlinked files show up as an ordinary file.
 return ezcArchiveEntry::getEntryFromFile( $files, $prefix );
 }
 }
 ?>
 
 |