• Модуль: main
  • Путь к файлу: ~/bitrix/modules/main/classes/general/zip.php
  • Класс: CZip
  • Вызов: CZip::Pack
public function Pack($arFileList, $startFile = "")
{
	$this->_errorReset();
	$this->startFile = $this->io->GetPhysicalName($startFile);
	$this->arPackedFiles = [];
	$this->arHeaders = [];
	$arCentralDirInfo = [];
	$zipfile_tmp = $zipname_tmp = '';

	$isNewArchive = true;
	if ($startFile != "" && is_file($this->io->GetPhysicalName($this->zipname)))
	{
		$isNewArchive = false;
	}

	if ($isNewArchive)
	{
		if (!$this->_openFile("wb"))
		{
			return false;
		}
	}
	else
	{
		if (!$this->_openFile("rb"))
		{
			return false;
		}

		// read the central directory
		if (($res = $this->_readEndCentralDir($arCentralDirInfo)) != 1)
		{
			$this->_closeFile();
			return $res;
		}

		@rewind($this->zipfile);

		//creating tmp file
		$zipname_tmp = GetDirPath($this->zipname) . uniqid('ziparc') . '.tmp';
		if (($zipfile_tmp = @fopen($this->io->GetPhysicalName($zipname_tmp), 'wb')) == 0)
		{
			$this->_closeFile();
			$this->_errorLog("ERR_READ_TMP", str_replace("#FILE_NAME#", removeDocRoot($zipname_tmp), GetMessage("MAIN_ZIP_ERR_READ_TMP")));
			return $this->arErrors;
		}

		//copy files from the archive to the tmp file
		$size = $arCentralDirInfo['offset'];

		while ($size != 0)
		{
			$length = ($size < self::ReadBlockSize ? $size : self::ReadBlockSize);
			$buffer = fread($this->zipfile, $length);
			@fwrite($zipfile_tmp, $buffer, $length);
			$size -= $length;
		}

		//swapping file handle to use methods on the temporary file, not the real archive
		$tmp_id = $this->zipfile;
		$this->zipfile = $zipfile_tmp;
		$zipfile_tmp = $tmp_id;
	}

	//starting measuring start time from here (only packing time)
	define("ZIP_START_TIME", microtime(true));
	$this->tempres = null;

	$arFileList = $this->_parseFileParams($arFileList);

	$arConvertedFileList = [];
	foreach ($arFileList as $fullpath)
	{
		$arConvertedFileList[] = $this->io->GetPhysicalName($fullpath);
	}

	$packRes = null;
	if (is_array($arFileList) && !empty($arFileList))
	{
		$packRes = $this->_processFiles($arConvertedFileList, $this->add_path, $this->remove_path);
	}

	if ($isNewArchive)
	{
		//writing Central Directory
		//save central directory offset
		$offset = @ftell($this->zipfile);

		//make central dir files header
		for ($i = 0, $counter = 0; $i < sizeof($this->arPackedFiles); $i++)
		{
			//write file header
			if ($this->arHeaders[$i]['status'] == 'ok')
			{
				if (($res = $this->_writeCentralFileHeader($this->arHeaders[$i])) != 1)
				{
					return $res;
				}
				$counter++;
			}

			$this->_convertHeader2FileInfo($this->arHeaders[$i], $this->arPackedFilesData[$i]);
		}

		$zip_comment = '';
		//calculate the size of the central header
		$size = @ftell($this->zipfile) - $offset;
		//make central dir footer
		if (($res = $this->_writeCentralHeader($counter, $size, $offset, $zip_comment)) != 1)
		{
			$this->arHeaders = null;
			return $res;
		}
	}
	else
	{
		//save the offset of the central dir
		$offset = @ftell($this->zipfile);

		//copy file headers block from the old archive
		$size = $arCentralDirInfo['size'];
		while ($size != 0)
		{
			$length = ($size < self::ReadBlockSize ? $size : self::ReadBlockSize);
			$buffer = @fread($zipfile_tmp, $length);
			@fwrite($this->zipfile, $buffer, $length);
			$size -= $length;
		}

		//add central dir files header
		for ($i = 0, $counter = 0; $i < sizeof($this->arHeaders); $i++)
		{
			//create the file header
			if ($this->arHeaders[$i]['status'] == 'ok')
			{
				if (($res = $this->_writeCentralFileHeader($this->arHeaders[$i])) != 1)
				{
					fclose($zipfile_tmp);
					$this->_closeFile();
					@unlink($this->io->GetPhysicalName($zipname_tmp));

					return $res;
				}
				$counter++;
			}
			//convert header to the usable format
			$this->_convertHeader2FileInfo($this->arHeaders[$i], $this->arPackedFilesData[$i]);
		}

		$zip_comment = '';

		//find the central header size
		$size = @ftell($this->zipfile) - $offset;

		//make central directory footer
		if (($res = $this->_writeCentralHeader($counter + $arCentralDirInfo['entries'], $size, $offset, $zip_comment)) != 1)
		{
			//clear file list
			$this->arHeaders = null;
			return $res;
		}

		//changing file handler back
		$tmp_id = $this->zipfile;
		$this->zipfile = $zipfile_tmp;
		$zipfile_tmp = $tmp_id;

		$this->_closeFile();
		@fclose($zipfile_tmp);
		// @unlink($this->zipname);

		//probably test the result @rename($zipname_tmp, $this->zipname);
		$this->_renameTmpFile($zipname_tmp, $this->zipname);
	}

	if ($isNewArchive && ($res === false))
	{
		$this->_cleanFile();
	}
	else
	{
		$this->_closeFile();
	}

	//if packing is not completed, remember last file
	if ($packRes === 'continue')
	{
		$this->startFile = $this->io->GetLogicalName(array_pop($this->arPackedFiles));
	}

	if ($packRes === false)
	{
		return IBXArchive::StatusError;
	}
	elseif ($packRes && $this->startFile == "")
	{
		return IBXArchive::StatusSuccess;
	}
	elseif ($packRes && $this->startFile != "")
	{
		//call Pack() with $this->GetStartFile() next time to continue
		return IBXArchive::StatusContinue;
	}
	return null;
}