/** * Sets this header with the values from the ezcArchiveEntry $entry. * * The values that are possible to set from the ezcArchiveEntry $entry are set in this header. * The properties that change are: internalFileAttributes, relativeHeaderOffset, type, and mtime. * * @param ezcArchiveEntry $entry * @return void */ public function setHeaderFromArchiveEntry(ezcArchiveEntry $entry) { $this->properties["internalFileAttributes"] = 0; $this->setType($entry->getType()); $this->setPermissions($entry->getPermissions()); $this->properties["relativeHeaderOffset"] = 0; $this->properties["mtime"] = $entry->getModificationTime(); }
/** * Sets this header with the values from the ezcArchiveEntry $entry. * * The values that are possible to set from the ezcArchiveEntry $entry are set in this header. * * @param ezcArchiveEntry $entry * @return void */ public function setHeaderFromArchiveEntry(ezcArchiveEntry $entry) { $this->version = 10; // FIXME $this->bitFlag = 0; // FIXME $this->atime = $entry->getAccessTime(); $this->groupId = $entry->getGroupId(); $this->userId = $entry->getUserId(); $this->setModificationTime($entry->getModificationTime()); if ($entry->isSymLink()) { $this->uncompressedSize = strlen($entry->getLink()); $this->crc = ezcArchiveChecksums::getCrc32FromString($entry->getLink()); } else { $this->uncompressedSize = $entry->getSize(); $this->crc = ezcArchiveChecksums::getCrc32FromFile($entry->getPath()); } $this->setFileName($entry->getPath(false)); }
/** * Sets this header with the values from the ezcArchiveEntry $entry. * * The values that are possible to set from the ezcArchiveEntry $entry are set in this header. * The properties that may change are: fileName, fileMode, userId, groupId, fileSize, modificationTime, * linkName, and type. * * @param ezcArchiveEntry $entry * @return void */ public function setHeaderFromArchiveEntry(ezcArchiveEntry $entry) { $this->splitFilePrefix($entry->getPath(false), $file, $filePrefix); $this->fileName = $file; $this->filePrefix = $filePrefix; $this->fileMode = $entry->getPermissions(); $this->userId = $entry->getUserId(); $this->groupId = $entry->getGroupId(); $this->fileSize = $entry->getSize(); $this->modificationTime = $entry->getModificationTime(); $this->linkName = $entry->getLink(false); switch ($entry->getType()) { case ezcArchiveEntry::IS_FILE: $this->type = 0; break; case ezcArchiveEntry::IS_LINK: $this->type = 1; break; case ezcArchiveEntry::IS_SYMBOLIC_LINK: $this->type = 2; break; case ezcArchiveEntry::IS_CHARACTER_DEVICE: $this->type = 3; break; case ezcArchiveEntry::IS_BLOCK_DEVICE: $this->type = 4; break; case ezcArchiveEntry::IS_DIRECTORY: $this->type = 5; break; case ezcArchiveEntry::IS_FIFO: $this->type = 6; break; // Devices, etc are set to \0. // Devices, etc are set to \0. default: $this->type = ""; break; // ends up as a \0 character. } $this->deviceMajorNumber = $entry->getMajor(); $this->deviceMinorNumber = $entry->getMinor(); $length = strlen($this->fileName); if ($entry->getType() == ezcArchiveEntry::IS_DIRECTORY) { // Make sure that the filename ends with a slash. if ($this->fileName[$length - 1] != "/") { $this->fileName .= "/"; } } else { if ($this->fileName[$length - 1] == "/") { $this->fileName = substr($this->fileName, 0, -1); // Remove last character. } } }
/** * 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); }
/** * Sets this header with the values from the ezcArchiveEntry $entry. * * The values that are possible to set from the ezcArchiveEntry $entry are set in this header. * The properties that may change are: fileName, fileMode, userId, groupId, fileSize, modificationTime, * linkName, and type. * * @param ezcArchiveEntry $entry * @return void */ public function setHeaderFromArchiveEntry(ezcArchiveEntry $entry) { $this->fileName = $entry->getPath(false); $this->fileMode = $entry->getPermissions(); $this->userId = $entry->getUserId(); $this->groupId = $entry->getGroupId(); $this->fileSize = $entry->getSize(); $this->modificationTime = $entry->getModificationTime(); $this->linkName = $entry->getLink(false); switch ($entry->getType()) { case ezcArchiveEntry::IS_FILE: $this->type = ""; break; // ends up as a \0 character. // ends up as a \0 character. case ezcArchiveEntry::IS_LINK: $this->type = 1; break; case ezcArchiveEntry::IS_SYMBOLIC_LINK: $this->type = 2; break; case ezcArchiveEntry::IS_DIRECTORY: $this->type = 5; break; // Devices, etc are set to \0. // Devices, etc are set to \0. default: $this->type = ""; break; // ends up as a \0 character. } $length = strlen($this->fileName); if ($entry->getType() == ezcArchiveEntry::IS_DIRECTORY) { // Make sure that the filename ends with a slash. if ($this->fileName[$length - 1] != "/") { $this->fileName .= "/"; } } else { if ($this->fileName[$length - 1] == "/") { $this->fileName = substr($header->fileName, 0, -1); // Remove last character. } } }
/** * 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); }