PluginProbe ʕ •ᴥ•ʔ
JetBackup – Backup, Restore & Migrate / 3.1.13.4
JetBackup – Backup, Restore & Migrate v3.1.13.4
3.1.22.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 / Entities / Util.php
backup / src / JetBackup / Entities Last commit date
.htaccess 9 months ago Util.php 9 months ago index.html 9 months ago web.config 9 months ago
Util.php
297 lines
1 <?php
2
3 namespace JetBackup\Entities;
4
5 use DateTime;
6 use DateTimeZone;
7 use Exception;
8 use JetBackup\Exception\IOException;
9 use JetBackup\Factory;
10 use JetBackup\Filesystem\File;
11 use JetBackup\JetBackup;
12
13 if (!defined( '__JETBACKUP__')) die('Direct access is not allowed');
14
15 class Util {
16
17 public const WEB_CONFIG_FILE = "%sweb.config";
18 const HTACCESS_FILE = "%s.htaccess";
19 const INDEX_HTML_FILE = "%sindex.html";
20
21 private function __construct() {}
22
23 /**
24 * @param string $directory
25 * @param bool $remove_main
26 * @param bool $verify
27 *
28 * @return void
29 * @throws IOException
30 */
31 public static function rm(string $directory, bool $remove_main=true):void {
32
33 if(!$directory) return;
34
35 $file = new File($directory);
36 if(!$file->exists()) return;
37
38 if($file->isFile() || $file->isLink()) {
39 unlink($directory);
40 return;
41 }
42
43 $main_length = strlen($directory);
44 if (($dir = @dir($directory)) === false) throw new IOException("Cannot delete directory $directory");
45 $queue = [$dir];
46
47 while($queue) {
48 $obj = array_shift($queue);
49
50 while ($obj !== false && ($fileName = $obj->read()) !== false) {
51 if($fileName == '.' || $fileName == '..') continue;
52
53 $file = new File($obj->path . '/' . $fileName);
54
55 if($file->isLink() || !$file->isDir()) {
56 if(!@unlink($file->path()))
57 throw new IOException("cannot remove file \"{$file->path()}\"");
58 continue;
59 }
60 array_unshift($queue, $obj);
61 $obj = dir($file->path());
62 }
63
64 if($obj !== false && ($remove_main || strlen($obj->path) != $main_length) && !@rmdir($obj->path))
65 throw new IOException("cannot remove \"$obj->path\": Directory not empty");
66
67 }
68 }
69
70 public static function cp(string $source, string $destination, int $permissions=0777, array $excludes=[]):void {
71 if(!file_exists($source)) throw new IOException("Source dir does not exist");
72 if(is_file($source)) {
73 foreach($excludes as $exclude) if(preg_match("#$exclude#", $source)) return;
74 if(!copy($source, $destination))
75 throw new IOException("Failed copping file \"$source\"");
76 return;
77 }
78
79 if(!file_exists($destination) || !is_dir($destination)) throw new IOException("Destination dir does not exist");
80
81 $queue = [$source];
82
83 while($queue) {
84 $dirName = array_shift($queue);
85 $dirObj = dir($dirName);
86
87 while (($fileName = $dirObj->read()) !== false) {
88 if($fileName == '.' || $fileName == '..') continue;
89
90 $filePath = $dirObj->path . '/' . $fileName;
91 $destFile = trim(preg_replace('/^' . preg_quote($source, '/') . '/', '', $dirObj->path), '/');
92
93 @mkdir($destination . '/' . $destFile, $permissions);
94
95 if(is_dir($filePath)) {
96 $queue[] = $filePath;
97 continue;
98 }
99
100 foreach($excludes as $exclude) if(preg_match("#$exclude#", $filePath)) continue 2;
101 if(!copy($filePath, $destination . '/' . $destFile . '/' . $fileName))
102 throw new IOException("Failed copping file \"$filePath\"");
103 }
104 }
105 }
106
107 public static function generateRandomString(int $length = 12): string {
108 try {
109 return substr(bin2hex(random_bytes(ceil($length / 2))), 0, $length);
110 } catch (Exception $e) {
111 // Fallback in case /dev/urandom is not readable
112 return substr(base64_encode(uniqid(mt_rand(), true)), 0, $length);
113 }
114 }
115
116
117 /**
118 * @param string|int $time
119 *
120 * @return DateTime
121 * @throws Exception
122 */
123 public static function getDateTime($time='now'): DateTime {
124 if(is_int($time)) $time = '@' . $time;
125 return new DateTime($time, new DateTimeZone(Factory::getSettingsGeneral()->getTimeZone()));
126 }
127
128 /**
129 * @throws Exception
130 */
131 public static function date(string $format, $timestamp=0): string {
132 if (!$timestamp || $timestamp == 0) $timestamp = time();
133 return self::getDateTime($timestamp)->format($format);
134 }
135
136 public static function generateUniqueId(): string {
137 static $inc;
138 if(!$inc) $inc = 0;
139 return sprintf("%08x%08x%08x", time(), floatval(microtime())*1000000, $inc++);
140 }
141
142 public static function generatePassword(int $length = 20 ): string {
143 $chars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!@#$%^&*()-_=+';
144 $charLength = strlen($chars);
145 $password = '';
146
147 while (strlen($password) < $length) {
148 $rand = random_int(0, PHP_INT_MAX);
149 $password .= $chars[$rand % $charLength];
150 }
151
152 return $password;
153 }
154
155
156 public static function humanReadableToBytes($sSize) {
157 if (is_numeric($sSize)) return $sSize;
158
159 $iValue = intval($sSize);
160 $sSuffix = strtoupper(substr($sSize, strlen($iValue)));
161
162 switch ($sSuffix) {
163 case 'PB': case 'P': $iValue *= 1125899906842624; break;
164 case 'TB': case 'T': $iValue *= 1099511627776; break;
165 case 'GB': case 'G': $iValue *= 1073741824; break;
166 case 'MB': case 'M': $iValue *= 1048576; break;
167 case 'KB': case 'K': $iValue *= 1024; break;
168 }
169 return $iValue;
170 }
171
172 public static function bytesToHumanReadable($bytes, $precision = 2): string {
173 if (!is_numeric($bytes)) {
174 // Handle the error, return an error message, or throw an exception
175 return 'Invalid numeric value';
176 }
177
178 $units = ['B', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'];
179
180 $bytes = max($bytes, 0);
181 $pow = floor(($bytes ? log($bytes) : 0) / log(1024));
182 $pow = min($pow, count($units) - 1);
183 $bytes /= (1 << (10 * $pow));
184
185 return round($bytes, $precision) . ' ' . $units[$pow];
186 }
187
188 /**
189 * @param string $path
190 *
191 * @return string
192 */
193 public static function mb_basename(string $path):string {
194 if(!$path) return '';
195 $path = preg_replace("#/+#", "/", $path);
196 if($path == '/') return '';
197 $path = preg_replace("#/$#", "", $path);
198 $pos = mb_strrpos(mb_convert_encoding($path, 'UTF-8'), "/");
199 return $pos !== false ? mb_substr($path, $pos+1) : $path;
200 }
201
202 /**
203 * @param string $path
204 *
205 * @return string
206 */
207 public static function mb_dirname(string $path):string {
208 if(!$path) return '.';
209 $path = preg_replace("#/+#", "/", $path);
210 if($path == '/') return '/';
211 $path = preg_replace("#/$#", "", $path);
212 $pos = mb_strrpos(mb_convert_encoding($path, 'UTF-8'), "/");
213 return $pos !== false ? mb_substr($path, 0, $pos) : $path;
214 }
215
216 public static function generateTimeZoneList(): array {
217 $timezones = DateTimeZone::listAbbreviations();
218 $timezone_readable = [];
219 foreach ($timezones as $timezone_area) {
220 foreach ($timezone_area as $timezone) {
221 // Ensure timezone_id is not null before trimming
222 if (is_null($timezone['timezone_id']) || trim($timezone['timezone_id']) == '') continue;
223 if (trim($timezone['timezone_id']) == 'GB') continue;
224 $hours = ($timezone['offset'] / 3600);
225 $offset = floor($hours); // Round the result to the nearest 0.5
226 $timezone_readable[$timezone['timezone_id']] = $offset;
227 }
228 }
229 ksort($timezone_readable);
230 return $timezone_readable;
231 }
232
233 public static function IISWebConfig(): string {
234
235 return <<<XML
236 <?xml version="1.0" encoding="UTF-8"?>
237 <configuration>
238 <system.webServer>
239 <security>
240 <authorization>
241 <remove users="*" roles="" verbs="" />
242 <add accessType="Deny" users="*" />
243 </authorization>
244 </security>
245 </system.webServer>
246 </configuration>
247 XML;
248
249 }
250
251
252 public static function getpwuid ($uid = null) : ?array {
253
254 if (!$uid) return null;
255 return function_exists('posix_getpwuid') ? posix_getpwuid($uid) : null;
256
257 }
258
259 public static function getgrgid ($gid = null) : ?array {
260
261 if (!$gid) return null;
262 return function_exists('posix_getgrgid') ? posix_getgrgid($gid) : null;
263
264 }
265
266 public static function geteuid () : ?int {
267 return function_exists('posix_geteuid') ? posix_geteuid() : null;
268 }
269
270
271
272
273
274 public static function secureFolder($folder): void {
275
276 $config_file = sprintf(self::WEB_CONFIG_FILE, $folder . JetBackup::SEP);
277 $htaccess_file = sprintf(self::HTACCESS_FILE, $folder . JetBackup::SEP);
278 $html_file = sprintf(self::INDEX_HTML_FILE, $folder . JetBackup::SEP);
279
280 if(!file_exists($folder)) mkdir($folder, 0700, true);
281 if(!file_exists($htaccess_file)) file_put_contents($htaccess_file, "Deny from all");
282 if(!file_exists($html_file)) file_put_contents($html_file, "");
283 if(!file_exists($config_file)) file_put_contents($config_file, self::IISWebConfig());
284
285 }
286
287 /**
288 * Normalizes a path format by replacing double forward slashes (//)
289 *
290 * @param string $path The path to be converted.
291 * @return string The converted Windows-style path.
292 */
293 public static function normalizePath(string $path): string
294 {
295 return str_replace('\\', JetBackup::SEP, $path);
296 }
297 }