• Модуль: main
  • Путь к файлу: ~/bitrix/modules/main/classes/general/zip.php
  • Класс: CZip
  • Вызов: CZip::_extractByRule
private function _extractByRule(&$arFileList, &$arParams)
{
	$path = $arParams['add_path'];
	$removePath = $arParams['remove_path'];
	$removeAllPath = $arParams['remove_all_path'];

	//path checking
	if (($path == "") || ((mb_substr($path, 0, 1) != "/") && (mb_substr($path, 0, 3) != "../") && (mb_substr($path, 1, 2) != ":/")))
	{
		$path = "./" . $path;
	}

	//reduce the path last (and duplicated) '/'
	if (($path != "./") && ($path != "/"))
	{
		// checking path end '/'
		while (mb_substr($path, -1) == "/")
		{
			$path = mb_substr($path, 0, mb_strlen($path) - 1);
		}
	}

	//path should end with the /
	if (($removePath != "") && (mb_substr($removePath, -1) != '/'))
	{
		$removePath .= '/';
	}

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

	//reading central directory information
	$arCentralDirInfo = [];
	if (($res = $this->_readEndCentralDir($arCentralDirInfo)) != 1)
	{
		$this->_closeFile();
		return $res;
	}

	//starting from the beginning of the central directory
	$entryPos = $arCentralDirInfo['offset'];

	//reading each entry
	$j_start = 0;

	for ($i = 0, $extractedCounter = 0; $i < $arCentralDirInfo['entries']; $i++)
	{
		//reading next central directory record
		@rewind($this->zipfile);
		if (@fseek($this->zipfile, $entryPos))
		{
			$this->_closeFile();
			$this->_errorLog("ERR_INVALID_ARCHIVE_ZIP", GetMessage("MAIN_ZIP_ERR_MISSING_FILE"));
			return $this->arErrors;
		}

		//reading the file header
		$header = [];
		if (($res = $this->_readCentralFileHeader($header)) != 1)
		{
			$this->_closeFile();
			return $res;
		}

		//saving the index
		$header['index'] = $i;

		//saving the file pos
		$entryPos = ftell($this->zipfile);

		$extract = false;

		//look for the specific extract rules
		if ((isset($arParams['by_name'])) && is_array($arParams['by_name']))
		{
			//is filename in the list
			$count = count($arParams['by_name']);
			for ($j = 0; $j < $count && !$extract; $j++)
			{
				//is directory
				if (mb_substr($arParams['by_name'][$j], -1) == "/")
				{
					//is dir in the filename path
					if ((mb_strlen($header['stored_filename']) > mb_strlen($arParams['by_name'][$j]))
						&& (mb_substr($header['stored_filename'], 0, mb_strlen($arParams['by_name'][$j])) == $arParams['by_name'][$j]))
					{
						$extract = true;
					}
				}
				else
				{
					if ($header['stored_filename'] == $arParams['by_name'][$j])
					{
						$extract = true;
					}
				}
			}
		}
		else
		{
			if ((isset($arParams['by_preg'])) && ($arParams['by_preg'] != ""))
			{
				//extract by preg rule
				if (preg_match($arParams['by_preg'], $header['stored_filename']))
				{
					$extract = true;
				}
			}
			else
			{
				if ((isset($arParams['by_index'])) && is_array($arParams['by_index']))
				{
					//extract by index rule (if index is in the list)
					for ($j = $j_start, $n = count($arParams['by_index']); $j < $n && !$extract; $j++)
					{
						if (($i >= $arParams['by_index'][$j]['start']) && ($i <= $arParams['by_index'][$j]['end']))
						{
							$extract = true;
						}

						if ($i >= $arParams['by_index'][$j]['end'])
						{
							$j_start = $j + 1;
						}

						if ($arParams['by_index'][$j]['start'] > $i)
						{
							break;
						}
					}
				}
				else
				{
					$extract = true;
				}
			}
		}

		// extract file
		if ($extract)
		{
			@rewind($this->zipfile);
			if (@fseek($this->zipfile, $header['offset']))
			{
				$this->_closeFile();
				$this->_errorLog("ERR_INVALID_ARCHIVE_ZIP", GetMessage("MAIN_ZIP_ERR_INVALID_ARCHIVE_ZIP"));
				return $this->arErrors;
			}
			//extract as a string
			if ($arParams['extract_as_string'])
			{
				//extract the file
				if (($res = $this->_extractFileAsString($header, $string)) != 1)
				{
					$this->_closeFile();
					return $res;
				}

				//get attributes
				if (($res = $this->_convertHeader2FileInfo($header, $arFileList[$extractedCounter])) != 1)
				{
					$this->_closeFile();
					return $res;
				}

				//set file content
				$arFileList[$extractedCounter]['content'] = $string;

				//next extracted file
				$extractedCounter++;
			}
			else
			{
				if (($res = $this->_extractFile($header, $path, $removePath, $removeAllPath, $arParams)) != 1)
				{
					$this->_closeFile();
					return $res;
				}

				//get attributes
				if (($res = $this->_convertHeader2FileInfo($header, $arFileList[$extractedCounter++])) != 1)
				{
					$this->_closeFile();
					return $res;
				}
			}
		}
	}
	$this->_closeFile();
	return $res;
}