?
Current Path : /home1/savoy/public_html/wp-content/plugins/duplicator/src/Libs/DupArchive/ |
Linux gator3171.hostgator.com 4.19.286-203.ELK.el7.x86_64 #1 SMP Wed Jun 14 04:33:55 CDT 2023 x86_64 |
Current File : /home1/savoy/public_html/wp-content/plugins/duplicator/src/Libs/DupArchive/DupArchive.php |
<?php namespace Duplicator\Libs\DupArchive; use Duplicator\Libs\DupArchive\Headers\DupArchiveReaderDirectoryHeader; use Duplicator\Libs\DupArchive\Headers\DupArchiveReaderFileHeader; use Duplicator\Libs\DupArchive\Headers\DupArchiveReaderGlobHeader; use Duplicator\Libs\DupArchive\Headers\DupArchiveReaderHeader; use Error; use Exception; class DupArchive { const DUPARCHIVE_VERSION = '1.0.0'; const INDEX_FILE_NAME = '__dup__archive__index.json'; const INDEX_FILE_SIZE = 2000; // reserver 2K const EXTRA_FILES_POS_KEY = 'extraPos'; const HEADER_TYPE_NONE = 0; const HEADER_TYPE_FILE = 1; const HEADER_TYPE_DIR = 2; const HEADER_TYPE_GLOB = 3; /** * Get header type enum * * @param resource $archiveHandle archive resource * * @return int */ protected static function getNextHeaderType($archiveHandle) { $retVal = self::HEADER_TYPE_NONE; $marker = fgets($archiveHandle, 4); if (feof($archiveHandle) === false) { switch ($marker) { case '<D>': $retVal = self::HEADER_TYPE_DIR; break; case '<F>': $retVal = self::HEADER_TYPE_FILE; break; case '<G>': $retVal = self::HEADER_TYPE_GLOB; break; default: throw new Exception("Invalid header marker {$marker}. Location:" . ftell($archiveHandle)); } } return $retVal; } /** * Get archive index data * * @param string $archivePath archive path * * @return bool|array return index data, false if don't exists */ public static function getIndexData($archivePath) { try { $indexContent = self::getSrcFile($archivePath, self::INDEX_FILE_NAME, 0, 3000, false); if ($indexContent === false) { return false; } $indexData = json_decode(rtrim($indexContent, "\0"), true); if (!is_array($indexData)) { return false; } } catch (Exception $e) { return false; } catch (Error $e) { return false; } return $indexData; } /** * Get extra files offset if set or 0 * * @param string $archivePath archive path * * @return int */ public static function getExtraOffset($archivePath) { if (($indexData = self::getIndexData($archivePath)) === false) { return 0; } return (isset($indexData[self::EXTRA_FILES_POS_KEY]) ? $indexData[self::EXTRA_FILES_POS_KEY] : 0); } /** * Add file in archive from src * * @param string $archivePath archive path * @param string $relativePath relative path * @param int $offset start search location * @param int $sizeToSearch max size where search * * @return bool|int false if file not found of path position */ public static function seachPathInArchive($archivePath, $relativePath, $offset = 0, $sizeToSearch = 0) { if (($archiveHandle = fopen($archivePath, 'rb')) === false) { throw new Exception("Can’t open archive at $archivePath!"); } $result = self::searchPath($archivePath, $relativePath, $offset, $sizeToSearch); @fclose($archiveHandle); return $result; } /** * Search path, if found set and return position * * @param resource $archiveHandle dup archive resource * @param string $relativePath relative path to extract * @param int $offset start search location * @param int $sizeToSearch max size where search * * @return bool|int false if file not found of path position */ public static function searchPath($archiveHandle, $relativePath, $offset = 0, $sizeToSearch = 0) { if (!is_resource($archiveHandle)) { throw new Exception('Archive handle must be a resource'); } if (fseek($archiveHandle, $offset, SEEK_SET) < 0) { return false; } if ($offset == 0) { DupArchiveReaderHeader::readFromArchive($archiveHandle); } $result = false; $position = ftell($archiveHandle); $continue = true; do { switch (($type = self::getNextHeaderType($archiveHandle))) { case self::HEADER_TYPE_FILE: $currentFileHeader = DupArchiveReaderFileHeader::readFromArchive($archiveHandle, true, true); if ($currentFileHeader->relativePath == $relativePath) { $continue = false; $result = $position; } break; case self::HEADER_TYPE_DIR: $directoryHeader = DupArchiveReaderDirectoryHeader::readFromArchive($archiveHandle, true); if ($directoryHeader->relativePath == $relativePath) { $continue = false; $result = $position; } break; case self::HEADER_TYPE_NONE: $continue = false; break; default: throw new Exception('Invali header type "' . $type . '"'); } $position = ftell($archiveHandle); if ($sizeToSearch > 0 && ($position - $offset) >= $sizeToSearch) { break; } } while ($continue); if ($result !== false) { if (fseek($archiveHandle, $result, SEEK_SET) < 0) { return false; } } return $result; } /** * Get file content * * @param string $archivePath archvie path * @param string $relativePath relative path to extract * @param int $offset start search location * @param int $sizeToSearch max size where search * @param bool $isCompressed true if is compressed * * @return bool|string false if file not found */ public static function getSrcFile($archivePath, $relativePath, $offset = 0, $sizeToSearch = 0, $isCompressed = null) { if (($archiveHandle = fopen($archivePath, 'rb')) === false) { throw new Exception("Can’t open archive at $archivePath!"); } $archiveHeader = DupArchiveReaderHeader::readFromArchive($archiveHandle); if (is_null($isCompressed)) { $isCompressed = $archiveHeader->isCompressed; } if (self::searchPath($archiveHandle, $relativePath, $offset, $sizeToSearch) === false) { return false; } if (self::getNextHeaderType($archiveHandle) != self::HEADER_TYPE_FILE) { return false; } $header = DupArchiveReaderFileHeader::readFromArchive($archiveHandle, false, true); $result = self::getSrcFromHeader($archiveHandle, $header, $isCompressed); @fclose($archiveHandle); return $result; } /** * Get src file form header * * @param resource $archiveHandle archive handle * @param DupArchiveReaderFileHeader $fileHeader file header * @param bool $isCompressed true if is compressed * * @return string */ protected static function getSrcFromHeader($archiveHandle, DupArchiveReaderFileHeader $fileHeader, $isCompressed) { if ($fileHeader->fileSize == 0) { return ''; } $dataSize = 0; $result = ''; do { $globHeader = DupArchiveReaderGlobHeader::readFromArchive($archiveHandle); $result .= DupArchiveReaderGlobHeader::readContent($archiveHandle, $globHeader, $isCompressed); $dataSize += $globHeader->originalSize; } while ($dataSize < $fileHeader->fileSize); return $result; } /** * Skip file in archive * * @param resource $archiveHandle dup archive resource * @param DupArchiveFileHeader $fileHeader file header * * @return void */ protected static function skipFileInArchive($archiveHandle, DupArchiveReaderFileHeader $fileHeader) { if ($fileHeader->fileSize == 0) { return; } $dataSize = 0; do { $globHeader = DupArchiveReaderGlobHeader::readFromArchive($archiveHandle, true); $dataSize += $globHeader->originalSize; } while ($dataSize < $fileHeader->fileSize); } /** * Assumes we are on one header and just need to get to the next * * @param resource $archiveHandle dup archive resource * * @return void */ protected static function skipToNextHeader($archiveHandle) { $headerType = self::getNextHeaderType($archiveHandle); switch ($headerType) { case self::HEADER_TYPE_FILE: $fileHeader = DupArchiveReaderFileHeader::readFromArchive($archiveHandle, false, true); self::skipFileInArchive($archiveHandle, $fileHeader); break; case self::HEADER_TYPE_DIR: DupArchiveReaderDirectoryHeader::readFromArchive($archiveHandle, true); break; case self::HEADER_TYPE_NONE: false; } } }