• Модуль: main
  • Путь к файлу: ~/bitrix/modules/main/classes/general/zip.php
  • Класс: CZip
  • Вызов: CZip::_deleteByRule
private function _deleteByRule(&$arResultList, $arParams)
{
	$arCentralDirInfo = [];
	$arHeaders = [];

	if (($res = $this->_openFile('rb')) != 1)
	{
		return $res;
	}

	if (($res = $this->_readEndCentralDir($arCentralDirInfo)) != 1)
	{
		$this->_closeFile();
		return $res;
	}

	//scanning all the files, starting at the beginning of Central Dir
	$entryPos = $arCentralDirInfo['offset'];
	@rewind($this->zipfile);

	if (@fseek($this->zipfile, $entryPos))
	{
		//clean file
		$this->_closeFile();
		$this->_errorLog("ERR_INVALID_ARCHIVE_ZIP", GetMessage("MAIN_ZIP_ERR_INVALID_ARCHIVE_ZIP"));
		return $this->arErrors;
	}

	$j_start = 0;

	//reading each entry
	for ($i = 0, $extractedCounter = 0; $i < $arCentralDirInfo['entries']; $i++)
	{
		//reading file header
		$arHeaders[$extractedCounter] = [];

		$res = $this->_readCentralFileHeader($arHeaders[$extractedCounter]);
		if ($res != 1)
		{
			$this->_closeFile();
			return $res;
		}

		//saving index
		$arHeaders[$extractedCounter]['index'] = $i;

		//check specific extract rules
		$isFound = false;

		//name rule
		if ((isset($arParams['by_name'])) && is_array($arParams['by_name']))
		{
			//if the filename is in the list
			for ($j = 0, $n = count($arParams['by_name']); $j < $n && !$isFound; $j++)
			{
				if (mb_substr($arParams['by_name'][$j], -1) == "/")
				{
					//if the directory is in the filename path
					if ((mb_strlen($arHeaders[$extractedCounter]['stored_filename']) > mb_strlen($arParams['by_name'][$j]))
						&& (mb_substr($arHeaders[$extractedCounter]['stored_filename'], 0, mb_strlen($arParams['by_name'][$j])) == $arParams['by_name'][$j]))
					{
						$isFound = true;
					}
					elseif ((($arHeaders[$extractedCounter]['external'] & 0x00000010) == 0x00000010) /* Indicates a folder */
						&& ($arHeaders[$extractedCounter]['stored_filename'] . '/' == $arParams['by_name'][$j]))
					{
						$isFound = true;
					}
				}
				elseif ($arHeaders[$extractedCounter]['stored_filename'] == $arParams['by_name'][$j])
				{
					//check filename
					$isFound = true;
				}
			}
		}
		else
		{
			if ((isset($arParams['by_preg'])) && ($arParams['by_preg'] != ""))
			{
				if (preg_match($arParams['by_preg'], $arHeaders[$extractedCounter]['stored_filename']))
				{
					$isFound = true;
				}
			}
			else
			{
				if ((isset($arParams['by_index'])) && is_array($arParams['by_index']))
				{
					//index rule: if index is in the list
					for ($j = $j_start, $n = count($arParams['by_index']); $j < $n && !$isFound; $j++)
					{
						if (($i >= $arParams['by_index'][$j]['start'])
							&& ($i <= $arParams['by_index'][$j]['end']))
						{
							$isFound = true;
						}
						if ($i >= $arParams['by_index'][$j]['end'])
						{
							$j_start = $j + 1;
						}
						if ($arParams['by_index'][$j]['start'] > $i)
						{
							break;
						}
					}
				}
			}
		}

		//delete?
		if ($isFound)
		{
			unset($arHeaders[$extractedCounter]);
		}
		else
		{
			$extractedCounter++;
		}
	}

	//if something should be deleted
	if ($extractedCounter > 0)
	{
		//create tmp file
		$zipname_tmp = GetDirPath($this->zipname) . uniqid('ziparc') . '.tmp';
		//create tmp zip archive
		$tmpzip = new CZip($zipname_tmp);

		if (($res = $tmpzip->_openFile('wb')) != 1)
		{
			$this->_closeFile();
			return $res;
		}

		//check which file should be kept
		for ($i = 0; $i < sizeof($arHeaders); $i++)
		{
			//calculate the position of the header
			@rewind($this->zipfile);
			if (@fseek($this->zipfile, $arHeaders[$i]['offset']))
			{
				$this->_closeFile();
				$tmpzip->_closeFile();
				@unlink($this->io->GetPhysicalName($zipname_tmp));
				$this->_errorLog("ERR_INVALID_ARCHIVE_ZIP", GetMessage("MAIN_ZIP_ERR_INVALID_ARCHIVE_ZIP"));

				return $this->arErrors;
			}

			if (($res = $this->_readFileHeader($arHeaders[$i])) != 1)
			{
				$this->_closeFile();
				$tmpzip->_closeFile();
				@unlink($this->io->GetPhysicalName($zipname_tmp));

				return $res;
			}

			//writing file header
			$res = $tmpzip->_writeFileHeader($arHeaders[$i]);
			if ($res != 1)
			{
				$this->_closeFile();
				$tmpzip->_closeFile();
				@unlink($this->io->GetPhysicalName($zipname_tmp));

				return $res;
			}

			//reading/writing data block
			$res = $this->_copyBlocks($this->zipfile, $tmpzip->zipfile, $arHeaders[$i]['compressed_size']);
			if ($res != 1)
			{
				$this->_closeFile();
				$tmpzip->_closeFile();
				@unlink($this->io->GetPhysicalName($zipname_tmp));

				return $res;
			}
		}

		//save central dir offset
		$offset = @ftell($tmpzip->zipfile);

		//re-write central dir files header
		for ($i = 0; $i < sizeof($arHeaders); $i++)
		{
			$res = $tmpzip->_writeCentralFileHeader($arHeaders[$i]);
			if ($res != 1)
			{
				$tmpzip->_closeFile();
				$this->_closeFile();
				@unlink($this->io->GetPhysicalName($zipname_tmp));

				return $res;
			}

			//convert header to the 'usable' format
			$tmpzip->_convertHeader2FileInfo($arHeaders[$i], $arResultList[$i]);
		}

		$zip_comment = '';
		$size = @ftell($tmpzip->zipfile) - $offset;

		$res = $tmpzip->_writeCentralHeader(sizeof($arHeaders), $size, $offset, $zip_comment);
		if ($res != 1)
		{
			unset($arHeaders);
			$tmpzip->_closeFile();
			$this->_closeFile();
			@unlink($this->io->GetPhysicalName($zipname_tmp));

			return $res;
		}

		$tmpzip->_closeFile();
		$this->_closeFile();

		//deleting zip file (result should be checked)
		@unlink($this->io->GetPhysicalName($this->zipname));

		//result should be checked
		$this->_renameTmpFile($zipname_tmp, $this->zipname);

		unset($tmpzip);
	}

	return $res;
}