PluginProbe ʕ •ᴥ•ʔ
JetBackup – Backup, Restore & Migrate / 3.1.13.4
JetBackup – Backup, Restore & Migrate v3.1.13.4
3.1.22.3 1.4.3 1.4.4 1.4.5 1.4.6 1.4.7 1.4.8 1.4.8.1 1.4.9 1.5.0 1.5.1 1.5.1.1 1.5.2 1.5.3 1.5.4 1.5.5 1.5.6 1.5.7 1.5.8 1.6.0 1.6.10 1.6.11 1.6.12 1.6.13 1.6.15 1.6.5.1 1.6.8.8 1.6.9 1.6.9.1 2.0.3 2.0.4 2.0.5 2.0.6 2.0.7.5 2.0.8.7 2.0.9.11 2.0.9.14 2.0.9.15 2.0.9.6 2.0.9.7 2.0.9.9 3.1.10.7 3.1.11.1 3.1.12.3 3.1.13.4 3.1.14.17 3.1.15.4 3.1.16.1 3.1.17.5 3.1.18.10 3.1.18.8 3.1.18.9 3.1.19.8 3.1.20.3 3.1.21.3 3.1.7.9 3.1.9.2 trunk 1.1.90 1.1.91 1.2.0 1.2.5 1.2.6 1.2.7 1.2.8 1.2.9 1.3.0 1.3.1 1.3.2 1.3.3 1.3.4 1.3.6 1.3.7 1.3.8 1.3.9 1.4.0 1.4.1 1.4.2
backup / src / JetBackup / Archive / Gzip.php
backup / src / JetBackup / Archive Last commit date
Data 9 months ago File 9 months ago Header 9 months ago Scan 9 months ago .htaccess 9 months ago Archive.php 9 months ago Gzip.php 9 months ago index.html 9 months ago web.config 9 months ago
Gzip.php
153 lines
1 <?php
2
3 namespace JetBackup\Archive;
4
5 use JetBackup\DirIterator\DirIteratorFile;
6 use JetBackup\Exception\GzipException;
7
8 if (!defined( '__JETBACKUP__')) die('Direct access is not allowed');
9
10 /**
11 * Class for compressing files using gzip.
12 */
13 class Gzip {
14
15 const DEFAULT_COMPRESS_CHUNK_SIZE = 10485760; // 10MB
16 const DEFAULT_DECOMPRESS_CHUNK_SIZE = 1048576; // 1MB
17 const DEFAULT_COMPRESSION_LEVEL = -1;
18
19 private function __construct() {}
20
21 /**
22 * @throws GzipException
23 */
24 private static function _getInfo($file) {
25 $info = new \stdClass();
26 if(file_exists($file)) {
27 $info = json_decode(file_get_contents($file));
28 if($info === false) throw new GzipException("Failed fetching compress information");
29 }
30 return $info;
31 }
32
33 /**
34 * @param $file
35 * @param $data
36 *
37 * @return void
38 * @throws GzipException
39 */
40 private static function _putInfo($file, $data) {
41 $tempFile = $file . '.tmp';
42 $jsonData = json_encode($data);
43 if ($jsonData === false) {
44 throw new GzipException("Failed to encode compress information");
45 }
46
47 if (file_put_contents($tempFile, $jsonData) === false) {
48 throw new GzipException("Failed to write compress information to temporary file");
49 }
50
51 if (!rename($tempFile, $file)) {
52 throw new GzipException("Failed to atomically write compress information");
53 }
54 }
55
56
57 /**
58 * @throws GzipException
59 */
60 public static function compress($file, $chunkSize=self::DEFAULT_COMPRESS_CHUNK_SIZE, $compressionLevel=self::DEFAULT_COMPRESSION_LEVEL, ?callable $callback=null) {
61 if(!file_exists($file) || !is_file($file)) throw new GzipException("Source file not found");
62
63 $target = $file . '.gz';
64
65 $info_file = $target . '.compress.info';
66 $info = self::_getInfo($info_file);
67
68 $fd = fopen($file, 'r');
69 $gzfd = fopen($target, 'ab');
70
71 $read = $write = 0;
72 if(isset($info->fdpos) && $info->fdpos) {
73 $read = $info->fdpos;
74 fseek($fd, $info->fdpos);
75 }
76 if(isset($info->fdgzpos) && $info->fdgzpos) {
77 $write = $info->fdgzpos;
78 fseek($gzfd, $info->fdgzpos);
79 }
80
81 while(!feof($fd)) {
82 $write += fwrite($gzfd, gzencode(fread($fd, $chunkSize), $compressionLevel));
83 $read += $chunkSize;
84
85 self::_putInfo($info_file, [
86 'fdpos' => $read,
87 'fdgzpos' => $write,
88 ]);
89
90 if($callback) $callback($read, DirIteratorFile::safe_filesize($file));
91 }
92
93 if(feof($fd)) {
94 @unlink($file);
95 @unlink($info_file);
96 }
97
98 fclose($fd);
99 fclose($gzfd);
100 }
101
102 /**
103 * @throws GzipException
104 */
105 public static function decompress($file, ?callable $callback=null, $chunkSize=self::DEFAULT_DECOMPRESS_CHUNK_SIZE) {
106 if(!file_exists($file) || !is_file($file)) throw new GzipException("Source file not found");
107
108 $info_file = $file . '.decompress.info';
109 $info = self::_getInfo($info_file);
110
111 // remove .gz suffix
112 $target = substr($file, 0, -3);
113
114 $fd = fopen($target, 'a');
115 $gzfd = gzopen($file, 'rb');
116
117 $read = $write = 0;
118 if(isset($info->fdpos) && $info->fdpos) {
119 $write = $info->fdpos;
120 fseek($fd, $info->fdpos);
121 }
122
123 if(isset($info->fdgzpos) && $info->fdgzpos) {
124 $read = $info->fdgzpos;
125 gzseek($gzfd, $info->fdgzpos);
126 }
127
128 while(!feof($gzfd)) {
129 $write += fwrite($fd, gzread($gzfd, $chunkSize));
130 $read += $chunkSize;
131
132 self::_putInfo($info_file, [
133 'fdpos' => $write,
134 'fdgzpos' => $read,
135 ]);
136
137 if($callback) $callback(
138 'Gzip',
139 'Decompressing',
140 (int) (DirIteratorFile::safe_filesize($file) * 3), // estimating X3 compression ratio, just for percentage calc
141 $read)
142 ;
143 }
144
145 if(feof($gzfd)) {
146 @unlink($file);
147 @unlink($info_file);
148 }
149
150 fclose($fd);
151 gzclose($gzfd);
152 }
153 }