- Модуль: main
- Путь к файлу: ~/bitrix/modules/main/classes/general/zip.php
- Класс: CZip
- Вызов: CZip::_extractFile
private function _extractFile(&$arEntry, $path, $removePath, $removeAllPath, $arParams)
{
if (($res = $this->_readFileHeader($header)) != 1)
{
return $res;
}
//to be checked: file header should be coherent with $arEntry info
$arEntry["filename"] = BitrixMainTextEncoding::convertEncoding($arEntry["filename"], "cp866", $this->fileSystemEncoding);
$arEntry["stored_filename"] = BitrixMainTextEncoding::convertEncoding($arEntry["stored_filename"], "cp866", $this->fileSystemEncoding);
//protecting against ../ etc. in file path
//only absolute path should be in the $arEntry
$arEntry['filename'] = _normalizePath($arEntry['filename']);
$arEntry['stored_filename'] = _normalizePath($arEntry['stored_filename']);
if ($removeAllPath)
{
$arEntry['filename'] = basename($arEntry['filename']);
}
else
{
if ($removePath != "")
{
if ($this->_containsPath($removePath, $arEntry['filename']) == 2)
{
//change file status
$arEntry['status'] = "filtered";
return $res;
}
$removePath_size = mb_strlen($removePath);
if (mb_substr($arEntry['filename'], 0, $removePath_size) == $removePath)
{
//remove path
$arEntry['filename'] = mb_substr($arEntry['filename'], $removePath_size);
}
}
}
//making absolute path to the extracted file out of filename stored in the zip header and passed extracting path
if ($path != '')
{
$arEntry['filename'] = $path . "/" . $arEntry['filename'];
}
//pre-extract callback
if ((isset($arParams['callback_pre_extract']))
&& ($arParams['callback_pre_extract'] != ''))
{
//generate local info
$arLocalHeader = [];
$this->_convertHeader2FileInfo($arEntry, $arLocalHeader);
//callback call
eval('$res = ' . $arParams['callback_pre_extract'] . '('callback_pre_extract', $arLocalHeader);');
//change file status
if ($res == 0)
{
$arEntry['status'] = "skipped";
$res = 1;
}
//update the info, only some fields can be modified
$arEntry['filename'] = $arLocalHeader['filename'];
}
//check if extraction should be done
if ($arEntry['status'] == 'ok')
{
if ($this->checkPermissions && !CBXArchive::IsFileSafe($arEntry['filename']))
{
$arEntry['status'] = "no_permissions";
}
else
{
//if the file exists, change status
if (file_exists($arEntry['filename']))
{
if (is_dir($arEntry['filename']))
{
$arEntry['status'] = "already_a_directory";
}
else
{
if (!is_writeable($arEntry['filename']))
{
$arEntry['status'] = "write_protected";
}
else
{
if ((filemtime($arEntry['filename']) > $arEntry['mtime']) && (!$this->replaceExistentFiles))
{
$arEntry['status'] = "newer_exist";
}
}
}
}
else
{
//check the directory availability and create it if necessary
if ((($arEntry['external'] & 0x00000010) == 0x00000010) || (mb_substr($arEntry['filename'], -1) == '/'))
{
$checkDir = $arEntry['filename'];
}
else
{
if (!mb_strstr($arEntry['filename'], "/"))
{
$checkDir = "";
}
else
{
$checkDir = dirname($arEntry['filename']);
}
}
if (($res = $this->_checkDir($checkDir, (($arEntry['external'] & 0x00000010) == 0x00000010))) != 1)
{
//change file status
$arEntry['status'] = "path_creation_fail";
//return $res;
$res = 1;
}
}
}
}
//check if extraction should be done
if ($arEntry['status'] == 'ok')
{
//if not a folder - extract
if (!(($arEntry['external'] & 0x00000010) == 0x00000010))
{
//if zip file with 0 compression
if (($arEntry['compression'] == 0) && ($arEntry['compressed_size'] == $arEntry['size']))
{
if (($destFile = @fopen($arEntry['filename'], 'wb')) == 0)
{
$arEntry['status'] = "write_error";
return $res;
}
//reading the fileby by self::ReadBlockSize octets blocks
$size = $arEntry['compressed_size'];
while ($size != 0)
{
$length = ($size < self::ReadBlockSize ? $size : self::ReadBlockSize);
$buffer = fread($this->zipfile, $length);
$binary_data = pack('a' . $length, $buffer);
@fwrite($destFile, $binary_data, $length);
$size -= $length;
}
//close the destination file
fclose($destFile);
//changing file modification time
touch($arEntry['filename'], $arEntry['mtime']);
}
else
{
if (($destFile = @fopen($arEntry['filename'], 'wb')) == 0)
{
//change file status
$arEntry['status'] = "write_error";
return $res;
}
//read the compressed file in a buffer (one shot)
$buffer = @fread($this->zipfile, $arEntry['compressed_size']);
//decompress the file
$fileContent = gzinflate($buffer);
unset($buffer);
//write uncompressed data
@fwrite($destFile, $fileContent, $arEntry['size']);
unset($fileContent);
@fclose($destFile);
touch($arEntry['filename'], $arEntry['mtime']);
}
if ((isset($arParams['set_chmod'])) && ($arParams['set_chmod'] != 0))
{
chmod($arEntry['filename'], $arParams['set_chmod']);
}
}
}
//post-extract callback
if ((isset($arParams['callback_post_extract'])) && ($arParams['callback_post_extract'] != ''))
{
//make local info
$arLocalHeader = [];
$this->_convertHeader2FileInfo($arEntry, $arLocalHeader);
//callback call
eval('$res = ' . $arParams['callback_post_extract'] . '('callback_post_extract', $arLocalHeader);');
}
return $res;
}