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