PluginProbe
AcyMailing – An Ultimate Newsletter Plugin and Marketing Automation Solution for WordPress / 11.1.1
AcyMailing – An Ultimate Newsletter Plugin and Marketing Automation Solution for WordPress v11.1.1
11.1.1 11.1.0 11.0.5 11.0.4 11.0.3 11.0.2 11.0.1 11.0.0 10.11.1 10.11.0 10.10.2 10.10.1 10.10.0 10.9.1 trunk 10.0.0 10.0.1 10.1.0 10.1.1 10.1.2 10.1.3 10.1.4 10.2.0 10.2.1 10.2.2 All 62 releases
← All changes | back/Helpers/global/file.php +0 -701 11.0.1 → 11.1.1 View file →
@@ -1,701 +1,0 @@
1 -<?php
2 -defined('ABSPATH') || die('Restricted Access');
3 -
4 -use AcyMailing\Helpers\ImageHelper;
5 -
6 -/**
7 - * Function to return the number of bytes of a val like 2M
8 - */
9 -function acym_bytes(string $val): int
10 -{
11 - $val = trim($val);
12 - if (empty($val)) {
13 - return 0;
14 - }
15 - $last = strtolower($val[strlen($val) - 1]);
16 - switch ($last) {
17 - case 'g':
18 - $val = intval($val) * 1073741824;
19 - break;
20 - case 'm':
21 - $val = intval($val) * 1048576;
22 - break;
23 - case 'k':
24 - $val = intval($val) * 1024;
25 - break;
26 - }
27 -
28 - return (int)$val;
29 -}
30 -
31 -//Create a dir and an index.html file inside
32 -function acym_createDir(string $dir, bool $report = true, bool $secured = false): bool
33 -{
34 - if (is_dir($dir)) {
35 - return true;
36 - }
37 -
38 - $indexhtml = '<html><body bgcolor="#FFFFFF"></body></html>';
39 -
40 - //Create the directory with an index file inside
41 - try {
42 - $status = acym_createFolder($dir);
43 - } catch (Exception $e) {
44 - $status = false;
45 - }
46 -
47 - if (!$status) {
48 - if ($report) {
49 - acym_display('Could not create the directory '.$dir, 'error');
50 - }
51 -
52 - return false;
53 - }
54 -
55 - try {
56 - $status = acym_writeFile($dir.DS.'index.html', $indexhtml);
57 - } catch (Exception $e) {
58 - $status = false;
59 - }
60 -
61 - if (!$status && $report) {
62 - acym_display('Could not create the file '.$dir.DS.'index.html', 'error');
63 - }
64 -
65 - if ($secured) {
66 - try {
67 - $htaccess = 'Order deny,allow'."\r\n".'Deny from all';
68 - $status = acym_writeFile($dir.DS.'.htaccess', $htaccess);
69 - } catch (Exception $e) {
70 - $status = false;
71 - }
72 -
73 - if (!$status && $report) {
74 - acym_display('Could not create the file '.$dir.DS.'.htaccess', 'error');
75 - }
76 - }
77 -
78 - return $status;
79 -}
80 -
81 -function acym_importFile(array $file, string $uploadPath, bool $onlyPict): ?string
82 -{
83 - // Check the token... no import without token!
84 - wp_verify_nonce(acym_getVar('cmd', '_wpnonce'), 'acymnonce') || die('Invalid Token');
85 -
86 - $config = acym_config();
87 - $additionalMsg = '';
88 -
89 - if ($file['error'] > 0) {
90 - $file['error'] = intval($file['error']);
91 - if ($file['error'] > 8) {
92 - $file['error'] = 0;
93 - }
94 -
95 - $phpFileUploadErrors = [
96 - 0 => 'Unknown error',
97 - 1 => 'The uploaded file exceeds the upload_max_filesize directive in php.ini',
98 - 2 => 'The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML form',
99 - 3 => 'The uploaded file was only partially uploaded',
100 - 4 => 'No file was uploaded',
101 - 6 => 'Missing a temporary folder',
102 - 7 => 'Failed to write file to disk',
103 - 8 => 'A PHP extension stopped the file upload',
104 - ];
105 -
106 - acym_enqueueMessage(acym_translationSprintf('ACYM_ERROR_UPLOADING_FILE_X', $phpFileUploadErrors[$file['error']]), 'error');
107 -
108 - return null;
109 - }
110 -
111 - acym_createDir($uploadPath, true);
112 -
113 - if (!acym_isWritable($uploadPath)) {
114 - acym_chmod($uploadPath, 0755);
115 - if (!acym_isWritable($uploadPath)) {
116 - acym_display(acym_translationSprintf('ACYM_WRITABLE_FOLDER', $uploadPath), 'error');
117 -
118 - return null;
119 - }
120 - }
121 -
122 - if ($onlyPict) {
123 - $allowedExtensions = ['png', 'jpeg', 'jpg', 'gif', 'ico', 'bmp'];
124 - } else {
125 - $allowedExtensions = explode(',', $config->get('allowed_files'));
126 - }
127 -
128 - // We don't allow to upload anything else than a picture extension
129 - if (!preg_match('#\.('.implode('|', $allowedExtensions).')$#Ui', $file['name'], $extension)) {
130 - $ext = substr($file['name'], strrpos($file['name'], '.') + 1);
131 - acym_display(
132 - acym_translationSprintf(
133 - 'ACYM_ACCEPTED_TYPE',
134 - esc_html($ext),
135 - implode(', ', $allowedExtensions)
136 - ),
137 - 'error'
138 - );
139 -
140 - return null;
141 - }
142 -
143 - // We will never allow some files to be uploaded...
144 - // This should never happen... only if there is an hack tentative so no need to translate this error message
145 - if (preg_match('#\.(php.?|.?htm.?|pl|py|jsp|asp|sh|cgi)#Ui', $file['name'])) {
146 - acym_display(
147 - 'This extension name is blocked by the system regardless your configuration for security reasons',
148 - 'error'
149 - );
150 -
151 - return null;
152 - }
153 -
154 - // We remove all dots or space from the file name to avoid the double extension security issue and the fact some mail clients don't like spaces
155 - $file['name'] = str_replace(
156 - ['-', '.', ' ', '\''],
157 - '_',
158 - substr($file['name'], 0, strrpos($file['name'], '.'))
159 - ).'.'.$extension[1];
160 -
161 - if ($onlyPict) {
162 - // Extra security: we make sure we only have a valid picture format
163 - $imageSize = @getimagesize($file['tmp_name']);
164 - if (empty($imageSize)) {
165 - acym_display(acym_translation('ACYM_INVALID_IMAGE'), 'error');
166 -
167 - return null;
168 - }
169 - }
170 -
171 - if (file_exists($uploadPath.DS.$file['name'])) {
172 - $i = 1;
173 - $nameFile = preg_replace('/\\.[^.\\s]{3,4}$/', '', $file['name']);
174 - $ext = substr($file['name'], strrpos($file['name'], '.') + 1);
175 - while (file_exists($uploadPath.DS.$nameFile.'_'.$i.'.'.$ext)) {
176 - $i++;
177 - }
178 -
179 - $file['name'] = $nameFile.'_'.$i.'.'.$ext;
180 - $additionalMsg = '<br />'.acym_translationSprintf('ACYM_FILE_RENAMED', $file['name']);
181 - if ($onlyPict) {
182 - $additionalMsg .= '<br /><a style="color: blue; cursor: pointer;" onclick="confirmBox(\'rename\', \''.$file['name'].'\', \''.$nameFile.'.'.$ext.'\')">'.acym_translation(
183 - 'ACYM_RENAME_OR_REPLACE'
184 - ).'</a>';
185 - }
186 - }
187 -
188 - if (!acym_uploadFile($file['tmp_name'], rtrim($uploadPath, DS).DS.$file['name'])) {
189 - acym_display(
190 - acym_translationSprintf(
191 - 'ACYM_FAIL_UPLOAD',
192 - '<b><i>'.esc_html($file['tmp_name']).'</i></b>',
193 - '<b><i>'.esc_html(rtrim($uploadPath, DS).DS.$file['name']).'</i></b>'
194 - ),
195 - 'error'
196 - );
197 -
198 - return null;
199 - }
200 -
201 - if ($onlyPict && $imageSize[0] > 1000) {
202 - $imageHelper = new ImageHelper();
203 - if ($imageHelper->available()) {
204 - $imageHelper->maxHeight = 9999;
205 - $imageHelper->maxWidth = 700;
206 - $message = 'ACYM_IMAGE_RESIZED';
207 - $imageHelper->destination = $uploadPath;
208 - $thumb = $imageHelper->generateThumbnail(rtrim($uploadPath, DS).DS.$file['name']);
209 - if (!empty($thumb)) {
210 - acym_moveFile($thumb['file'], $uploadPath.DS.$file['name']);
211 - $additionalMsg .= '<br />'.acym_translation($message);
212 - }
213 - }
214 - }
215 - acym_enqueueMessage(acym_translation('ACYM_SUCCESS_FILE_UPLOAD').$additionalMsg, 'success');
216 -
217 - return $file['name'];
218 -}
219 -
220 -function acym_inputFile(
221 - string $name,
222 - string $value = '',
223 - string $class = '',
224 - array $attributes = [],
225 - string $downloadUrl = ''
226 -): void {
227 - $hasValue = !empty($value);
228 - $noFileText = acym_translation('ACYM_NO_FILE_CHOSEN');
229 - $baseName = substr($name, -2) === '[]' ? substr($name, 0, -2) : $name;
230 - ?>
231 -
232 - <div class="cell <?php echo esc_attr($class); ?> grid-x acym__input__file__container">
233 - <input type="hidden" name="<?php echo esc_attr($baseName); ?>" value="<?php echo esc_attr($value); ?>" class="acym__input__file__clear">
234 - <input <?php
235 - foreach ($attributes as $oneAttribute => $oneValue) {
236 - if (is_array($oneValue) || is_object($oneValue)) {
237 - $oneValue = json_encode($oneValue);
238 - } elseif ($oneValue === true) {
239 - $oneValue = $oneAttribute;
240 - }
241 -
242 - echo ' '.esc_attr($oneAttribute).'="'.esc_attr($oneValue).'"';
243 - }
244 - ?> style="display: none" type="file" name="<?php echo esc_attr($name); ?>">
245 - <button type="button" class="acym__button__file button button-secondary cell shrink">
246 - <?php echo esc_html(acym_translation('ACYM_CHOOSE_FILE')); ?>
247 - </button>
248 - <span class="cell shrink margin-left-2 margin-right-2 acym__input__file__name" data-no-file="<?php echo esc_attr($noFileText); ?>">
249 - <?php echo esc_html($hasValue ? $value : $noFileText); ?>
250 - </span>
251 - <i class="acym__input__file__download cell shrink acym__color__blue cursor-pointer acymicon-download margin-right-1"
252 - <?php echo $hasValue ? '' : ' style="display: none;"'; ?>
253 - <?php echo !empty($downloadUrl) ? ' data-download-url="'.esc_url($downloadUrl).'"' : ''; ?>
254 - title="<?php echo esc_attr(acym_translation('ACYM_DOWNLOAD')); ?>" aria-label="<?php echo esc_attr(acym_translation('ACYM_DOWNLOAD')); ?>"></i>
255 - <i class="acymicon-close acym__color__red acym__input__file__delete cursor-pointer cell shrink margin-left-1"
256 - <?php echo $hasValue ? '' : ' style="display: none;"'; ?>
257 - title="<?php echo esc_attr(acym_translation('ACYM_DELETE')); ?>" aria-label="<?php echo esc_attr(acym_translation('ACYM_DELETE')); ?>"></i>
258 - </div>
259 - <?php
260 -}
261 -
262 -function acym_getFilesFolder(bool $ignoreVariables = false): string
263 -{
264 - $config = acym_config();
265 - $uploadFolder = $config->get('uploadfolder', ACYM_UPLOAD_FOLDER);
266 - if ($ignoreVariables) {
267 - $uploadFolder = str_replace(['{userid}', '{groupname}', '{year}', '{month}', '{day}'], '', $uploadFolder);
268 - }
269 - $uploadFolder = trim($uploadFolder, '/');
270 -
271 - $uploadFolder = str_replace('{userid}', acym_currentUserId(), $uploadFolder);
272 - $uploadFolder = str_replace('{year}', gmdate('Y'), $uploadFolder);
273 - $uploadFolder = str_replace('{month}', gmdate('m'), $uploadFolder);
274 - $uploadFolder = str_replace('{day}', gmdate('d'), $uploadFolder);
275 -
276 - return acym_replaceGroupTags($uploadFolder);
277 -}
278 -
279 -/**
280 - * Find all sub folders...
281 - * Return an array of all folders ordered properly
282 - */
283 -function acym_generateArborescence(array $folders): array
284 -{
285 - //Recursive algorythm to catch subfolders
286 - $folderList = [];
287 - foreach ($folders as $folder) {
288 - $folderPath = acym_cleanPath(ACYM_ROOT.trim(str_replace('/', DS, trim($folder)), DS));
289 - if (!file_exists($folderPath)) {
290 - acym_createDir($folderPath);
291 - }
292 - $subFolders = acym_listFolderTree($folderPath, '', 15);
293 - $folderList[$folder] = [];
294 - foreach ($subFolders as $oneFolder) {
295 - $subFolder = str_replace(ACYM_ROOT, '', $oneFolder['relname']);
296 - $subFolder = str_replace(DS, '/', $subFolder);
297 - $folderList[$folder][$subFolder] = ltrim($subFolder, '/');
298 - }
299 - $folderList[$folder] = array_unique($folderList[$folder]);
300 - }
301 -
302 - return $folderList;
303 -}
304 -
305 -function acym_makeSafeFile(string $file): string
306 -{
307 - $file = rtrim($file, '.');
308 - $regex = ['#(\.){2,}#', '#[^A-Za-z0-9\.\_\- ]#', '#^\.#'];
309 -
310 - return trim(preg_replace($regex, '', $file));
311 -}
312 -
313 -function acym_getFolders(
314 - string $path,
315 - string $filter = '.',
316 - bool $recurse = false,
317 - bool $full = false,
318 - array $exclude = ['.svn', 'CVS', '.DS_Store', '__MACOSX'],
319 - array $excludefilter = ['^\..*']
320 -): array {
321 - $path = acym_cleanPath($path);
322 -
323 - if (!is_dir($path)) {
324 - acym_enqueueMessage(acym_translationSprintf('ACYM_IS_NOT_A_FOLDER', $path), 'error');
325 -
326 - return [];
327 - }
328 -
329 - if (count($excludefilter)) {
330 - $excludefilter_string = '/('.implode('|', $excludefilter).')/';
331 - } else {
332 - $excludefilter_string = '';
333 - }
334 -
335 - $arr = acym_getItems($path, $filter, $recurse, $full, $exclude, $excludefilter_string, false);
336 - asort($arr);
337 -
338 - return array_values($arr);
339 -}
340 -
341 -function acym_getFiles(
342 - string $path,
343 - string $filter = '.',
344 - bool $recurse = false,
345 - bool $full = false,
346 - array $exclude = ['.svn', 'CVS', '.DS_Store', '__MACOSX'],
347 - array $excludefilter = [
348 - '^\..*',
349 - '.*~',
350 - ],
351 - bool $naturalSort = false
352 -): array {
353 - $path = acym_cleanPath($path);
354 -
355 - if (!is_dir($path)) {
356 - acym_enqueueMessage(acym_translationSprintf('ACYM_IS_NOT_A_FOLDER', $path), 'error');
357 -
358 - return [];
359 - }
360 -
361 - if (count($excludefilter)) {
362 - $excludefilter_string = '/('.implode('|', $excludefilter).')/';
363 - } else {
364 - $excludefilter_string = '';
365 - }
366 -
367 - $arr = acym_getItems($path, $filter, $recurse, $full, $exclude, $excludefilter_string, true);
368 -
369 - if ($naturalSort) {
370 - natsort($arr);
371 - } else {
372 - asort($arr);
373 - }
374 -
375 - return array_values($arr);
376 -}
377 -
378 -function acym_getItems(
379 - string $path,
380 - string $filter,
381 - bool $recurse,
382 - bool $full,
383 - array $exclude,
384 - string $excludefilter_string,
385 - bool $findfiles
386 -): array {
387 - $arr = [];
388 -
389 - if (!($handle = @opendir($path))) {
390 - return $arr;
391 - }
392 -
393 - while (($file = readdir($handle)) !== false) {
394 - if (
395 - $file == '.'
396 - || $file == '..'
397 - || in_array($file, $exclude)
398 - || (!empty($excludefilter_string) && preg_match($excludefilter_string, $file))
399 - ) {
400 - continue;
401 - }
402 - $fullpath = rtrim($path, '/').'/'.$file;
403 -
404 - $isDir = is_dir($fullpath);
405 -
406 - if (($isDir xor $findfiles) && preg_match("/$filter/", $file)) {
407 - if ($full) {
408 - $arr[] = $fullpath;
409 - } else {
410 - $arr[] = $file;
411 - }
412 - }
413 -
414 - if ($isDir && $recurse) {
415 - $arr = array_merge(
416 - $arr,
417 - acym_getItems(
418 - $fullpath,
419 - $filter,
420 - true,
421 - $full,
422 - $exclude,
423 - $excludefilter_string,
424 - $findfiles
425 - )
426 - );
427 - }
428 - }
429 -
430 - closedir($handle);
431 -
432 - return $arr;
433 -}
434 -
435 -function acym_copyFolder(string $src, string $dest, ?string $path = null, bool $force = false, bool $use_streams = false): bool
436 -{
437 - if (!empty($path)) {
438 - $src = acym_cleanPath($path.'/'.$src);
439 - $dest = acym_cleanPath($path.'/'.$dest);
440 - }
441 -
442 - $src = rtrim($src, DIRECTORY_SEPARATOR);
443 - $dest = rtrim($dest, DIRECTORY_SEPARATOR);
444 -
445 - if (!file_exists($src)) {
446 - acym_enqueueMessage(acym_translationSprintf('ACYM_FOLDER_DOES_NOT_EXIST', $src), 'error');
447 -
448 - return false;
449 - }
450 -
451 - if (file_exists($dest) && !$force) {
452 - acym_enqueueMessage(acym_translationSprintf('ACYM_FOLDER_ALREADY_EXIST', $dest), 'error');
453 -
454 - return true;
455 - }
456 -
457 - if (!acym_createFolder($dest)) {
458 - acym_enqueueMessage(acym_translation('ACYM_CANNOT_CREATE_DESTINATION_FOLDER'), 'error');
459 -
460 - return false;
461 - }
462 -
463 - if (!($dh = @opendir($src))) {
464 - acym_enqueueMessage(acym_translation('ACYM_CANNOT_OPEN_SOURCE_FOLDER'), 'error');
465 -
466 - return false;
467 - }
468 -
469 - while (($file = readdir($dh)) !== false) {
470 - $sfid = $src.'/'.$file;
471 - $dfid = $dest.'/'.$file;
472 -
473 - switch (filetype($sfid)) {
474 - case 'dir':
475 - if ($file != '.' && $file != '..') {
476 - $ret = acym_copyFolder($sfid, $dfid, null, $force, $use_streams);
477 -
478 - if ($ret !== true) {
479 - return $ret;
480 - }
481 - }
482 - break;
483 -
484 - case 'file':
485 - if (!@copy($sfid, $dfid)) {
486 - acym_enqueueMessage(acym_translationSprintf('ACYM_COPY_FILE_FAILED_PERMISSION', $sfid), 'error');
487 -
488 - return false;
489 - }
490 - break;
491 - }
492 - }
493 -
494 - return true;
495 -}
496 -
497 -function acym_listFolderTree(string $path, string $filter, int $maxLevel = 3, int $level = 0, int $parent = 0): array
498 -{
499 - $dirs = [];
500 -
501 - if ($level === 0) {
502 - $GLOBALS['acym_folder_tree_index'] = 0;
503 - }
504 -
505 - if ($level < $maxLevel) {
506 - $folders = acym_getFolders($path, $filter);
507 -
508 - foreach ($folders as $name) {
509 - $id = ++$GLOBALS['acym_folder_tree_index'];
510 - $fullName = acym_cleanPath($path.'/'.$name);
511 - $dirs[] = [
512 - 'id' => $id,
513 - 'parent' => $parent,
514 - 'name' => $name,
515 - 'fullname' => $fullName,
516 - 'relname' => str_replace(ACYM_ROOT, '', $fullName),
517 - ];
518 - $dirs2 = acym_listFolderTree($fullName, $filter, $maxLevel, $level + 1, $id);
519 - $dirs = array_merge($dirs, $dirs2);
520 - }
521 - }
522 -
523 - return $dirs;
524 -}
525 -
526 -/**
527 - * @param mixed $buffer
528 - */
529 -function acym_writeFile(string $file, $buffer, int $flags = 0): bool
530 -{
531 - if (!file_exists(dirname($file)) && !acym_createFolder(dirname($file))) {
532 - return false;
533 - }
534 -
535 - $file = acym_cleanPath($file);
536 -
537 - return is_int(file_put_contents($file, $buffer, $flags));
538 -}
539 -
540 -function acym_copyFile(string $src, string $dest, string $path = ''): bool
541 -{
542 - if (!empty($path)) {
543 - $src = acym_cleanPath($path.DS.$src);
544 - $dest = acym_cleanPath($path.DS.$dest);
545 - }
546 -
547 - if (!is_readable($src)) {
548 - acym_enqueueMessage(acym_translationSprintf('ACYM_COULD_NOT_FIND_FILE_SOURCE_PERMISSION', $src), 'error');
549 -
550 - return false;
551 - }
552 -
553 - if (!@copy($src, $dest)) {
554 - acym_enqueueMessage(acym_translationSprintf('ACYM_COULD_NOT_COPY_FILE_X_TO_X', $src, $dest), 'error');
555 -
556 - return false;
557 - }
558 -
559 - return true;
560 -}
561 -
562 -function acym_fileGetExt(string $file): string
563 -{
564 - $pathInfo = pathinfo($file);
565 -
566 - return empty($pathInfo['extension']) ? '' : strtolower($pathInfo['extension']);
567 -}
568 -
569 -function acym_cleanPath(string $path, string $ds = DIRECTORY_SEPARATOR): string
570 -{
571 - $path = trim($path);
572 -
573 - if (empty($path)) {
574 - $path = ACYM_ROOT;
575 - } elseif (($ds === '\\') && substr($path, 0, 2) == '\\\\') {
576 - $path = "\\".preg_replace('#[/\\\\]+#', $ds, $path);
577 - } else {
578 - $path = preg_replace('#[/\\\\]+#', $ds, $path);
579 - }
580 -
581 - return $path;
582 -}
583 -
584 -function acym_createArchive(string $name, array $files): bool
585 -{
586 - $contents = [];
587 - $ctrldir = [];
588 -
589 - $timearray = getdate();
590 - $dostime = (($timearray['year'] - 1980) << 25) | ($timearray['mon'] << 21) | ($timearray['mday'] << 16) | ($timearray['hours'] << 11) | ($timearray['minutes'] << 5) | ($timearray['seconds'] >> 1);
591 - $dtime = dechex($dostime);
592 - $hexdtime = chr(hexdec($dtime[6].$dtime[7])).chr(hexdec($dtime[4].$dtime[5])).chr(hexdec($dtime[2].$dtime[3])).chr(
593 - hexdec($dtime[0].$dtime[1])
594 - );
595 -
596 - foreach ($files as $file) {
597 - $data = $file['data'];
598 - $filename = str_replace('\\', '/', $file['name']);
599 -
600 - $fr = "\x50\x4b\x03\x04\x14\x00\x00\x00\x08\x00".$hexdtime;
601 -
602 - $unc_len = strlen($data);
603 - $crc = crc32($data);
604 - $zdata = gzcompress($data);
605 - $zdata = substr(substr($zdata, 0, strlen($zdata) - 4), 2);
606 - $c_len = strlen($zdata);
607 -
608 - $fr .= pack('V', $crc).pack('V', $c_len).pack('V', $unc_len).pack('v', strlen($filename)).pack(
609 - 'v',
610 - 0
611 - ).$filename.$zdata;
612 -
613 - $old_offset = strlen(implode('', $contents));
614 - $contents[] = $fr;
615 -
616 - $cdrec = "\x50\x4b\x01\x02\x00\x00\x14\x00\x00\x00\x08\x00".$hexdtime;
617 - $cdrec .= pack('V', $crc).pack('V', $c_len).pack('V', $unc_len).pack('v', strlen($filename)).pack('v', 0).pack(
618 - 'v',
619 - 0
620 - ).pack('v', 0).pack('v', 0).pack('V', 32).pack('V', $old_offset).$filename;
621 -
622 - $ctrldir[] = $cdrec;
623 - }
624 -
625 - $data = implode('', $contents);
626 - $dir = implode('', $ctrldir);
627 - $buffer = $data.$dir."\x50\x4b\x05\x06\x00\x00\x00\x00".pack('v', count($ctrldir)).pack('v', count($ctrldir)).pack(
628 - 'V',
629 - strlen($dir)
630 - ).pack('V', strlen($data))."\x00\x00";
631 -
632 - return acym_writeFile($name.'.zip', $buffer);
633 -}
634 -
635 -function acym_loaderLogo(bool $withContainer = true): void
636 -{
637 - if ($withContainer) {
638 - echo '<div class="cell shrink acym_loader_logo">';
639 - }
640 - ?>
641 - <svg version="1.1" xmlns="http://www.w3.org/2000/svg" width="80" height="80" viewBox="0 0 1024 1024">
642 - <path class="acym__svg__loader"
643 - fill="#a6a9ab"
644 - d="M553.074 174.168c-12.201 7.319-26.84 10.573-40.668 10.573s-27.655-3.253-40.668-10.573l-242.376-139.081-229.362 132.575v732.011l254.576 143.963v-430.26l219.602 124.442c11.388 6.507 24.401 9.76 37.415 9.76 0 0 0 0 0 0s0 0 0 0c12.201 0 25.214-3.253 36.6-9.76l221.23-124.442v430.26l254.576-144.775v-732.011l-229.362-131.762-241.563 139.081zM491.261 701.215l-217.164-122.815-61.001-34.161v430.26l-173.243-97.601v-662.063l422.94 245.629c0 0 0 0 0 0 8.947 4.881 17.895 8.135 27.655 10.573v230.178zM983.334 876.086l-173.243 98.416v-431.073l-61.001 34.161-217.164 122.815v-229.362c9.76-2.441 18.707-5.694 27.655-10.573l423.753-246.444v662.063zM539.246 425.493c-17.080 9.76-38.227 9.76-55.307 0 0 0 0 0 0 0l-422.94-245.629 168.362-97.601 222.043 127.696c18.707 10.573 39.853 16.267 61.001 16.267s42.294-5.694 61.001-16.267l222.043-127.696 168.362 97.601-424.566 245.629z"></path>
645 - </svg>
646 - <?php
647 - if ($withContainer) {
648 - echo '</div>';
649 - }
650 -}
651 -
652 -function acym_fileNameValid(string $filename): bool
653 -{
654 - if (empty($filename)) return false;
655 -
656 - if (strpos($filename, '..') !== false || strpos($filename, '/') !== false || strpos($filename, '\\') !== false) return false;
657 -
658 - return true;
659 -}
660 -
661 -function acym_getImageFileExtensions(bool $allowSvg = false): array
662 -{
663 - $imageFormats = ['jpg', 'jpeg', 'png', 'gif', 'ico', 'bmp'];
664 - if ($allowSvg) {
665 - $imageFormats[] = 'svg';
666 - }
667 -
668 - return $imageFormats;
669 -}
670 -
671 -function acym_isSvgFileSafe(string $path): bool
672 -{
673 - if (!is_file($path)) {
674 - return false;
675 - }
676 -
677 - $content = @file_get_contents($path);
678 - if ($content === false || trim($content) === '') {
679 - return false;
680 - }
681 -
682 - // Decode HTML entities so obfuscated payloads (e.g. "javascript&#58;") are caught, and drop NULL bytes.
683 - $content = str_replace("\0", '', html_entity_decode($content, ENT_QUOTES | ENT_HTML5));
684 -
685 - $dangerousPatterns = [
686 - '#<\s*script#i',
687 - '#<\s*(foreignObject|iframe|embed|object|audio|video|handler|listener)#i',
688 - '#\son[a-z]+\s*=#i',
689 - '#javascript\s*:#i',
690 - '#data\s*:\s*text/html#i',
691 - '#<!\s*(DOCTYPE|ENTITY)#i',
692 - ];
693 -
694 - foreach ($dangerousPatterns as $pattern) {
695 - if (preg_match($pattern, $content)) {
696 - return false;
697 - }
698 - }
699 -
700 - return true;
701 -}