• Модуль: 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;
}