You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
100 lines
3.1 KiB
100 lines
3.1 KiB
<?php
|
|
|
|
/**
|
|
*
|
|
* @package Duplicator
|
|
* @copyright (c) 2021, Snapcreek LLC
|
|
*/
|
|
|
|
namespace Duplicator\Libs\DupArchive\Headers;
|
|
|
|
use Exception;
|
|
|
|
/**
|
|
* File header
|
|
*/
|
|
class DupArchiveReaderFileHeader
|
|
{
|
|
public $fileSize = 0;
|
|
public $mtime = 0;
|
|
public $permissions = '';
|
|
public $hash = '';
|
|
public $relativePathLength = 0;
|
|
public $relativePath = '';
|
|
|
|
/**
|
|
* Class constructor
|
|
*/
|
|
protected function __construct()
|
|
{
|
|
// Prevent direct instantiation
|
|
}
|
|
|
|
|
|
/**
|
|
* Read header form archive
|
|
* delta = 84-22 = 62 bytes per file -> 20000 files -> 1.2MB larger
|
|
* <F><FS>x</FS><MT>x</<MT><FP>x</FP><HA>x</HA><RFPL>x</RFPL><RFP>x</RFP></F>
|
|
* # F#x#x#x#x#x#x!
|
|
*
|
|
* @param resource $archiveHandle archive resource
|
|
* @param boolean $skipContents if true skip contents
|
|
* @param boolean $skipMarker if true skip marker
|
|
*
|
|
* @return static
|
|
*/
|
|
public static function readFromArchive($archiveHandle, $skipContents = false, $skipMarker = false)
|
|
{
|
|
// RSR TODO Read header from archive handle and populate members
|
|
// TODO: return null if end of archive or throw exception if can read something but its not a file header
|
|
|
|
$instance = new static();
|
|
|
|
if (!$skipMarker) {
|
|
$marker = @fread($archiveHandle, 3);
|
|
|
|
if ($marker === false) {
|
|
if (feof($archiveHandle)) {
|
|
return false;
|
|
} else {
|
|
throw new Exception('Error reading file header');
|
|
}
|
|
}
|
|
|
|
if ($marker != '<F>') {
|
|
throw new Exception("Invalid file header marker found [{$marker}] : location " . ftell($archiveHandle));
|
|
}
|
|
}
|
|
|
|
$instance->fileSize = DupArchiveHeaderU::readStandardHeaderField($archiveHandle, 'FS');
|
|
$instance->mtime = DupArchiveHeaderU::readStandardHeaderField($archiveHandle, 'MT');
|
|
$instance->permissions = DupArchiveHeaderU::readStandardHeaderField($archiveHandle, 'P');
|
|
$instance->hash = DupArchiveHeaderU::readStandardHeaderField($archiveHandle, 'HA');
|
|
$instance->relativePathLength = DupArchiveHeaderU::readStandardHeaderField($archiveHandle, 'RPL');
|
|
|
|
// Skip <RP>
|
|
fread($archiveHandle, 4);
|
|
$instance->relativePath = fread($archiveHandle, $instance->relativePathLength);
|
|
|
|
// Skip </RP>
|
|
// fread($archiveHandle, 5);
|
|
|
|
// Skip the </F>
|
|
// fread($archiveHandle, 4);
|
|
|
|
// Skip the </RP> and the </F>
|
|
fread($archiveHandle, 9);
|
|
|
|
if ($skipContents && ($instance->fileSize > 0)) {
|
|
$dataSize = 0;
|
|
$moreGlobs = true;
|
|
while ($moreGlobs) {
|
|
$globHeader = DupArchiveReaderGlobHeader::readFromArchive($archiveHandle, true);
|
|
$dataSize += $globHeader->originalSize;
|
|
$moreGlobs = ($dataSize < $instance->fileSize);
|
|
}
|
|
}
|
|
|
|
return $instance;
|
|
}
|
|
}
|
|
|