- Модуль: main
- Путь к файлу: ~/bitrix/modules/main/classes/general/zip.php
- Класс: CZip
- Вызов: CZip::_readEndCentralDir
private function _readEndCentralDir(&$arCentralDir)
{
$res = 1;
//going to the end of the file
$size = filesize($this->io->GetPhysicalName($this->zipname));
@fseek($this->zipfile, $size);
if (@ftell($this->zipfile) != $size)
{
$this->_errorLog("ERR_ARC_END", str_replace("#FILE_NAME#", removeDocRoot($this->zipname), GetMessage("MAIN_ZIP_ERR_ARC_END")));
return $this->arErrors;
}
//if archive is without comments (usually), the end of central dir is at 22 bytes of the file end
$isFound = 0;
$pos = 0;
if ($size > 26)
{
@fseek($this->zipfile, $size - 22);
if (@ftell($this->zipfile) != ($size - 22))
{
$this->_errorLog("ERR_ARC_MID", str_replace("#FILE_NAME#", removeDocRoot($this->zipname), GetMessage("MAIN_ZIP_ERR_ARC_MID")));
return $this->arErrors;
}
//read 4 bytes
$binary_data = @fread($this->zipfile, 4);
$data = unpack('Vid', $binary_data);
//signature check
if ($data['id'] == 0x06054b50)
{
$isFound = 1;
}
$pos = ftell($this->zipfile);
}
//going back to the max possible size of the Central Dir End Record
if (!$isFound)
{
$maxSize = 65557; // 0xFFFF + 22;
if ($maxSize > $size)
{
$maxSize = $size;
}
@fseek($this->zipfile, $size - $maxSize);
if (@ftell($this->zipfile) != ($size - $maxSize))
{
$this->_errorLog("ERR_ARC_MID", str_replace("#FILE_NAME#", removeDocRoot($this->zipname), GetMessage("MAIN_ZIP_ERR_ARC_MID")));
return $this->arErrors;
}
//reading byte per byte to find the signature
$pos = ftell($this->zipfile);
$bytes = 0x00000000;
while ($pos < $size)
{
//reading 1 byte
$byte = @fread($this->zipfile, 1);
//0x03000000504b0506 -> 0x504b0506
$bytes = ($bytes << (8 * (PHP_INT_SIZE - 3))) >> (8 * (PHP_INT_SIZE - 4));
//adding the byte
$bytes = $bytes | ord($byte);
//compare bytes
if ($bytes == 0x504b0506)
{
$pos++;
break;
}
$pos++;
}
//if end of the central dir is not found
if ($pos == $size)
{
$this->_errorLog("ERR_ARC_MID_END", GetMessage("MAIN_ZIP_ERR_ARC_MID_END"));
return $this->arErrors;
}
}
//reading first 18 bytes of the header
$binary_data = fread($this->zipfile, 18);
//if block size is not valid
if (strlen($binary_data) != 18)
{
$this->_errorLog("ERR_ARC_END_SIZE", str_replace("#SIZE#", mb_strlen($binary_data), GetMessage("MAIN_ZIP_ERR_ARC_END_SIZE")));
return $this->arErrors;
}
//extracting values
$data = unpack('vdisk/vdisk_start/vdisk_entries/ventries/Vsize/Voffset/vcomment_size', $binary_data);
//checking global size
if (($pos + $data['comment_size'] + 18) != $size)
{
$this->_errorLog("ERR_SIGNATURE", GetMessage("MAIN_ZIP_ERR_SIGNATURE"));
return $this->arErrors;
}
//reading comments
if ($data['comment_size'] != 0)
{
$arCentralDir['comment'] = fread($this->zipfile, $data['comment_size']);
}
else
{
$arCentralDir['comment'] = '';
}
$arCentralDir['entries'] = $data['entries'];
$arCentralDir['disk_entries'] = $data['disk_entries'];
$arCentralDir['offset'] = $data['offset'];
$arCentralDir['size'] = $data['size'];
$arCentralDir['disk'] = $data['disk'];
$arCentralDir['disk_start'] = $data['disk_start'];
return $res;
}