/** * 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); }
/** * 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 ezcArchiveException if the archive is closed or read-only * @throws ezcBaseFileNotFoundException if one of the specified files is missing * @throws ezcBaseFilePermissionException if the archive is not writable * * @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 function appendToCurrent($files, $prefix) { if (!$this->isWritable()) { throw new ezcBaseFilePermissionException($this->file->getFileName(), ezcBaseFilePermissionException::WRITE, "Archive is read-only"); } // Current position valid? if (!$this->isEmpty() && !$this->valid()) { return false; } 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. $entries = ezcArchiveEntry::getEntryFromFile($files, $prefix); if ($this->isEmpty()) { $this->file->truncate(); $this->file->rewind(); $cur = -1; } else { // Create the new headers. $cur = $this->key(); // Current Header. $lh = $this->getLocalHeader($cur); $pos = $this->localHeaderPositions[$cur] + $lh->getHeaderSize() + $lh->compressedSize; $this->file->truncate($pos); $this->file->seek($pos); } foreach ($entries as $entry) { $cur++; // Set local header position $this->localHeaderPositions[$cur] = $this->file->getPosition(); // Set local header $this->localHeaders[$cur] = new ezcArchiveLocalFileHeader(); $this->localHeaders[$cur]->setHeaderFromArchiveEntry($entry); if ($entry->isSymLink()) { $fileData = $entry->getLink(); $this->localHeaders[$cur]->setCompression(0, $this->localHeaders[$cur]->uncompressedSize); // Compression is 0, for now. } else { if ($entry->isDirectory()) { // Added for issue #13517: Not possible to add directories to an archive on Windows $fileData = gzdeflate(''); // empty string for directories $this->localHeaders[$cur]->setCompression(8, strlen($fileData)); } else { // FIXME, File in memory, compression level always 8, add constants. $fileData = gzdeflate(file_get_contents($entry->getPath())); $this->localHeaders[$cur]->setCompression(8, strlen($fileData)); } } $this->localHeaders[$cur]->writeEncodedHeader($this->file); // Write link or file. $this->file->write($fileData); unset($fileData); // Create also the central headers. $this->centralHeaders[$cur] = new ezcArchiveCentralDirectoryHeader(); $this->centralHeaders[$cur]->setHeaderFromLocalFileHeader($this->localHeaders[$cur]); $this->centralHeaders[$cur]->setHeaderFromArchiveEntry($entry); $this->centralHeaders[$cur]->relativeHeaderOffset = $this->localHeaderPositions[$cur]; // Set the entry. $entry->removePrefixFromPath(); $this->entries[$cur] = $entry; } for ($i = 0; $i <= $cur; $i++) { // Write the headers. $this->centralHeaderPositions[$i] = $this->file->getPosition(); $this->centralHeaders[$i]->writeEncodedHeader($this->file); } // Remove the rest of the localHeaders and centralHeaders. for ($i = $cur + 1; $i < $this->entriesRead; $i++) { unset($this->localHeaders[$i]); unset($this->localHeaderPositions[$i]); unset($this->centralHeaders[$i]); unset($this->centralHeaderPositions[$i]); } $this->entriesRead = $cur + 1; // Write the end record. $this->endRecord = new ezcArchiveCentralDirectoryEndHeader(); $this->endRecord->centralDirectoryStart = $this->centralHeaderPositions[0]; $this->endRecord->centralDirectorySize = $this->file->getPosition() - $this->centralHeaderPositions[0]; $this->endRecord->totalCentralDirectoryEntries = $cur + 1; $this->endRecord->writeEncodedHeader($this->file); }