25 private $add_path =
"";
26 private $remove_path =
"";
27 private $startFile =
"";
28 private $lastFile = [];
29 private $step_time = 30;
30 private $tempres =
false;
31 private $replaceExistentFiles =
false;
32 private $checkPermissions =
true;
40 $this->file_pos = $pos;
41 $this->_bCompress = $bCompress;
46 if (@file_exists($this->io->GetPhysicalName($strArchiveName)))
48 if ($fp = @fopen($this->io->GetPhysicalName($strArchiveName),
"rb"))
50 $data = fread($fp, 2);
52 if (
$data ==
"\37\213")
54 $this->_bCompress =
true;
60 if (str_ends_with($strArchiveName,
'gz'))
62 $this->_bCompress =
true;
68 $this->_bCompress =
true;
71 $this->_strArchiveName = $strArchiveName;
72 $this->_arErrors = [];
81 public function Pack($arFileList, $startFile =
"")
83 $this->_arErrors = [];
84 $this->startFile = $this->io->GetPhysicalName($startFile);
87 if (file_exists($this->io->GetPhysicalName($this->_strArchiveName))
88 && is_file($this->io->GetPhysicalName($this->_strArchiveName)) && ($startFile !=
""))
95 if (!$this->_openWrite())
102 if (!$this->_openAppendFast())
109 $arFileList = $this->_parseFileParams($arFileList);
111 $arConvertedFileList = [];
112 foreach ($arFileList as $fullpath)
114 $arConvertedFileList[] = $this->io->GetPhysicalName($fullpath);
117 $this->tempres =
null;
119 if (is_array($arFileList) && !empty($arFileList))
121 $res = $this->_processFiles($arConvertedFileList, $this->add_path, $this->remove_path);
124 if (
$res !==
false &&
$res !==
"continue")
126 $this->_writeFooter();
131 if ($bNewArchive && (
$res ===
false))
137 if (
$res ===
'continue')
139 $this->startFile = $this->io->GetLogicalName(array_pop($this->lastFile));
165 $this->_arErrors = [];
170 $strExtrType =
"complete";
173 if ($v_result = $this->_openRead())
175 $v_result = $this->_extractList($strPath, $v_list_detail, $strExtrType, $arFileList,
'');
188 return $this->startFile;
191 private function _haveTime()
196 private function _processFiles($arFileList, $strAddPath, $strRemovePath)
198 $strAddPath = str_replace(
"\\",
"/", $strAddPath);
199 $strRemovePath = str_replace(
"\\",
"/", $strRemovePath);
203 $this->_arErrors[] = [
"ERR_DFILE",
GetMessage(
"MAIN_ARCHIVE_ERR_DFILE")];
207 if (!is_array($arFileList) || empty($arFileList))
214 if (!isset($this->tempres))
216 $this->tempres =
"started";
220 while ($j++ <
count($arFileList) && ($this->tempres ===
"started"))
222 $strFilename = $arFileList[$j] ??
'';
224 if ($this->_normalizePath($strFilename) == $this->_normalizePath($this->_strArchiveName))
229 if ($strFilename ==
'')
234 if (!file_exists($strFilename))
236 $this->_arErrors[] = [
"NO_FILE", str_replace(
"#FILE_NAME#",
removeDocRoot($strFilename),
GetMessage(
"MAIN_ARCHIVE_NO_FILE"))];
240 if (!@is_dir($strFilename))
242 $strFilename = str_replace(
"//",
"/", $strFilename);
245 if ($this->startFile <>
'')
247 if ($strFilename != $this->startFile)
255 $this->startFile =
null;
261 if ($this->checkPermissions)
269 if ($this->_haveTime())
271 if (!$this->_addFile($strFilename, $this->add_path, $this->remove_path))
274 $this->tempres =
false;
279 $this->lastFile[] = $strFilename;
284 $this->tempres =
"continue";
285 return $this->tempres;
291 if (!(
$handle = opendir($strFilename)))
293 $this->_arErrors[] = [
"NO_READ", str_replace(
"#DIR_NAME#", $strFilename,
GetMessage(
"MAIN_ARCHIVE_ERR_DFILE"))];
297 if ($this->checkPermissions)
309 $arFileList_tmp = [];
310 if ($strFilename !=
".")
312 $arFileList_tmp[] = $strFilename .
'/' .
$dir;
316 $arFileList_tmp[] =
$dir;
319 $this->_processFiles($arFileList_tmp, $strAddPath, $strRemovePath);
323 unset($arFileList_tmp);
329 return $this->tempres;
341 $this->_bCompress =
$arOptions[
"COMPRESS"] ===
true;
347 $this->stepped =
$arOptions[
"STEPPED"] ===
true;
350 if (array_key_exists(
"START_TIME",
$arOptions))
352 $this->start_time = floatval(
$arOptions[
"START_TIME"]);
355 if (array_key_exists(
"MAX_EXEC_TIME",
$arOptions))
357 $this->max_exec_time = intval(
$arOptions[
"MAX_EXEC_TIME"]);
362 $this->file_pos = intval(
$arOptions[
"FILE_POS"]);
368 $this->add_path = $this->io->GetPhysicalName(str_replace(
"\\",
"/", strval(
$arOptions[
"ADD_PATH"])));
371 if (array_key_exists(
"REMOVE_PATH",
$arOptions))
373 $this->remove_path = $this->io->GetPhysicalName(str_replace(
"\\",
"/", strval(
$arOptions[
"REMOVE_PATH"])));
377 if (array_key_exists(
"STEP_TIME",
$arOptions))
379 $this->step_time = floatval(
$arOptions[
"STEP_TIME"]);
382 if (array_key_exists(
"UNPACK_REPLACE",
$arOptions))
384 $this->replaceExistentFiles =
$arOptions[
"UNPACK_REPLACE"] ===
true;
387 if (array_key_exists(
"CHECK_PERMISSIONS",
$arOptions))
389 $this->checkPermissions =
$arOptions[
"CHECK_PERMISSIONS"] ===
true;
405 "ADD_PATH" => $this->add_path,
406 "REMOVE_PATH" => $this->remove_path,
407 "STEP_TIME" => $this->step_time,
408 "UNPACK_REPLACE" => $this->replaceExistentFiles,
409 "CHECK_PERMISSIONS" => $this->checkPermissions,
422 public function Add($vFileList, $strAddPath =
false, $strRemovePath =
false)
424 $this->_arErrors = [];
427 if (file_exists($this->io->GetPhysicalName($this->_strArchiveName))
428 && is_file($this->io->GetPhysicalName($this->_strArchiveName)))
430 $bNewArchive =
false;
435 if (!$this->_openWrite())
442 if (!$this->_openAppend())
448 $arFileList = $this->_parseFileParams($vFileList);
450 if (is_array($arFileList) && !empty($arFileList))
452 $res = $this->_addFileList($arFileList, $strAddPath, $strRemovePath);
457 $this->_writeFooter();
462 if ($bNewArchive && !
$res)
477 public function addFile($strFilename, $strAddPath, $strRemovePath)
479 $strAddPath = str_replace(
"\\",
"/", $strAddPath);
480 $strRemovePath = str_replace(
"\\",
"/", $strRemovePath);
484 $this->_arErrors[] = [
"ERR_DFILE",
GetMessage(
"MAIN_ARCHIVE_ERR_DFILE")];
488 if ($strFilename ==
'')
493 if (!file_exists($this->io->GetPhysicalName($strFilename)))
495 $this->_arErrors[] = [
"NO_FILE",
"File '" . $strFilename .
"' does not exist"];
499 if (!$this->_addFile($strFilename, $strAddPath, $strRemovePath))
513 public function addString($strFilename, $strFileContent)
515 $this->_arErrors = [];
517 if (!file_exists($this->io->GetPhysicalName($this->_strArchiveName))
518 || !is_file($this->io->GetPhysicalName($this->_strArchiveName)))
520 if (!$this->_openWrite())
527 if (!$this->_openAppend())
532 $res = $this->_addString($strFilename, $strFileContent);
534 $this->_writeFooter();
547 $this->_arErrors = [];
551 $strExtrType =
"complete";
553 if ($vFileList !==
false)
555 $arFileList = $this->_parseFileParams($vFileList);
556 $strExtrType =
"partial";
559 if ($v_result = $this->_openRead())
561 $v_result = $this->_extractList($strPath, $v_list_detail, $strExtrType, $arFileList,
'');
574 $this->_arErrors = [];
578 if ($this->_openRead())
580 if (!$this->_extractList(
'',
$arRes,
"list",
'',
''))
599 private function _addFileList($arFileList, $strAddPath, $strRemovePath)
602 $strAddPath = str_replace(
"\\",
"/", $strAddPath);
603 $strRemovePath = str_replace(
"\\",
"/", $strRemovePath);
607 $this->_arErrors[] = [
"ERR_DFILE",
GetMessage(
"MAIN_ARCHIVE_ERR_DFILE")];
611 if (!is_array($arFileList) || empty($arFileList))
616 $fileListCount =
count($arFileList);
617 for ($j = 0; ($j < $fileListCount) && ($v_result); $j++)
619 $strFilename = $arFileList[$j];
621 if ($strFilename == $this->_strArchiveName)
626 if ($strFilename ==
'')
631 if (!file_exists($this->io->GetPhysicalName($strFilename)))
633 $this->_arErrors[] = [
"NO_FILE",
"File '" . $strFilename .
"' does not exist"];
637 if (!$this->_addFile($strFilename, $strAddPath, $strRemovePath))
642 if (@is_dir($this->io->GetPhysicalName($strFilename)))
644 if (!(
$handle = opendir($this->io->GetPhysicalName($strFilename))))
646 $this->_arErrors[] = [
"NO_READ", str_replace(
"#DIR_NAME#", $strFilename,
GetMessage(
"MAIN_ARCHIVE_ERR_DFILE"))];
654 $arFileList_tmp = [];
655 if ($strFilename !=
".")
657 $arFileList_tmp[] = $strFilename .
'/' .
$dir;
661 $arFileList_tmp[] =
$dir;
664 $v_result = $this->_addFileList($arFileList_tmp, $strAddPath, $strRemovePath);
668 unset($arFileList_tmp);
677 private function _addFile($strFilename, $strAddPath, $strRemovePath)
681 $this->_arErrors[] = [
"ERR_DFILE",
GetMessage(
"MAIN_ARCHIVE_ERR_DFILE")];
685 if ($strFilename ==
'')
687 $this->_arErrors[] = [
"NO_FILENAME",
GetMessage(
"MAIN_ARCHIVE_NO_FILENAME")];
691 $strFilename = str_replace(
"\\",
"/", $strFilename);
692 $strFilename_stored = $strFilename;
694 if (strcmp($strFilename, $strRemovePath) == 0)
699 if ($strRemovePath <>
'')
701 if (!str_ends_with($strRemovePath,
'/'))
703 $strRemovePath .=
'/';
706 if (str_starts_with($strFilename, $strRemovePath))
708 $strFilename_stored = substr($strFilename, strlen($strRemovePath));
712 if ($strAddPath <>
'')
714 if (str_ends_with($strAddPath,
'/'))
716 $strFilename_stored = $strAddPath . $strFilename_stored;
720 $strFilename_stored = $strAddPath .
'/' . $strFilename_stored;
724 $strFilename_stored = $this->_normalizePath($strFilename_stored);
726 if (is_file($strFilename))
728 if (($dfile = @fopen($strFilename,
"rb")) == 0)
730 $this->_arErrors[] = [
"ERR_OPEN", str_replace(
"#FILE_NAME#",
removeDocRoot($strFilename),
GetMessage(
"MAIN_ARCHIVE_ERR_OPEN"))];
734 $istime = ((microtime(
true) -
$this->start_time) < round($this->max_exec_time)) || !$this->stepped;
738 if (($this->file_pos == 0))
740 if (!$this->_writeHeader($strFilename, $strFilename_stored))
746 if (($this->file_pos > 0) && $this->stepped)
748 if ($this->_bCompress)
750 @gzseek($dfile, $this->file_pos);
754 @fseek($dfile, $this->file_pos);
758 while ($istime && ($v_buffer = fread($dfile, 512)) !=
'')
760 $v_binary_data = pack(
"a512",
"$v_buffer");
761 $this->_writeBlock($v_binary_data);
762 $istime = ((microtime(
true) -
$this->start_time) < round($this->max_exec_time)) || !$this->stepped;
766 if ($istime && $this->stepped)
772 if ($this->_bCompress)
774 $this->file_pos = @gztell($dfile);
778 $this->file_pos = @ftell($dfile);
784 elseif (!$this->_writeHeader($strFilename, $strFilename_stored))
800 private function _addString($strFilename, $strFileContent)
804 $this->_arErrors[] = [
"ERR_DFILE",
GetMessage(
"MAIN_ARCHIVE_ERR_DFILE")];
808 if ($strFilename ==
'')
810 $this->_arErrors[] = [
"NO_FILENAME",
GetMessage(
"MAIN_ARCHIVE_NO_FILENAME")];
814 $strFilename = str_replace(
"\\",
"/", $strFilename);
816 if (!$this->_writeHeaderBlock($strFilename, strlen($strFileContent)))
822 while (($v_buffer = substr($strFileContent, ((
$i++) * 512), 512)) !=
'')
824 $v_binary_data = pack(
"a512", $v_buffer);
825 $this->_writeBlock($v_binary_data);
831 private function _extractList($p_path, &$p_list_detail, $p_mode, $p_file_list, $p_remove_path)
834 $v_extract_all =
true;
837 $p_path = str_replace(
"\\",
"/", $p_path);
838 $p_path = $this->io->GetPhysicalName($p_path);
841 || (!str_starts_with($p_path,
'/')
842 && !str_starts_with($p_path,
"../")
843 && !mb_strpos($p_path,
':')))
845 $p_path =
"./" . $p_path;
848 $p_remove_path = str_replace(
"\\",
"/", $p_remove_path);
849 if (($p_remove_path !=
'') && (!str_ends_with($p_remove_path,
'/')))
851 $p_remove_path .=
'/';
859 $v_extract_all =
false;
862 $v_extract_all =
false;
866 $this->_arErrors[] = [
"ERR_PARAM", str_replace(
"#EXTRACT_MODE#", $p_mode,
GetMessage(
"MAIN_ARCHIVE_ERR_PARAM"))];
872 while (strlen($v_binary_data = $this->_readBlock()) != 0)
874 $v_extract_file =
false;
876 if (!$this->_readHeader($v_binary_data, $v_header))
881 if ($v_header[
'filename'] ==
'')
887 if ($v_header[
'typeflag'] ==
'L')
889 if (!$this->_readLongHeader($v_header))
894 if ((!$v_extract_all) && (is_array($p_file_list)))
901 if (str_ends_with($p_file_list[
$i],
'/'))
904 if ((mb_strlen($v_header[
'filename']) > mb_strlen($p_file_list[
$i]))
905 && (str_starts_with($v_header[
'filename'], $p_file_list[
$i])))
907 $v_extract_file =
true;
911 elseif ($p_file_list[
$i] == $v_header[
'filename'])
914 $v_extract_file =
true;
921 $v_extract_file =
true;
925 if (($v_extract_file) && (!$v_listing))
927 if (($p_remove_path !=
'')
928 && (str_starts_with($v_header[
'filename'], $p_remove_path)))
930 $v_header[
'filename'] = substr($v_header[
'filename'], strlen($p_remove_path));
932 if (($p_path !=
'./') && ($p_path !=
'/'))
934 while (str_ends_with($p_path,
'/'))
936 $p_path = substr($p_path, 0, -1);
939 if (str_starts_with($v_header[
'filename'],
'/'))
941 $v_header[
'filename'] = $p_path . $v_header[
'filename'];
945 $v_header[
'filename'] = $p_path .
'/' . $v_header[
'filename'];
948 if (file_exists($v_header[
'filename']))
950 if ((@is_dir($v_header[
'filename'])) && ($v_header[
'typeflag'] ==
''))
952 $this->_arErrors[] = [
"DIR_EXISTS", str_replace(
"#FILE_NAME#",
removeDocRoot($this->io->GetLogicalName($v_header[
'filename'])),
GetMessage(
"MAIN_ARCHIVE_DIR_EXISTS"))];
956 if ((is_file($v_header[
'filename'])) && ($v_header[
'typeflag'] ==
"5"))
958 $this->_arErrors[] = [
"FILE_EXISTS", str_replace(
"#FILE_NAME#",
removeDocRoot($this->io->GetLogicalName($v_header[
'filename'])),
GetMessage(
"MAIN_ARCHIVE_FILE_EXISTS"))];
961 if (!is_writeable($v_header[
'filename']))
963 $this->_arErrors[] = [
"FILE_PERMS", str_replace(
"#FILE_NAME#",
removeDocRoot($this->io->GetLogicalName($v_header[
'filename'])),
GetMessage(
"MAIN_ARCHIVE_FILE_PERMS"))];
967 elseif (($this->_dirCheck(($v_header[
'typeflag'] ==
"5" ? $v_header[
'filename'] : dirname($v_header[
'filename'])))) != 1)
969 $this->_arErrors[] = [
"NO_DIR", str_replace(
"#FILE_NAME#",
removeDocRoot($this->io->GetLogicalName($v_header[
'filename'])),
GetMessage(
"MAIN_ARCHIVE_NO_DIR"))];
975 $this->_jumpBlock(ceil(($v_header[
'size'] / 512)));
978 elseif ((file_exists($v_header[
'filename']) && $this->replaceExistentFiles) || !(file_exists($v_header[
'filename'])))
980 if ($v_header[
'typeflag'] ==
"5")
982 if (!@file_exists($v_header[
'filename']))
984 if (!@mkdir($v_header[
'filename'], BX_DIR_PERMISSIONS))
986 $this->_arErrors[] = [
"ERR_CREATE_DIR", str_replace(
"#DIR_NAME#",
removeDocRoot($this->io->GetLogicalName($v_header[
'filename'])),
GetMessage(
"MAIN_ARCHIVE_ERR_CREATE_DIR"))];
993 if (($v_dest_file = @fopen($v_header[
'filename'],
"wb")) == 0)
995 $this->_arErrors[] = [
"ERR_CREATE_FILE", str_replace(
"#FILE_NAME#",
removeDocRoot($this->io->GetLogicalName($v_header[
'filename'])),
GetMessage(
"MAIN_ARCHIVE_ERR_CREATE_FILE"))];
1000 $n = floor($v_header[
'size'] / 512);
1003 $v_content = $this->_readBlock();
1004 fwrite($v_dest_file, $v_content, 512);
1006 if (($v_header[
'size'] % 512) != 0)
1008 $v_content = $this->_readBlock();
1009 fwrite($v_dest_file, $v_content, ($v_header[
'size'] % 512));
1012 @fclose($v_dest_file);
1014 @chmod($v_header[
'filename'], BX_FILE_PERMISSIONS);
1015 @touch($v_header[
'filename'], $v_header[
'mtime']);
1019 if (filesize($v_header[
'filename']) != $v_header[
'size'])
1021 $this->_arErrors[] = [
"ERR_SIZE_CHECK", str_replace([
"#FILE_NAME#",
"#SIZE#",
"#EXP_SIZE#"], [
removeDocRoot($v_header[
'size']), filesize($v_header[
'filename']), $v_header[
'size']],
GetMessage(
"MAIN_ARCHIVE_ERR_SIZE_CHECK"))];
1028 $this->_jumpBlock(ceil(($v_header[
'size'] / 512)));
1033 $this->_jumpBlock(ceil(($v_header[
'size'] / 512)));
1036 if ($v_listing || $v_extract_file)
1038 if (($v_file_dir = dirname($v_header[
'filename'])) == $v_header[
'filename'])
1042 if ((str_starts_with($v_header[
'filename'],
'/')) && ($v_file_dir ==
''))
1047 $p_list_detail[$v_nb++] = $v_header;
1054 private function _writeHeader($strFilename, $strFilename_stored)
1056 if ($strFilename_stored ==
'')
1058 $strFilename_stored = $strFilename;
1061 $strFilename_ready = $this->_normalizePath($strFilename_stored);
1063 if (strlen($strFilename_ready) > 99)
1065 if (!$this->_writeLongHeader($strFilename_ready))
1071 $v_info = stat($strFilename);
1072 $v_uid = sprintf(
"%6s ", DecOct($v_info[
'uid']));
1073 $v_gid = sprintf(
"%6s ", DecOct($v_info[
'gid']));
1074 $v_perms = sprintf(
"%6s ", DecOct(fileperms($strFilename)));
1075 $v_mtime = sprintf(
"%11s", DecOct(filemtime($strFilename)));
1077 if (@is_dir($strFilename))
1080 $v_size = sprintf(
"%11s ", DecOct(0));
1086 $v_size = sprintf(
"%11s ", DecOct(filesize($strFilename)));
1098 $v_binary_data_first = pack(
"a100a8a8a8a12A12", $strFilename_ready, $v_perms, $v_uid, $v_gid, $v_size, $v_mtime);
1099 $v_binary_data_last = pack(
"a1a100a6a2a32a32a8a8a155a12", $v_typeflag, $v_linkname, $v_magic, $v_version, $v_uname, $v_gname, $v_devmajor, $v_devminor, $v_prefix,
'');
1102 for (
$i = 0;
$i < 148;
$i++)
1104 $v_checksum += ord(substr($v_binary_data_first,
$i, 1));
1106 for (
$i = 148;
$i < 156;
$i++)
1108 $v_checksum += ord(
' ');
1110 for (
$i = 156, $j = 0;
$i < 512;
$i++, $j++)
1112 $v_checksum += ord(substr($v_binary_data_last, $j, 1));
1115 $this->_writeBlock($v_binary_data_first, 148);
1117 $v_checksum = sprintf(
"%6s ", DecOct($v_checksum));
1118 $v_binary_data = pack(
"a8", $v_checksum);
1119 $this->_writeBlock($v_binary_data, 8);
1121 $this->_writeBlock($v_binary_data_last, 356);
1126 private function _writeLongHeader($strFilename)
1128 $v_size = sprintf(
"%11s ", DecOct(mb_strlen($strFilename)));
1138 $v_binary_data_first = pack(
"a100a8a8a8a12A12",
'././@LongLink', 0, 0, 0, $v_size, 0);
1139 $v_binary_data_last = pack(
"a1a100a6a2a32a32a8a8a155a12", $v_typeflag, $v_linkname, $v_magic, $v_version, $v_uname, $v_gname, $v_devmajor, $v_devminor, $v_prefix,
'');
1142 for (
$i = 0;
$i < 148;
$i++)
1144 $v_checksum += ord(substr($v_binary_data_first,
$i, 1));
1147 for (
$i = 148;
$i < 156;
$i++)
1149 $v_checksum += ord(
' ');
1152 for (
$i = 156, $j = 0;
$i < 512;
$i++, $j++)
1154 $v_checksum += ord(substr($v_binary_data_last, $j, 1));
1157 $this->_writeBlock($v_binary_data_first, 148);
1159 $v_checksum = sprintf(
"%6s ", DecOct($v_checksum));
1160 $v_binary_data = pack(
"a8", $v_checksum);
1161 $this->_writeBlock($v_binary_data, 8);
1163 $this->_writeBlock($v_binary_data_last, 356);
1165 $p_filename = $this->_normalizePath($strFilename);
1168 while (($v_buffer = substr($p_filename, ((
$i++) * 512), 512)) !=
'')
1170 $v_binary_data = pack(
"a512",
"$v_buffer");
1171 $this->_writeBlock($v_binary_data);
1176 private function _writeHeaderBlock($strFilename, $iSize, $p_mtime = 0, $p_perms = 0, $p_type =
'', $p_uid = 0, $p_gid = 0)
1178 $strFilename = $this->_normalizePath($strFilename);
1180 if (mb_strlen($strFilename) > 99)
1182 if (!$this->_writeLongHeader($strFilename))
1190 $v_size = sprintf(
"%11s ", DecOct(0));
1194 $v_size = sprintf(
"%11s ", DecOct($iSize));
1197 $v_uid = sprintf(
"%6s ", DecOct($p_uid));
1198 $v_gid = sprintf(
"%6s ", DecOct($p_gid));
1199 $v_perms = sprintf(
"%6s ", DecOct($p_perms));
1200 $v_mtime = sprintf(
"%11s", DecOct($p_mtime));
1210 $v_binary_data_first = pack(
"a100a8a8a8a12A12", $strFilename, $v_perms, $v_uid, $v_gid, $v_size, $v_mtime);
1211 $v_binary_data_last = pack(
"a1a100a6a2a32a32a8a8a155a12", $p_type, $v_linkname, $v_magic, $v_version, $v_uname, $v_gname, $v_devmajor, $v_devminor, $v_prefix,
'');
1214 for (
$i = 0;
$i < 148;
$i++)
1216 $v_checksum += ord(substr($v_binary_data_first,
$i, 1));
1218 for (
$i = 148;
$i < 156;
$i++)
1220 $v_checksum += ord(
' ');
1222 for (
$i = 156, $j = 0;
$i < 512;
$i++, $j++)
1224 $v_checksum += ord(substr($v_binary_data_last, $j, 1));
1227 $this->_writeBlock($v_binary_data_first, 148);
1229 $v_checksum = sprintf(
"%6s ", DecOct($v_checksum));
1230 $v_binary_data = pack(
"a8", $v_checksum);
1231 $this->_writeBlock($v_binary_data, 8);
1233 $this->_writeBlock($v_binary_data_last, 356);
1238 private function _readBlock()
1241 if (is_resource($this->_dFile))
1243 if ($this->_bCompress)
1245 $v_block = @gzread($this->_dFile, 512);
1249 $v_block = @fread($this->_dFile, 512);
1255 private function _readHeader($v_binary_data, &$v_header)
1257 if (strlen($v_binary_data) == 0)
1259 $v_header[
'filename'] =
'';
1263 if (strlen($v_binary_data) != 512)
1265 $v_header[
'filename'] =
'';
1266 $this->_arErrors[] = [
"INV_BLOCK_SIZE", str_replace(
"#BLOCK_SIZE#", strlen($v_binary_data),
GetMessage(
"MAIN_ARCHIVE_INV_BLOCK_SIZE"))];
1271 for (
$i = 0;
$i < 148;
$i++)
1273 $v_checksum += ord(substr($v_binary_data,
$i, 1));
1275 for (
$i = 148;
$i < 156;
$i++)
1277 $v_checksum += ord(
' ');
1279 for (
$i = 156;
$i < 512;
$i++)
1281 $v_checksum += ord(substr($v_binary_data,
$i, 1));
1285 $v_data = unpack(
"a100filename/a8mode/a8uid/a8gid/a12size/a12mtime/a8checksum/a1typeflag/a100link/a6magic/a2version/a32uname/a32gname/a8devmajor/a8devminor/a131prefix", $v_binary_data);
1287 $v_header[
'checksum'] = octdec(trim($v_data[
'checksum']));
1288 if ($v_header[
'checksum'] != $v_checksum)
1290 $v_header[
'filename'] =
'';
1292 if (($v_checksum == 256) && ($v_header[
'checksum'] == 0))
1297 $this->_arErrors[] = [
"INV_BLOCK_CHECK",
GetMessage(
"MAIN_ARCHIVE_INV_BLOCK_CHECK1")];
1302 $v_header[
'filename'] = trim($v_data[
'prefix'] .
"/" . $v_data[
'filename']);
1303 $v_header[
'mode'] = octdec(trim($v_data[
'mode']));
1304 $v_header[
'uid'] = octdec(trim($v_data[
'uid']));
1305 $v_header[
'gid'] = octdec(trim($v_data[
'gid']));
1306 $v_header[
'size'] = octdec(trim($v_data[
'size']));
1307 $v_header[
'mtime'] = octdec(trim($v_data[
'mtime']));
1308 if (($v_header[
'typeflag'] = $v_data[
'typeflag']) ==
"5")
1310 $v_header[
'size'] = 0;
1313 $v_header[
'filename'] = \Bitrix\Main\IO\Path::normalize($v_header[
'filename']);
1318 private function _readLongHeader(&$v_header)
1322 $n = floor($v_header[
'size'] / 512);
1325 $v_content = $this->_readBlock();
1326 $v_filename .= $v_content;
1329 if (($v_header[
'size'] % 512) != 0)
1331 $v_content = $this->_readBlock();
1332 $v_filename .= trim($v_content);
1335 $v_binary_data = $this->_readBlock();
1337 if (!$this->_readHeader($v_binary_data, $v_header))
1342 $v_header[
'filename'] = \Bitrix\Main\IO\Path::normalize($v_filename);
1347 private function _jumpBlock($p_len =
false)
1349 if (is_resource($this->_dFile))
1351 if ($p_len ===
false)
1356 if ($this->_bCompress)
1358 @gzseek($this->_dFile, @gztell($this->_dFile) + ($p_len * 512));
1362 @fseek($this->_dFile, @ftell($this->_dFile) + ($p_len * 512));
1367 private function _parseFileParams($vFileList)
1369 if (isset($vFileList) && is_array($vFileList))
1374 if (isset($vFileList) && $vFileList <>
'')
1376 if (str_starts_with($vFileList,
"\""))
1378 return [trim($vFileList,
"\"")];
1380 return explode($this->_strSeparator, $vFileList);
1386 private function _openWrite()
1388 $this->_checkDirPath($this->_strArchiveName);
1390 if ($this->_bCompress)
1392 $this->_dFile = @gzopen($this->io->GetPhysicalName($this->_strArchiveName),
"wb9f");
1396 $this->_dFile = @fopen($this->io->GetPhysicalName($this->_strArchiveName),
"wb");
1399 if (!($this->_dFile))
1401 $this->_arErrors[] = [
"ERR_OPEN_WRITE", str_replace(
"#FILE_NAME#",
removeDocRoot($this->_strArchiveName),
GetMessage(
"MAIN_ARCHIVE_ERR_OPEN_WRITE"))];
1407 private function _openAppendFast()
1409 $this->_checkDirPath($this->_strArchiveName);
1411 if ($this->_bCompress)
1413 $this->_dFile = @gzopen($this->io->GetPhysicalName($this->_strArchiveName),
"ab9f");
1417 $this->_dFile = @fopen($this->io->GetPhysicalName($this->_strArchiveName),
"ab");
1419 if (!($this->_dFile))
1421 $this->_arErrors[] = [
"ERR_OPEN_WRITE", str_replace(
"#FILE_NAME#",
removeDocRoot($this->_strArchiveName),
GetMessage(
"MAIN_ARCHIVE_ERR_OPEN_WRITE"))];
1427 private function _openAppend()
1429 if (filesize($this->io->GetPhysicalName($this->_strArchiveName)) == 0)
1431 return $this->_openWrite();
1434 $this->_checkDirPath($this->_strArchiveName);
1436 if ($this->_bCompress)
1440 if (!@rename($this->io->GetPhysicalName($this->_strArchiveName), $this->io->GetPhysicalName($this->_strArchiveName .
".tmp")))
1442 $this->_arErrors[] = [
"ERR_RENAME", str_replace([
"#FILE_NAME#",
"#FILE_NAME2#"], [
removeDocRoot($this->_strArchiveName),
removeDocRoot($this->_strArchiveName .
".tmp")],
GetMessage(
"MAIN_ARCHIVE_ERR_RENAME"))];
1446 $dTarArch_tmp = @gzopen($this->io->GetPhysicalName($this->_strArchiveName .
".tmp"),
"rb");
1449 $this->_arErrors[] = [
"ERR_OPEN", str_replace(
"#FILE_NAME#",
removeDocRoot($this->_strArchiveName .
".tmp"),
GetMessage(
"MAIN_ARCHIVE_ERR_OPEN"))];
1450 @rename($this->io->GetPhysicalName($this->_strArchiveName .
".tmp"), $this->io->GetPhysicalName($this->_strArchiveName));
1454 if (!$this->_openWrite())
1456 @rename($this->io->GetPhysicalName($this->_strArchiveName .
".tmp"), $this->io->GetPhysicalName($this->_strArchiveName));
1460 $v_buffer = @gzread($dTarArch_tmp, 512);
1462 if (!@gzeof($dTarArch_tmp))
1466 $v_binary_data = pack(
"a512", $v_buffer);
1467 $this->_writeBlock($v_binary_data);
1468 $v_buffer = @gzread($dTarArch_tmp, 512);
1470 while (!@gzeof($dTarArch_tmp));
1473 @gzclose($dTarArch_tmp);
1475 @unlink($this->io->GetPhysicalName($this->_strArchiveName .
".tmp"));
1479 if (!$this->_openReadWrite())
1485 $iSize = filesize($this->io->GetPhysicalName($this->_strArchiveName));
1486 fseek($this->_dFile, $iSize - 512);
1492 private function _openReadWrite()
1494 if ($this->_bCompress)
1496 $this->_dFile = @gzopen($this->io->GetPhysicalName($this->_strArchiveName),
"r+b");
1500 $this->_dFile = @fopen($this->io->GetPhysicalName($this->_strArchiveName),
"r+b");
1511 private function _openRead()
1513 if ($this->_bCompress)
1515 $this->_dFile = @gzopen($this->io->GetPhysicalName($this->_strArchiveName),
"rb");
1519 $this->_dFile = @fopen($this->io->GetPhysicalName($this->_strArchiveName),
"rb");
1524 $this->_arErrors[] = [
"ERR_OPEN", str_replace(
"#FILE_NAME#",
removeDocRoot($this->_strArchiveName),
GetMessage(
"MAIN_ARCHIVE_ERR_OPEN"))];
1532 private function _writeBlock($v_binary_data, $iLen =
false)
1534 if (is_resource($this->_dFile))
1536 if ($iLen ===
false)
1538 if ($this->_bCompress)
1540 @gzputs($this->_dFile, $v_binary_data);
1544 @fputs($this->_dFile, $v_binary_data);
1549 if ($this->_bCompress)
1551 @gzputs($this->_dFile, $v_binary_data, $iLen);
1555 @fputs($this->_dFile, $v_binary_data, $iLen);
1561 private function _writeFooter()
1563 if (is_resource($this->_dFile))
1565 $v_binary_data = pack(
"a512",
'');
1566 $this->_writeBlock($v_binary_data);
1570 private function _cleanFile()
1573 @unlink($this->io->GetPhysicalName($this->_strArchiveName));
1576 private function _close()
1578 if (is_resource($this->_dFile))
1580 if ($this->_bCompress)
1582 @gzclose($this->_dFile);
1586 @fclose($this->_dFile);
1593 private function _normalizePath($strPath)
1598 $strPath = str_replace(
"\\",
"/", $strPath);
1600 while (str_contains($strPath,
".../"))
1602 $strPath = str_replace(
".../",
"../", $strPath);
1605 $arPath = explode(
'/', $strPath);
1607 for (
$i = $nPath - 1;
$i >= 0;
$i--)
1623 $strResult =
$arPath[
$i] . (
$i != ($nPath - 1) ?
'/' . $strResult :
'');
1630 private function _checkDirPath(
$path)
1632 $path = str_replace([
"\\",
"//"],
"/",
$path);
1635 if (!str_ends_with(
$path,
"/"))
1643 if (!file_exists($this->io->GetPhysicalName(
$path)))
1645 return mkdir($this->io->GetPhysicalName(
$path), BX_DIR_PERMISSIONS,
true);
1649 return is_dir($this->io->GetPhysicalName(
$path));
1653 private function _dirCheck($p_dir)
1655 if ((@is_dir($p_dir)) || ($p_dir ==
''))
1660 $p_parent_dir = dirname($p_dir);
1662 if (($p_parent_dir != $p_dir) &&
1663 ($p_parent_dir !=
'') &&
1664 (!$this->_dirCheck($p_parent_dir)))
1669 if (!@mkdir($p_dir, BX_DIR_PERMISSIONS))
1671 $this->_arErrors[] = [
"CANT_CREATE_PATH", str_replace(
"#DIR_NAME#", $p_dir,
GetMessage(
"MAIN_ARCHIVE_CANT_CREATE_PATH"))];;