1C-Bitrix 25.700.0
Загрузка...
Поиск...
Не найдено
storage.php
См. документацию.
1<?php
3
5{
6 const FILE_SKIPPED = 0;
7 const FILE_MOVED = 1;
10
11 public static $part_size = 0;
12 public static $part_count = 0;
13
14 private static $_services = /*.(array[string]CCloudStorageService).*/
15 null;
16
17 public static $file_skip_reason = '';
18
22 public static function _init()
23 {
24 if (!isset(self::$_services))
25 {
26 /* @var CCloudStorageService $obService */
27 $obService = null;
28 self::$_services = /*.(array[string]CCloudStorageService).*/ [];
29 foreach (GetModuleEvents('clouds', 'OnGetStorageService', true) as $arEvent)
30 {
31 $obService = ExecuteModuleEventEx($arEvent);
32 if (is_object($obService))
33 {
34 self::$_services[$obService->GetID()] = $obService;
35 }
36 }
37 }
38 }
39
44 public static function GetServiceByID($ID)
45 {
47 if (array_key_exists($ID, self::$_services))
48 {
49 return self::$_services[$ID];
50 }
51 else
52 {
53 return null;
54 }
55 }
56
60 public static function GetServiceList()
61 {
63 return self::$_services;
64 }
65
70 public static function GetServiceLocationList($ID)
71 {
73 if (is_object($obService))
74 {
75 return $obService->GetLocationList();
76 }
77 else
78 {
79 return /*.(array[string]string).*/
80 [];
81 }
82 }
83
88 public static function GetServiceDescription($ID)
89 {
91 if (is_object($obService))
92 {
93 return $obService->GetName();
94 }
95 else
96 {
97 return '';
98 }
99 }
100
106 public static function FindBucketForFile($arFile, $strFileName)
107 {
108 if (array_key_exists('size', $arFile) && $arFile['size'] > 0)
109 {
110 $file_size = intval($arFile['size']);
111 }
112 elseif (array_key_exists('FILE_SIZE', $arFile) && $arFile['FILE_SIZE'] > 0)
113 {
114 $file_size = intval($arFile['FILE_SIZE']);
115 }
116 else
117 {
118 $file_size = intval($arFile['file_size']);
119 }
120
121 self::$file_skip_reason = '';
122 $activeCounter = 0;
123 $writableCounter = 0;
124 foreach (CCloudStorageBucket::GetAllBuckets() as $bucket)
125 {
126 if ($bucket['ACTIVE'] !== 'Y')
127 {
128 continue;
129 }
130 $activeCounter++;
131
132 if ($bucket['READ_ONLY'] === 'Y')
133 {
134 continue;
135 }
136 $writableCounter++;
137
138 foreach ($bucket['FILE_RULES_COMPILED'] as $rule)
139 {
140 if ($rule['MODULE_MASK'] != '')
141 {
142 $bMatchModule = (preg_match($rule['MODULE_MASK'], $arFile['MODULE_ID']) > 0);
143 }
144 else
145 {
146 $bMatchModule = true;
147 }
148
149 if ($rule['EXTENTION_MASK'] != '')
150 {
151 $bMatchExtention =
152 (preg_match($rule['EXTENTION_MASK'], $strFileName) > 0)
153 || (preg_match($rule['EXTENTION_MASK'], $arFile['ORIGINAL_NAME']) > 0);
154 }
155 else
156 {
157 $bMatchExtention = true;
158 }
159
160 if ($rule['SIZE_ARRAY'])
161 {
162 $bMatchSize = false;
163 foreach ($rule['SIZE_ARRAY'] as $size)
164 {
165 if (
166 ($file_size >= $size[0])
167 && ($size[1] === 0.0 || $file_size <= $size[1])
168 )
169 {
170 $bMatchSize = true;
171 }
172 }
173 }
174 else
175 {
176 $bMatchSize = true;
177 }
178
179 if (!$bMatchModule)
180 {
181 self::$file_skip_reason = 'NO_FILE_MODULE_MATCH';
182 }
183 elseif (!$bMatchExtention)
184 {
185 self::$file_skip_reason = 'NO_FILE_EXTENTION_MATCH';
186 }
187 elseif (!$bMatchSize)
188 {
189 self::$file_skip_reason = 'NO_FILE_SIZE_MATCH';
190 }
191
192 if ($bMatchModule && $bMatchExtention && $bMatchSize)
193 {
194 return new CCloudStorageBucket(intval($bucket['ID']));
195 }
196 }
197 }
198
199 if (!$activeCounter)
200 {
201 self::$file_skip_reason = 'NO_ACTIVE_BUCKETS';
202 }
203 elseif (!$writableCounter)
204 {
205 self::$file_skip_reason = 'NO_WRITABLE_BUCKETS';
206 }
207
208 return null;
209 }
210
211 public static function GetImageSize($path)
212 {
214 $path = $io->GetPhysicalName($path);
215
216 $image = new \Bitrix\Main\File\Image($path);
217
218 if (($info = $image->getInfo(false)) !== null)
219 {
220 return [
221 0 => $info->getWidth(),
222 1 => $info->getHeight(),
223 2 => $info->getFormat(),
224 3 => $info->getAttributes(),
225 'mime' => $info->getMime(),
226 ];
227 }
228
229 return false;
230 }
231
241 public static function OnBeforeResizeImage($arFile, $arResizeParams, &$callbackData, &$bNeedResize, &$sourceImageFile, &$cacheImageFileTmp)
242 {
243 $callbackData = null;
244
245 if (intval($arFile['HANDLER_ID']) <= 0)
246 {
247 return false;
248 }
249
250 $obSourceBucket = new CCloudStorageBucket(intval($arFile['HANDLER_ID']));
251 if (!$obSourceBucket->Init())
252 {
253 return false;
254 }
255
256 $callbackData = /*.(array[string]mixed).*/
257 [];
258 $callbackData['obSourceBucket'] = $obSourceBucket;
259
260 //Assume target bucket same as source
261 $callbackData['obTargetBucket'] = $obTargetBucket = $obSourceBucket;
262
263 //if original file bucket is read only
264 if ($obSourceBucket->READ_ONLY === 'Y') //Try to find bucket with write rights
265 {
266 $bucket = CCloudStorage::FindBucketForFile($arFile, $arFile['FILE_NAME']);
267 if (!is_object($bucket))
268 {
269 return false;
270 }
271 if ($bucket->Init())
272 {
273 $callbackData['obTargetBucket'] = $obTargetBucket = $bucket;
274 }
275 }
276
277 if (!$arFile['SRC'])
278 {
279 $arFile['SRC'] = $obSourceBucket->GetFileSRC($arFile, false);
280 }
281
282 if (defined('BX_MOBILE') && constant('BX_MOBILE') === true)
283 {
284 $bImmediate = true;
285 }
286 else
287 {
288 $bImmediate = $arResizeParams[5];
289 }
290
291 $callbackData['bImmediate'] = $bImmediate;
292 $callbackData['cacheID'] = $arFile['ID'] . '/' . md5(serialize($arResizeParams));
293 $callbackData['cacheOBJ'] = new CPHPCache;
294 $callbackData['fileDIR'] = '/' . 'resize_cache/' . $callbackData['cacheID'] . '/' . $arFile['SUBDIR'];
295 $callbackData['fileNAME'] = $arFile['FILE_NAME'];
296 $callbackData['fileURL'] = $callbackData['fileDIR'] . '/' . $callbackData['fileNAME'];
297
298 $result = true;
299 if ($callbackData['cacheOBJ']->StartDataCache(CACHED_clouds_file_resize, $callbackData['cacheID'], 'clouds'))
300 {
301 $cacheImageFile = $obTargetBucket->GetFileSRC($callbackData['fileURL'], false);
302 $arDestinationSize = [];
303
304 //Check if it is cache file was deleted, but there was a successful resize
305 $delayInfo = $bImmediate ? false : CCloudStorage::ResizeImageFileGet($cacheImageFile);
306 if (is_array($delayInfo) && ($delayInfo['ERROR_CODE'] < 10))
307 {
308 $callbackData['cacheSTARTED'] = true;
309 if ($arFile['FILE_SIZE'] > 1)
310 {
311 $callbackData['fileSize'] = $arFile['FILE_SIZE'];
312 }
313 $bNeedResize = false;
314 $result = true;
315 }
316 //Check if it is cache file was deleted, but not the file in the cloud
317 elseif ($fs = $obTargetBucket->FileExists($callbackData['fileURL']))
318 {
319 //If file was resized before the fact was registered
320 if (COption::GetOptionString('clouds', 'delayed_resize') === 'Y')
321 {
323 $arDestinationSize,
324 $arFile,
325 $cacheImageFile,
326 $arResizeParams,
327 9 //already where
328 );
329 }
330
331 $callbackData['cacheSTARTED'] = true;
332 if ($fs > 1)
333 {
334 $callbackData['fileSize'] = $fs;
335 }
336 $bNeedResize = false;
337 $result = true;
338 }
339 else
340 {
341 $callbackData['tmpFile'] = CFile::GetTempName('', $arFile['FILE_NAME']);
342 $callbackData['tmpFile'] = preg_replace('#[\\\\/]+#', '/', $callbackData['tmpFile']);
343
344 if (
345 !$bImmediate
346 && COption::GetOptionString('clouds', 'delayed_resize') === 'Y'
348 $arDestinationSize,
349 $arFile,
350 $cacheImageFile,
351 $arResizeParams
352 )
353 )
354 {
355 $callbackData['cacheSTARTED'] = false;
356 $bNeedResize = false;
357 $callbackData['cacheOBJ']->AbortDataCache();
358 $callbackData['cacheVARS'] = [
359 'cacheImageFile' => $cacheImageFile,
360 'width' => $arDestinationSize['width'],
361 'height' => $arDestinationSize['height'],
362 'size' => null,
363 ];
364 $result = true;
365 }
366 elseif ($obSourceBucket->DownloadToFile($arFile, $callbackData['tmpFile']))
367 {
368 $callbackData['cacheSTARTED'] = true;
369 $bNeedResize = true;
370 $sourceImageFile = $callbackData['tmpFile'];
371 $cacheImageFileTmp = CFile::GetTempName('', $arFile['FILE_NAME']);
372 $result = true;
373 }
374 else
375 {
376 $callbackData['cacheSTARTED'] = false;
377 $bNeedResize = false;
378 $callbackData['cacheOBJ']->AbortDataCache();
379 $result = false;
380 }
381 }
382 }
383 else
384 {
385 $callbackData['cacheSTARTED'] = false;
386 $callbackData['cacheVARS'] = $callbackData['cacheOBJ']->GetVars();
387 $bNeedResize = false;
388 $result = true;
389 }
390
391 return $result;
392 }
393
394 public static function OnAfterResizeImage($arFile, $arResizeParams, &$callbackData, &$cacheImageFile, &$cacheImageFileTmp, &$arImageSize)
395 {
398
399 if (!is_array($callbackData))
400 {
401 return false;
402 }
403
404 if ($callbackData['cacheSTARTED'])
405 {
407 $obTargetBucket = $callbackData['obTargetBucket'];
409 $cacheOBJ = $callbackData['cacheOBJ'];
410
411 if (isset($callbackData['tmpFile'])) //have to upload to the cloud
412 {
413 $arFileToStore = CFile::MakeFileArray($io->GetPhysicalName($cacheImageFileTmp));
414 if (!$arFileToStore)
415 {
416 $cacheOBJ->AbortDataCache();
417
418 $tmpFile = $io->GetPhysicalName($callbackData['tmpFile']);
419 unlink($tmpFile);
420 @rmdir(mb_substr($tmpFile, 0, -mb_strlen(bx_basename($tmpFile))));
421
422 unlink($cacheImageFileTmp);
423 @rmdir(mb_substr($cacheImageFileTmp, 0, -mb_strlen(bx_basename($cacheImageFileTmp))));
424
425 $obSourceBucket = new CCloudStorageBucket(intval($arFile['HANDLER_ID']));
426 if ($obSourceBucket->Init())
427 {
428 $cacheImageFile = $obSourceBucket->GetFileSRC($arFile, false);
429 }
430
431 return false;
432 }
433
434 if (!preg_match('/^image\\//', $arFileToStore['type']))
435 {
436 $arFileToStore['type'] = $arFile['CONTENT_TYPE'];
437 }
438
439 if ($obTargetBucket->SaveFile($callbackData['fileURL'], $arFileToStore))
440 {
441 $cacheImageFile = $obTargetBucket->GetFileSRC($callbackData['fileURL'], false);
442
443 $arImageSize = static::GetImageSize($cacheImageFileTmp);
444 $arImageSize[2] = filesize($io->GetPhysicalName($cacheImageFileTmp));
445 $iFileSize = filesize($arFileToStore['tmp_name']);
446
447 if (!is_array($arImageSize))
448 {
449 $arImageSize = [0, 0];
450 }
451 $cacheOBJ->EndDataCache([
452 'cacheImageFile' => $cacheImageFile,
453 'width' => $arImageSize[0],
454 'height' => $arImageSize[1],
455 'size' => $arImageSize[2],
456 ]);
457
458 $tmpFile = $io->GetPhysicalName($callbackData['tmpFile']);
459 unlink($tmpFile);
460 @rmdir(mb_substr($tmpFile, 0, -mb_strlen(bx_basename($tmpFile))));
461
462 $arCloudImageSizeCache[$cacheImageFile] = $arImageSize;
463
464 $obTargetBucket->IncFileCounter($iFileSize);
465
466 if (
467 COption::GetOptionString('clouds', 'delayed_resize') === 'Y'
468 && !is_array(CCloudStorage::ResizeImageFileGet($cacheImageFile))
469 )
470 {
471 $arDestinationSize = [];
473 $arDestinationSize,
474 $arFile,
475 $cacheImageFile,
476 $arResizeParams,
477 9 //already there
478 );
479 }
480 }
481 else
482 {
483 $cacheOBJ->AbortDataCache();
484
485 $tmpFile = $io->GetPhysicalName($callbackData['tmpFile']);
486 unlink($tmpFile);
487 @rmdir(mb_substr($tmpFile, 0, -mb_strlen(bx_basename($tmpFile))));
488
489 unlink($cacheImageFileTmp);
490 @rmdir(mb_substr($cacheImageFileTmp, 0, -mb_strlen(bx_basename($cacheImageFileTmp))));
491
492 $obSourceBucket = new CCloudStorageBucket(intval($arFile['HANDLER_ID']));
493 if ($obSourceBucket->Init())
494 {
495 $cacheImageFile = $obSourceBucket->GetFileSRC($arFile, false);
496 }
497
498 return false;
499 }
500 }
501 else //the file is already in the cloud
502 {
503 $source = new \Bitrix\Main\File\Image\Rectangle($arFile['WIDTH'], $arFile['HEIGHT']);
504 $destination = new \Bitrix\Main\File\Image\Rectangle($arResizeParams[0]['width'], $arResizeParams[0]['height']);
505 $source->resize($destination, $arResizeParams[1]);
506 $cacheImageFile = $obTargetBucket->GetFileSRC($callbackData['fileURL'], false);
507 $arImageSize = [
508 $destination->getWidth(),
509 $destination->getHeight(),
510 $callbackData['fileSize'] ?? $obTargetBucket->GetFileSize($callbackData['fileURL']),
511 ];
512 $cacheOBJ->EndDataCache([
513 'cacheImageFile' => $cacheImageFile,
514 'width' => $arImageSize[0],
515 'height' => $arImageSize[1],
516 'size' => $arImageSize[2],
517 ]);
518
519 $arCloudImageSizeCache[$cacheImageFile] = $arImageSize;
520 }
521 }
522 elseif (is_array($callbackData['cacheVARS']))
523 {
524 $cacheImageFile = $callbackData['cacheVARS']['cacheImageFile'];
525 $arImageSize = [
526 $callbackData['cacheVARS']['width'],
527 $callbackData['cacheVARS']['height'],
528 $callbackData['cacheVARS']['size'],
529 ];
530 $arCloudImageSizeCache[$cacheImageFile] = $arImageSize;
531 }
532 else
533 {
534 return false;
535 }
536
537 $delayedResize = $callbackData['bImmediate'] ? false : COption::GetOptionString('clouds', 'delayed_resize') === 'Y';
538 foreach (GetModuleEvents('clouds', 'OnAfterResizeImage', true) as $arEvent)
539 {
540 $cacheImageFileBefore = $cacheImageFile;
541 ExecuteModuleEventEx($arEvent, [$delayedResize, &$cacheImageFile]);
542 if ($cacheImageFile !== $cacheImageFileBefore && $cacheImageFile)
543 {
544 $arCloudImageSizeCache[$cacheImageFile] = $arCloudImageSizeCache[$cacheImageFileBefore];
545 }
546 }
547
548 return true;
549 }
550
551 public static function ResizeImageFileGet($destinationFile)
552 {
553 global $DB;
554 $destinationFile = preg_replace('/^https?:/i', '', $destinationFile);
555 $destinationFile = CCloudUtil::URLEncode($destinationFile, 'UTF-8', true);
556 $q = $DB->Query('
557 select
558 ID
559 ,ERROR_CODE
560 ,FILE_ID
561 ,' . $DB->DateToCharFunction('TIMESTAMP_X', 'FULL') . " TIMESTAMP_X
562 from b_clouds_file_resize
563 where TO_PATH = '" . $DB->ForSql($destinationFile) . "'
564 ");
565 $a = $q->Fetch();
566 return $a;
567 }
568
569 public static function ResizeImageFileAdd(&$arDestinationSize, $sourceFile, $destinationFile, $arResizeParams, $errorCode = 0)
570 {
571 global $DB;
572 $destinationFile = preg_replace('/^https?:/i', '', $destinationFile);
573 $destinationFile = CCloudUtil::URLEncode($destinationFile, 'UTF-8', true);
574 $q = $DB->Query('
575 select
576 ID
577 ,ERROR_CODE
578 ,PARAMS
579 ,' . $DB->DateToCharFunction('TIMESTAMP_X', 'FULL') . " TIMESTAMP_X
580 from b_clouds_file_resize
581 where TO_PATH = '" . $DB->ForSql($destinationFile) . "'
582 ");
583
584 $a = $q->Fetch();
585 if ($a && $a['ERROR_CODE'] >= 10 && $a['ERROR_CODE'] < 20)
586 {
587 $DB->Query('DELETE from b_clouds_file_resize WHERE ID = ' . $a['ID']);
588 $a = false;
589 }
590
591 if (!$a)
592 {
593 $arResizeParams['type'] = $sourceFile['CONTENT_TYPE'];
594 $DB->Add('b_clouds_file_resize', [
595 '~TIMESTAMP_X' => $DB->CurrentTimeFunction(),
596 'ERROR_CODE' => intval($errorCode),
597 'PARAMS' => serialize($arResizeParams),
598 'FROM_PATH' => CCloudUtil::URLEncode($sourceFile['SRC'], 'UTF-8', true),
599 'TO_PATH' => $destinationFile,
600 'FILE_ID' => $sourceFile['ID'],
601 ]);
602 }
603 }
604
605 public static function ResizeImageFileDelay(&$arDestinationSize, $sourceFile, $destinationFile, $arResizeParams)
606 {
607 global $DB;
608 $destinationFile = preg_replace('/^https?:/i', '', $destinationFile);
609 $destinationFile = CCloudUtil::URLEncode($destinationFile, 'UTF-8', true);
610 $q = $DB->Query('
611 select
612 ID
613 ,ERROR_CODE
614 ,PARAMS
615 ,' . $DB->DateToCharFunction('TIMESTAMP_X', 'FULL') . " TIMESTAMP_X
616 from b_clouds_file_resize
617 where TO_PATH = '" . $DB->ForSql($destinationFile) . "'
618 ");
619 if ($resize = $q->Fetch())
620 {
621 if ($resize['ERROR_CODE'] < 10)
622 {
623 $arResizeParams = unserialize($resize['PARAMS'], ['allowed_classes' => false]);
624 $id = $resize['ID'];
625 }
626//Give it a try
627 elseif (
628 $resize['ERROR_CODE'] >= 10
629 && $resize['ERROR_CODE'] < 20
630 && (MakeTimeStamp($resize['TIMESTAMP_X']) + 300/*5min*/) < (time() + CTimeZone::GetOffset())
631 )
632 {
633 $DB->Query('
634 UPDATE b_clouds_file_resize
635 SET ERROR_CODE = 1
636 WHERE ID=' . $resize['ID'] . '
637 ');
638 $arResizeParams = unserialize($resize['PARAMS'], ['allowed_classes' => false]);
639 $id = $resize['ID'];
640 }
641 else
642 {
643 return false;
644 }
645 }
646 else
647 {
648 $id = 0;
649 }
650
651 $arSize = $arResizeParams[0];
652 $resizeType = $arResizeParams[1];
653 $arWaterMark = $arResizeParams[2];
654 // $jpgQuality = $arResizeParams[3];
655 $arFilters = $arResizeParams[4];
656
657 $source = new \Bitrix\Main\File\Image\Rectangle($sourceFile['WIDTH'], $sourceFile['HEIGHT']);
658 $destination = new \Bitrix\Main\File\Image\Rectangle($arSize['width'], $arSize['height']);
659 $bNeedCreatePicture = $source->resize($destination, $resizeType);
660 $bNeedCreatePicture |= is_array($arWaterMark) && !empty($arWaterMark);
661 $bNeedCreatePicture |= is_array($arFilters) && !empty($arFilters);
662
663 if ($bNeedCreatePicture)
664 {
665 if ($id <= 0)
666 {
667 $arResizeParams['type'] = $sourceFile['CONTENT_TYPE'];
668 $id = $DB->Add('b_clouds_file_resize', [
669 '~TIMESTAMP_X' => $DB->CurrentTimeFunction(),
670 'ERROR_CODE' => 2,
671 'PARAMS' => serialize($arResizeParams),
672 'FROM_PATH' => CCloudUtil::URLEncode($sourceFile['SRC'], 'UTF-8', true),
673 'TO_PATH' => $destinationFile,
674 'FILE_ID' => $sourceFile['ID'],
675 ]);
676 }
677
678 return $id > 0;
679 }
680 else
681 {
682 return false;
683 }
684 }
685
691 public static function ResizeImageFileCheck($obBucket, $path)
692 {
693 global $DB;
695
696 $path = preg_replace('/^https?:/i', '', $path);
697 $path = CCloudUtil::URLEncode($path, 'UTF-8', true);
698 $q = $DB->Query('
699 select
700 ID
701 ,ERROR_CODE
702 ,TO_PATH
703 ,FROM_PATH
704 ,PARAMS
705 ,' . $DB->DateToCharFunction('TIMESTAMP_X', 'FULL') . " TIMESTAMP_X
706 from b_clouds_file_resize
707 where TO_PATH = '" . $DB->ForSql($path) . "'
708 ");
709 $task = $q->Fetch();
710 if (!$task)
711 {
712 return false;
713 }
714
715 //File in the Sky with Diamonds
716 if ($task['ERROR_CODE'] == 9)
717 {
718 return true;
719 }
720
721 //Fatal error
722 if ($task['ERROR_CODE'] >= 20)
723 {
724 return false;
725 }
726
727 //Recoverable error
728 if ($task['ERROR_CODE'] >= 10 && $task['ERROR_CODE'] < 20)
729 {
730 if ((MakeTimeStamp($task['TIMESTAMP_X']) + 300/*5min*/) > (time() + CTimeZone::GetOffset()))
731 {
732 return false;
733 }
734 }
735
736 $DB->Query('
737 UPDATE b_clouds_file_resize
738 SET ERROR_CODE = 11
739 WHERE ID = ' . $task['ID'] . '
740 ');
741
742 $tmpFile = CFile::MakeFileArray($task['FROM_PATH']);
743 // if (!is_array($tmpFile) || !file_exists($tmpFile["tmp_name"]))
744 // {
745 // $tmpFile = CFile::MakeFileArray(\Bitrix\Main\Web\Uri::urnEncode($task["FROM_PATH"], "UTF-8"));
746 // }
747
748 if (!is_array($tmpFile) || !file_exists($tmpFile['tmp_name']))
749 {
750 $DB->Query('
751 UPDATE b_clouds_file_resize
752 SET ERROR_CODE = 22
753 WHERE ID = ' . $task['ID'] . '
754 ');
755 return false;
756 }
757
758 $arResizeParams = unserialize($task['PARAMS'], ['allowed_classes' => false]);
759 if (!is_array($arResizeParams))
760 {
761 $DB->Query('
762 UPDATE b_clouds_file_resize
763 SET ERROR_CODE = 23
764 WHERE ID = ' . $task['ID'] . '
765 ');
766 return false;
767 }
768
769 $DB->Query('
770 UPDATE b_clouds_file_resize
771 SET ERROR_CODE = 14
772 WHERE ID = ' . $task['ID'] . '
773 ');
774
775 $arSize = $arResizeParams[0];
776 $resizeType = $arResizeParams[1];
777 $arWaterMark = $arResizeParams[2];
778 $jpgQuality = $arResizeParams[3];
779 $arFilters = $arResizeParams[4];
780
781 $from_path = $io->GetLogicalName($tmpFile['tmp_name']);
782 $to_path = rawurldecode($task['TO_PATH']);
783 $to_path = CFile::GetTempName('', bx_basename($to_path));
784
785 if (!CFile::ResizeImageFile($from_path, $to_path, $arSize, $resizeType, $arWaterMark, $jpgQuality, $arFilters))
786 {
787 $DB->Query('
788 UPDATE b_clouds_file_resize
789 SET ERROR_CODE = 25
790 WHERE ID = ' . $task['ID'] . '
791 ');
792 return false;
793 }
794
795 $DB->Query('
796 UPDATE b_clouds_file_resize
797 SET ERROR_CODE = 16
798 WHERE ID = ' . $task['ID'] . '
799 ');
800
801 $fileToStore = CFile::MakeFileArray($io->GetPhysicalName($to_path));
802 if ($arResizeParams['type'] && !preg_match('/^image\\//', $fileToStore['type']))
803 {
804 $fileToStore['type'] = $arResizeParams['type'];
805 }
806
807 $baseURL = preg_replace('/^https?:/i', '', $obBucket->GetFileSRC('/'));
808 $pathToStore = mb_substr($task['TO_PATH'], mb_strlen($baseURL) - 1);
809 $pathToStore = rawurldecode($pathToStore);
810 if (!$obBucket->SaveFile($pathToStore, $fileToStore))
811 {
812 $DB->Query('
813 UPDATE b_clouds_file_resize
814 SET ERROR_CODE = 27
815 WHERE ID = ' . $task['ID'] . '
816 ');
817 return false;
818 }
819 $obBucket->IncFileCounter($fileToStore['size']);
820 $DB->Query('
821 UPDATE b_clouds_file_resize
822 SET ERROR_CODE = 9
823 WHERE ID = ' . $task['ID']
824 );
825
826 return true;
827 }
828
829 public static function OnMakeFileArray($arSourceFile, &$arDestination)
830 {
831 if (!is_array($arSourceFile))
832 {
833 $file = $arSourceFile;
834 if (mb_substr($file, 0, mb_strlen($_SERVER['DOCUMENT_ROOT'])) == $_SERVER['DOCUMENT_ROOT'])
835 {
836 $file = ltrim(mb_substr($file, mb_strlen($_SERVER['DOCUMENT_ROOT'])), '/');
837 }
838
839 if (!preg_match('#^https?://#', $file))
840 {
841 return false;
842 }
843
844 $bucket = CCloudStorage::FindBucketByFile($file);
845 if (!is_object($bucket))
846 {
847 return false;
848 }
849
850 $filePath = mb_substr($file, mb_strlen($bucket->GetFileSRC('/')) - 1);
851 $filePath = rawurldecode($filePath);
852
854 $target = CFile::GetTempName('', bx_basename($filePath));
855 $target = preg_replace('#[\\\\/]+#', '/', $target);
856
857 if ($bucket->DownloadToFile($filePath, $target))
858 {
859 $arDestination = $io->GetPhysicalName($target);
860 }
861
862 return true;
863 }
864 else
865 {
866 if ($arSourceFile['HANDLER_ID'] <= 0)
867 {
868 return false;
869 }
870
871 $bucket = new CCloudStorageBucket($arSourceFile['HANDLER_ID']);
872 if (!$bucket->Init())
873 {
874 return false;
875 }
876
877 $target = CFile::GetTempName('', $arSourceFile['FILE_NAME']);
878 $target = preg_replace('#[\\\\/]+#', '/', $target);
879
880 if ($bucket->DownloadToFile($arSourceFile, $target))
881 {
882 $arDestination['name'] = ($arSourceFile['ORIGINAL_NAME'] <> '' ? $arSourceFile['ORIGINAL_NAME'] : $arSourceFile['FILE_NAME']);
883 $arDestination['size'] = $arSourceFile['FILE_SIZE'];
884 $arDestination['type'] = $arSourceFile['CONTENT_TYPE'];
885 $arDestination['description'] = $arSourceFile['DESCRIPTION'];
886 $arDestination['tmp_name'] = $target;
887 }
888
889 return true;
890 }
891 }
892
893 public static function OnFileDelete($arFile)
894 {
895 global $DB;
896
897 if ($arFile['HANDLER_ID'] <= 0)
898 {
899 return false;
900 }
901
902 $bucket = new CCloudStorageBucket($arFile['HANDLER_ID']);
903 if ((!$bucket->Init()) || ($bucket->READ_ONLY === 'Y'))
904 {
905 return false;
906 }
907
908 $result = $bucket->DeleteFile('/' . $arFile['SUBDIR'] . '/' . $arFile['FILE_NAME']);
909 if ($result)
910 {
911 $bucket->DecFileCounter($arFile['FILE_SIZE']);
912 }
913
914 $path = '/resize_cache/' . $arFile['ID'] . '/';
915 $arCloudFiles = $bucket->ListFiles($path, true);
916 if (is_array($arCloudFiles['file']))
917 {
918 $delete_size = 0;
919 foreach ($arCloudFiles['file'] as $i => $file_name)
920 {
921 $tmp = $bucket->DeleteFile($path . $file_name);
922 if ($tmp)
923 {
924 $bucket->DecFileCounter($arCloudFiles['file_size'][$i]);
925 $delete_size += $arCloudFiles['file_size'][$i];
926 }
927 }
928 /****************************** QUOTA ******************************/
929 if ($delete_size > 0 && COption::GetOptionInt('main', 'disk_space') > 0)
930 {
931 CDiskQuota::updateDiskQuota('file', $delete_size, 'delete');
932 }
933 /****************************** QUOTA ******************************/
934 }
935
936 $DB->Query('
937 DELETE FROM b_clouds_file_resize
938 WHERE FILE_ID = ' . intval($arFile['ID']) . '
939 ', true);
940
941 \Bitrix\Clouds\FileHashTable::deleteByFilePath($bucket->ID, '/' . $arFile['SUBDIR'] . '/' . $arFile['FILE_NAME']);
942
943 return $result;
944 }
945
946 public static function DeleteDirFilesEx($path)
947 {
948 $path = rtrim($path, '/') . '/';
949 foreach (CCloudStorageBucket::GetAllBuckets() as $bucket)
950 {
951 $obBucket = new CCloudStorageBucket($bucket['ID']);
952 if (
953 $obBucket->Init()
954 && ($obBucket->READ_ONLY === 'N')
955 && ($obBucket->ACTIVE === 'Y')
956 )
957 {
958 $arCloudFiles = $obBucket->ListFiles($path, true);
959 if (is_array($arCloudFiles['file']))
960 {
961 foreach ($arCloudFiles['file'] as $i => $file_name)
962 {
963 $tmp = $obBucket->DeleteFile($path . $file_name);
964 if ($tmp)
965 {
966 $obBucket->DecFileCounter($arCloudFiles['file_size'][$i]);
967 }
968 }
969 }
970 }
971 }
972 }
973
974 public static function OnFileCopy(&$arFile, $newPath = '')
975 {
976 if ($arFile['HANDLER_ID'] <= 0)
977 {
978 return false;
979 }
980
981 $bucket = new CCloudStorageBucket($arFile['HANDLER_ID']);
982 if (!$bucket->Init())
983 {
984 return false;
985 }
986
987 if ($bucket->READ_ONLY === 'Y')
988 {
989 return false;
990 }
991
992 $filePath = '';
993 $newName = '';
994
995 if ($newPath !== '')
996 {
997 $filePath = '/' . trim(str_replace('//', '/', $newPath), '/');
998 }
999 else
1000 {
1001 $strFileExt = strrchr($arFile['FILE_NAME'], '.');
1002 while (true)
1003 {
1004 $newName = md5(uniqid(mt_rand(), true)) . $strFileExt;
1005 $filePath = '/' . $arFile['SUBDIR'] . '/' . $newName;
1006 if (!$bucket->FileExists($filePath))
1007 {
1008 break;
1009 }
1010 }
1011 }
1012
1013 if ($newPath === '')
1014 {
1015 if ($arFile['EXTERNAL_ID'] == '')
1016 {
1017 $arFile['EXTERNAL_ID'] = md5(mt_rand());
1018 }
1019
1021 $bucket->ID
1022 ,$arFile['SUBDIR']
1023 ,$newName
1024 ,$arFile['EXTERNAL_ID']
1025 );
1026 }
1027
1028 $result = $bucket->FileCopy($arFile, $filePath);
1029
1030 if ($result)
1031 {
1032 $copySize = $arFile['FILE_SIZE'];
1033 $bucket->IncFileCounter($copySize);
1035 $bucket->ID
1036 ,$arFile['SUBDIR']
1037 ,$newName
1038 ,$copySize
1039 );
1040
1041 if ($newPath !== '')
1042 {
1043 $arFile['FILE_NAME'] = bx_basename($filePath);
1044 $arFile['SUBDIR'] = mb_substr($filePath, 1, -(mb_strlen(bx_basename($filePath)) + 1));
1045 }
1046 else
1047 {
1048 $arFile['FILE_NAME'] = $newName;
1049 }
1050 }
1051
1052 return $result;
1053 }
1054
1055 public static function OnGetFileSRC($arFile)
1056 {
1057 if ($arFile['HANDLER_ID'] <= 0)
1058 {
1059 return false;
1060 }
1061
1062 $bucket = new CCloudStorageBucket($arFile['HANDLER_ID']);
1063 if ($bucket->Init())
1064 {
1065 return $bucket->GetFileSRC($arFile, false);
1066 }
1067
1068 return false;
1069 }
1070
1071 protected static function _delete_file($file)
1072 {
1073 if (is_array($file))
1074 {
1076 }
1077 elseif (is_string($file) && file_exists($file))
1078 {
1079 unlink($file);
1080 @rmdir(mb_substr($file, 0, -mb_strlen(bx_basename($file))));
1081 }
1082 }
1083
1084 public static function MoveFile($arFile, $obTargetBucket)
1085 {
1087 self::$file_skip_reason = '';
1088
1089 //Try to find suitable bucket for the file
1090 $bucket = CCloudStorage::FindBucketForFile($arFile, $arFile['FILE_NAME']);
1091 if (!is_object($bucket))
1092 {
1094 }
1095
1096 if (!$bucket->Init())
1097 {
1098 self::$file_skip_reason = 'FAILED_TO_INIT_BUCKET';
1100 }
1101
1102 //Check if this is same bucket as the target
1103 if ($bucket->ID != $obTargetBucket->ID)
1104 {
1105 self::$file_skip_reason = 'FOUND_BUCKET_DOES_NOT_MATCH_TARGET';
1107 }
1108
1109 $filePath = '/' . $arFile['SUBDIR'] . '/' . $arFile['FILE_NAME'];
1110 $filePath = preg_replace('#[\\\\/]+#', '/', $filePath);
1111
1112 if ($bucket->FileExists($filePath))
1113 {
1114 self::$file_skip_reason = 'CLOUD_FILE_EXISTS';
1116 }
1117
1118 if ($arFile['FILE_SIZE'] > $bucket->getService()->GetMinUploadPartSize())
1119 {
1120 $obUpload = new CCloudStorageUpload($filePath);
1121 if (!$obUpload->isStarted())
1122 {
1123 if ($arFile['HANDLER_ID'])
1124 {
1125 $ar = [];
1126 if (!CCloudStorage::OnMakeFileArray($arFile, $ar))
1127 {
1128 self::$file_skip_reason = 'FAILED_TO_DOWNLOAD_FILE_1';
1130 }
1131
1132 if (!isset($ar['tmp_name']))
1133 {
1134 self::$file_skip_reason = 'FAILED_TO_DOWNLOAD_FILE_2';
1136 }
1137 }
1138 else
1139 {
1140 $ar = CFile::MakeFileArray($arFile['ID']);
1141 if (!isset($ar['tmp_name']))
1142 {
1143 self::$file_skip_reason = 'FAILED_TO_GET_SOURCE_FILE_INFO_1';
1145 }
1146 }
1147
1148 $temp_file = CTempFile::GetDirectoryName(2, 'clouds') . bx_basename($arFile['FILE_NAME']);
1149 $temp_fileX = $io->GetPhysicalName($temp_file);
1150 CheckDirPath($temp_fileX);
1151
1152 if (file_exists($ar['tmp_name']))
1153 {
1154 $sourceFile = $ar['tmp_name'];
1155 }
1156 elseif (file_exists($io->GetPhysicalName($ar['tmp_name'])))
1157 {
1158 $sourceFile = $io->GetPhysicalName($ar['tmp_name']);
1159 }
1160 else
1161 {
1162 self::$file_skip_reason = 'FAILED_TO_FIND_SOURCE_FILE';
1164 }
1165
1166 if (!copy($sourceFile, $temp_fileX))
1167 {
1168 self::$file_skip_reason = 'FAILED_TO_COPY_SOURCE_FILE';
1170 }
1171
1172 if ($obUpload->Start($bucket->ID, $arFile['FILE_SIZE'], $arFile['CONTENT_TYPE'], $temp_file))
1173 {
1175 }
1176 else
1177 {
1178 self::$file_skip_reason = 'FAILED_TO_START_UPLOAD';
1180 }
1181 }
1182 else
1183 {
1184 $temp_file = $obUpload->getTempFileName();
1185 $temp_fileX = $io->GetPhysicalName($temp_file);
1186
1187 $fp = fopen($temp_fileX, 'rb');
1188 if (!is_resource($fp))
1189 {
1190 self::$file_skip_reason = 'FAILED_TO_READ_SOURCE_FILE';
1192 }
1193
1194 $pos = $obUpload->GetPos();
1195 if ($pos >= filesize($temp_fileX))
1196 {
1197 if ($obUpload->Finish())
1198 {
1199 $bucket->IncFileCounter(filesize($temp_fileX));
1200
1201 if ($arFile['HANDLER_ID'])
1202 {
1203 self::_delete_file($arFile);
1204 }
1205 else
1206 {
1207 $ar = CFile::MakeFileArray($arFile['ID']);
1208 $fileNameX = $io->GetPhysicalName($ar['tmp_name']);
1209 self::_delete_file($fileNameX);
1210 }
1211
1213 }
1214 else
1215 {
1216 self::$file_skip_reason = 'FAILED_TO_FINISH_UPLOAD';
1218 }
1219 }
1220
1221 fseek($fp, $pos);
1222 self::$part_count = $obUpload->GetPartCount();
1223 self::$part_size = $obUpload->getPartSize();
1224 $part = fread($fp, self::$part_size);
1225 while ($obUpload->hasRetries())
1226 {
1227 if ($obUpload->Next($part))
1228 {
1230 }
1231 }
1232
1233 self::$file_skip_reason = 'FAILED_TO_UPLOAD_FILE_CHUNK';
1235 }
1236 }
1237 else
1238 {
1239 if ($arFile['HANDLER_ID'])
1240 {
1241 $ar = [];
1242 if (!CCloudStorage::OnMakeFileArray($arFile, $ar))
1243 {
1244 self::$file_skip_reason = 'FAILED_TO_DOWNLOAD_FILE_3';
1246 }
1247
1248 if (!isset($ar['tmp_name']))
1249 {
1250 self::$file_skip_reason = 'FAILED_TO_DOWNLOAD_FILE_4';
1252 }
1253 }
1254 else
1255 {
1256 $ar = CFile::MakeFileArray($arFile['ID']);
1257 if (!isset($ar['tmp_name']))
1258 {
1259 self::$file_skip_reason = 'FAILED_TO_GET_SOURCE_FILE_INFO_2';
1261 }
1262 }
1263
1264 $res = $bucket->SaveFile($filePath, $ar);
1265 if ($res)
1266 {
1267 $bucket->IncFileCounter(filesize($ar['tmp_name']));
1268
1269 if ($arFile['HANDLER_ID'])
1270 {
1271 self::_delete_file($arFile);
1272 }
1273 else
1274 {
1275 self::_delete_file($ar['tmp_name']);
1276 }
1277
1278 self::$file_skip_reason = 'FAILED_TO_UPLOAD_FILE';
1280 }
1281 else
1282 {
1283 //delete temporary copy
1284 if ($arFile['HANDLER_ID'])
1285 {
1286 self::_delete_file($ar['tmp_name']);
1287 }
1288
1290 }
1291 }
1292 }
1293
1294 public static function OnFileSave(&$arFile, $strFileName, $strSavePath, $bForceMD5 = false, $bSkipExt = false, $dirAdd = '')
1295 {
1296 if (!$arFile['tmp_name'] && !array_key_exists('content', $arFile))
1297 {
1298 return false;
1299 }
1300
1301 if (array_key_exists('bucket', $arFile))
1302 {
1303 $bucket = $arFile['bucket'];
1304 }
1305 else
1306 {
1307 $bucket = CCloudStorage::FindBucketForFile($arFile, $strFileName);
1308 }
1309
1310 if (!is_object($bucket))
1311 {
1312 return false;
1313 }
1314
1315 if (!$bucket->Init())
1316 {
1317 return false;
1318 }
1319
1320 $original = null;
1321 $copySize = false;
1322 $subDir = '';
1323 $filePath = '';
1324
1325 if (array_key_exists('bucket', $arFile))
1326 {
1327 $newName = bx_basename($arFile['tmp_name']);
1328
1329 $prefix = $bucket->GetFileSRC('/');
1330 $subDir = mb_substr($arFile['tmp_name'], mb_strlen($prefix));
1331 $subDir = mb_substr($subDir, 0, -mb_strlen($newName) - 1);
1332 }
1333 else
1334 {
1335 if (array_key_exists('content', $arFile))
1336 {
1337 $arFile['tmp_name'] = CTempFile::GetFileName(bx_basename($arFile['name']));
1338 CheckDirPath($arFile['tmp_name']);
1339 $fp = fopen($arFile['tmp_name'], 'ab');
1340 if ($fp)
1341 {
1342 fwrite($fp, $arFile['content']);
1343 fclose($fp);
1344 }
1345 }
1346
1347 if (
1348 !$bForceMD5
1349 && COption::GetOptionString('main', 'save_original_file_name', 'N') == 'Y'
1350 )
1351 {
1352 if (COption::GetOptionString('main', 'convert_original_file_name', 'Y') == 'Y')
1353 {
1354 $newName = CCloudStorage::translit($strFileName);
1355 }
1356 else
1357 {
1358 $newName = $strFileName;
1359 }
1360 }
1361 else
1362 {
1363 $strFileExt = ($bSkipExt ? '' : strrchr($strFileName, '.'));
1364 $newName = md5(uniqid(mt_rand(), true)) . $strFileExt;
1365 }
1366
1367 //check for double extension vulnerability
1368 $newName = RemoveScriptExtension($newName);
1369 $dir_add = $dirAdd;
1370
1371 if (empty($dir_add))
1372 {
1373 while (true)
1374 {
1375 $dir_add = md5(mt_rand());
1376 $dir_add = mb_substr($dir_add, 0, 3) . '/' . $dir_add;
1377
1378 $subDir = trim(trim($strSavePath, '/') . '/' . $dir_add, '/');
1379 $filePath = '/' . $subDir . '/' . $newName;
1380
1381 if (!$bucket->FileExists($filePath))
1382 {
1383 break;
1384 }
1385 }
1386 }
1387 else
1388 {
1389 $subDir = trim(trim($strSavePath, '/') . '/' . $dir_add, '/');
1390 $filePath = '/' . $subDir . '/' . $newName;
1391 }
1392
1393 if (!isset($arFile['external_id']))
1394 {
1395 $arFile['external_id'] = md5(mt_rand());
1396 }
1397
1399 $bucket->ID
1400 ,$subDir
1401 ,$newName
1402 ,$arFile['external_id']
1403 );
1404
1405 $targetPath = $bucket->GetFileSRC('/');
1406 if (mb_strpos($arFile['tmp_name'], $targetPath) === 0)
1407 {
1408 $arDbFile = [
1409 'SUBDIR' => '',
1410 'FILE_NAME' => mb_substr($arFile['tmp_name'], mb_strlen($targetPath)),
1411 'CONTENT_TYPE' => $arFile['type'],
1412 ];
1413
1414 //get the file hash
1415 $arFile['FILE_HASH'] = '';
1416 if (COption::GetOptionString('main', 'control_file_duplicates', 'N') === 'Y')
1417 {
1418 $info = $bucket->GetFileInfo('/' . $arDbFile['FILE_NAME']);
1419 if ($info)
1420 {
1421 $arFile['FILE_HASH'] = $info['hash'];
1422 $copySize = $info['size'];
1423 }
1424 }
1425
1426 //control of duplicates
1427 if ($arFile['FILE_HASH'] <> '')
1428 {
1429 $original = CFile::FindDuplicate($copySize, $arFile['FILE_HASH'], $bucket->ID);
1430 if ($original !== null)
1431 {
1432 $arFile['original_file'] = $original;
1433 }
1434 }
1435
1436 //copy only if the file is not a duplicate
1437 if ($original === null)
1438 {
1439 $copyPath = $bucket->FileCopy($arDbFile, $filePath);
1440 if (!$copyPath)
1441 {
1442 return false;
1443 }
1444
1445 if ($copySize === false)
1446 {
1447 $info = $bucket->GetFileInfo('/' . urldecode(mb_substr($copyPath, mb_strlen($targetPath))));
1448 if ($info)
1449 {
1450 $copySize = $info['size'];
1451 }
1452 else
1453 {
1454 return false;
1455 }
1456 }
1457 }
1458 }
1459 else
1460 {
1461 if (!$bucket->SaveFile($filePath, $arFile))
1462 {
1463 return false;
1464 }
1465
1466 //get the file hash
1467 $arFile['FILE_HASH'] = '';
1468 $size = 0;
1469 if (COption::GetOptionString('main', 'control_file_duplicates', 'N') === 'Y')
1470 {
1471 $info = $bucket->GetFileInfo($filePath);
1472 if ($info)
1473 {
1474 $arFile['FILE_HASH'] = $info['hash'];
1475 $size = $info['size'];
1476 }
1477 }
1478
1479 //control of duplicates
1480 if ($arFile['FILE_HASH'] <> '')
1481 {
1482 $original = CFile::FindDuplicate($size, $arFile['FILE_HASH'], $bucket->ID);
1483 if ($original !== null)
1484 {
1485 $arFile['original_file'] = $original;
1486
1487 //we don't need the duplicate anymore
1488 $bucket->DeleteFile($filePath);
1489 }
1490 }
1491 }
1492 }
1493
1494 $arFile['HANDLER_ID'] = $bucket->ID;
1495 $arFile['WIDTH'] = 0;
1496 $arFile['HEIGHT'] = 0;
1497
1498 if ($original === null)
1499 {
1500 $arFile['SUBDIR'] = $subDir;
1501 $arFile['FILE_NAME'] = $newName;
1502 }
1503 else
1504 {
1505 //points to the original's physical path
1506 $arFile['SUBDIR'] = $original->getFile()->getSubdir();
1507 $arFile['FILE_NAME'] = $original->getFile()->getFileName();
1508 }
1509
1510 if (array_key_exists('bucket', $arFile))
1511 {
1512 $arFile['WIDTH'] = $arFile['width'];
1513 $arFile['HEIGHT'] = $arFile['height'];
1514 $arFile['size'] = $arFile['file_size'];
1515 }
1516 elseif ($copySize !== false)
1517 {
1518 $arFile['WIDTH'] = $arFile['width'];
1519 $arFile['HEIGHT'] = $arFile['height'];
1520 $arFile['size'] = $copySize;
1521
1522 //if the file is a duplicate we shouldn't increase the size counter
1523 if ($original === null)
1524 {
1525 $bucket->IncFileCounter($copySize);
1527 $bucket->ID
1528 ,$subDir
1529 ,$newName
1530 ,$copySize
1531 );
1532 }
1533 }
1534 else
1535 {
1536 //if the file is a duplicate we shouldn't increase the size counter
1537 if ($original === null)
1538 {
1539 $fileSize = filesize($arFile['tmp_name']);
1540 $bucket->IncFileCounter($fileSize);
1542 $bucket->ID
1543 ,$subDir
1544 ,$newName
1545 ,$fileSize
1546 );
1547 }
1548
1549 $image = new \Bitrix\Main\File\Image($arFile['tmp_name']);
1550 $flashEnabled = !CFile::IsImage($arFile['ORIGINAL_NAME'], $arFile['type']);
1551 $info = $image->getInfo($flashEnabled);
1552 if ($info !== null)
1553 {
1554 $arFile['WIDTH'] = $info->getWidth();
1555 $arFile['HEIGHT'] = $info->getHeight();
1556 }
1557 }
1558
1559 if (isset($arFile['old_file']))
1560 {
1561 CFile::Delete($arFile['old_file']);
1562 }
1563
1564 return true;
1565 }
1566
1567 public static function OnAfterFileSave($arFile)
1568 {
1570 $arFile['HANDLER_ID']
1571 ,$arFile['SUBDIR']
1572 ,$arFile['FILE_NAME']
1573 );
1574 }
1575
1576 public static function OnAfterFileDeleteDuplicate($original, $duplicate)
1577 {
1578 $result = false;
1579 if ($original->getHandlerId() > 0)
1580 {
1581 $bucket = new CCloudStorageBucket($original->getHandlerId());
1582 if ($bucket->Init())
1583 {
1584 $duplicatePath = '/' . $duplicate->getSubdir() . '/' . $duplicate->getFileName();
1585 \Bitrix\Clouds\FileHashTable::deleteByFilePath($original->getHandlerId(), $duplicatePath);
1586
1587 $result = $bucket->DeleteFile($duplicatePath, $duplicate->getFileSize());
1588 if ($result)
1589 {
1590 $bucket->DecFileCounter($duplicate->getFileSize());
1591 }
1592 }
1593 }
1594 return $result;
1595 }
1596
1597 public static function CleanUp()
1598 {
1599 $buckets = [];
1600 $date = new \Bitrix\Main\Type\DateTime();
1601 $date->add('-1D');
1603 'filter' => [
1604 '<TIMESTAMP_X' => $date,
1605 ],
1606 'limit' => 100, // ~10 sec
1607 ]);
1608 while ($saveFile = $savedFiles->fetchObject())
1609 {
1610 $dbFile = CFile::GetList([], [
1611 'EXTERNAL_ID' => $saveFile->getExternalId(),
1612 'SUBDIR' => $saveFile->getSubdir(),
1613 'FILE_NAME' => $saveFile->getFileName(),
1614 'HANDLER_ID' => $saveFile->getBucketId(),
1615 ]);
1616 if ($dbFile->Fetch())
1617 {
1618 $saveFile->delete();
1619 }
1620 else
1621 {
1622 $bucketId = $saveFile->getBucketId();
1623 if (!isset($buckets[$bucketId]))
1624 {
1625 $buckets[$bucketId] = new \CCloudStorageBucket($bucketId);
1626 }
1627 $bucket = $buckets[$bucketId];
1628
1629 if ($bucket->Init())
1630 {
1631 $filePath = '/' . $saveFile->getSubdir() . '/' . $saveFile->getFileName();
1632 if ($bucket->DeleteFile($filePath))
1633 {
1634 $fileSize = $saveFile->getFileSize();
1635 if ($fileSize >= 0)
1636 {
1637 $bucket->DecFileCounter($fileSize);
1638 }
1639 }
1640 $saveFile->delete();
1641 }
1642 }
1643 }
1644
1646
1647 return 'CCloudStorage::CleanUp();';
1648 }
1649
1650 public static function FindBucketByFile($file_name)
1651 {
1652 foreach (CCloudStorageBucket::GetAllBuckets() as $bucket)
1653 {
1654 if ($bucket['ACTIVE'] == 'Y')
1655 {
1656 $obBucket = new CCloudStorageBucket($bucket['ID']);
1657 if ($obBucket->Init())
1658 {
1659 $prefix = $obBucket->GetFileSRC('/');
1660 if (mb_substr($file_name, 0, mb_strlen($prefix)) === $prefix)
1661 {
1662 return $obBucket;
1663 }
1664 }
1665 }
1666 }
1667 return false;
1668 }
1669
1670 public static function FindFileURIByURN($urn, $log_descr = '')
1671 {
1672 foreach (CCloudStorageBucket::GetAllBuckets() as $bucket)
1673 {
1674 if ($bucket['ACTIVE'] == 'Y')
1675 {
1676 $obBucket = new CCloudStorageBucket($bucket['ID']);
1677 if ($obBucket->Init() && $obBucket->FileExists($urn))
1678 {
1679 $uri = $obBucket->GetFileSRC($urn);
1680
1681 if ($log_descr && COption::GetOptionString('clouds', 'log_404_errors') === 'Y')
1682 {
1683 CEventLog::Log('WARNING', 'CLOUDS_404', 'clouds', $uri, $log_descr);
1684 }
1685
1686 return $uri;
1687 }
1688 }
1689 }
1690 return '';
1691 }
1692
1693 public static function OnBuildGlobalMenu(&$aGlobalMenu, &$aModuleMenu)
1694 {
1695 global $USER;
1696 if (!$USER->CanDoOperation('clouds_browse'))
1697 {
1698 return;
1699 }
1700
1701 //When UnRegisterModuleDependences is called from module uninstall
1702 //cached EventHandlers may be called
1703 if (defined('BX_CLOUDS_UNINSTALLED'))
1704 {
1705 return;
1706 }
1707
1708 $aMenu = [
1709 'parent_menu' => 'global_menu_content',
1710 'section' => 'clouds',
1711 'sort' => 150,
1712 'text' => GetMessage('CLO_STORAGE_MENU'),
1713 'title' => GetMessage('CLO_STORAGE_TITLE'),
1714 'icon' => 'clouds_menu_icon',
1715 'page_icon' => 'clouds_page_icon',
1716 'items_id' => 'menu_clouds',
1717 'items' => []
1718 ];
1719
1720 $rsBuckets = CCloudStorageBucket::GetList(['SORT' => 'DESC', 'ID' => 'ASC']);
1721 while ($arBucket = $rsBuckets->Fetch())
1722 {
1723 $aMenu['items'][] = [
1724 'text' => $arBucket['BUCKET'],
1725 'url' => 'clouds_file_list.php?lang=' . LANGUAGE_ID . '&bucket=' . $arBucket['ID'] . '&path=/',
1726 'more_url' => [
1727 'clouds_file_list.php?bucket=' . $arBucket['ID'],
1728 ],
1729 'title' => '',
1730 'page_icon' => 'clouds_page_icon',
1731 'items_id' => 'menu_clouds_bucket_' . $arBucket['ID'],
1732 'module_id' => 'clouds',
1733 'items' => []
1734 ];
1735 }
1736
1737 if (!empty($aMenu['items']))
1738 {
1739 $aModuleMenu[] = $aMenu;
1740 }
1741 }
1742
1743 public static function OnAdminListDisplay(&$obList)
1744 {
1745 global $USER;
1746
1747 if ($obList->table_id !== 'tbl_fileman_admin')
1748 {
1749 return;
1750 }
1751
1752 if (!is_object($USER) || !$USER->CanDoOperation('clouds_upload'))
1753 {
1754 return;
1755 }
1756
1757 static $clouds = null;
1758 if (!isset($clouds))
1759 {
1760 $clouds = [];
1761 $rsClouds = CCloudStorageBucket::GetList(['SORT' => 'DESC', 'ID' => 'ASC']);
1762 while ($arStorage = $rsClouds->Fetch())
1763 {
1764 if ($arStorage['READ_ONLY'] == 'N' && $arStorage['ACTIVE'] == 'Y')
1765 {
1766 $clouds[$arStorage['ID']] = $arStorage['BUCKET'];
1767 }
1768 }
1769 }
1770
1771 if (empty($clouds))
1772 {
1773 return;
1774 }
1775
1776 foreach ($obList->aRows as $obRow)
1777 {
1778 if ($obRow->arRes['TYPE'] === 'F')
1779 {
1780 $ID = 'F' . $obRow->arRes['NAME'];
1781 $file = $obRow->arRes['NAME'];
1782 $path = mb_substr($obRow->arRes['ABS_PATH'], 0, -mb_strlen($file));
1783
1784 $arSubMenu = [];
1785 foreach ($clouds as $id => $bucket)
1786 {
1787 $arSubMenu[] = [
1788 'TEXT' => $bucket,
1789 'ACTION' => $s = "if(confirm('" . GetMessage('CLO_STORAGE_UPLOAD_CONF') . "')) jsUtils.Redirect([], '" . CUtil::AddSlashes('/bitrix/admin/clouds_file_list.php?lang=' . LANGUAGE_ID . '&bucket=' . urlencode($id) . '&path=' . urlencode($path) . '&ID=' . urlencode($ID) . '&action=upload&' . bitrix_sessid_get()) . "');"
1790 ];
1791 }
1792
1793 $obRow->aActions[] = [
1794 'TEXT' => GetMessage('CLO_STORAGE_UPLOAD_MENU'),
1795 'MENU' => $arSubMenu,
1796 ];
1797 }
1798 }
1799 }
1800
1801 public static function HasActiveBuckets()
1802 {
1803 foreach (CCloudStorageBucket::GetAllBuckets() as $bucket)
1804 {
1805 if ($bucket['ACTIVE'] === 'Y')
1806 {
1807 return true;
1808 }
1809 }
1810 return false;
1811 }
1812
1813 public static function OnBeforeProlog()
1814 {
1815 if (defined('BX_CHECK_SHORT_URI') && BX_CHECK_SHORT_URI)
1816 {
1817 $upload_dir = '/' . trim(COption::GetOptionString('main', 'upload_dir', 'upload'), '/') . '/';
1818 $request_uri = rawurldecode($_SERVER['REQUEST_URI']);
1819
1820 foreach (CCloudStorageBucket::GetAllBuckets() as $arBucket)
1821 {
1822 if ($arBucket['ACTIVE'] == 'Y')
1823 {
1824 $obBucket = new CCloudStorageBucket($arBucket['ID']);
1825 if ($obBucket->Init())
1826 {
1827 $bucketUrl = $obBucket->GetFileSRC('/');
1828 $bucketPrefix = rtrim(parse_url($bucketUrl, PHP_URL_PATH), '/');
1829 $prefixMatch = $bucketPrefix ? '(?:' . $bucketPrefix . '|)' : '';
1830 $match = [];
1831 if (
1832 COption::GetOptionString('clouds', 'delayed_resize') === 'Y'
1833 && preg_match('#^' . $prefixMatch . '(/resize_cache/.*$)#', $request_uri, $match)
1834 )
1835 {
1836 session_write_close();
1837 $to_file = $obBucket->GetFileSRC($match[1], false);
1838 if (CCloudStorage::ResizeImageFileCheck($obBucket, $to_file))
1839 {
1840 $cache_time = 3600 * 24 * 30; // 30 days
1841 header('Cache-Control: max-age=' . $cache_time);
1842 header('Expires: ' . gmdate('D, d M Y H:i:s', time() + $cache_time) . ' GMT');
1843 header_remove('Pragma');
1844 LocalRedirect(\Bitrix\Main\Web\Uri::urnEncode($to_file, 'UTF-8'), true, '301 Moved Permanently');
1845 }
1846 }
1847 elseif (
1848 !preg_match('/[?&]/', $request_uri)
1849 && $obBucket->FileExists($request_uri)
1850 )
1851 {
1852 if (COption::GetOptionString('clouds', 'log_404_errors') === 'Y')
1853 {
1854 CEventLog::Log('WARNING', 'CLOUDS_404', 'clouds', $_SERVER['REQUEST_URI'], $_SERVER['HTTP_REFERER']);
1855 }
1856 LocalRedirect($obBucket->GetFileSRC($request_uri), true);
1857 }
1858 elseif (mb_strpos($request_uri, $upload_dir) === 0)
1859 {
1860 $check_url = mb_substr($request_uri, mb_strlen($upload_dir) - 1);
1861 if ($obBucket->FileExists($check_url))
1862 {
1863 if (COption::GetOptionString('clouds', 'log_404_errors') === 'Y')
1864 {
1865 CEventLog::Log('WARNING', 'CLOUDS_404', 'clouds', $_SERVER['REQUEST_URI'], $_SERVER['HTTP_REFERER']);
1866 }
1867 LocalRedirect($obBucket->GetFileSRC($check_url), true);
1868 }
1869 }
1870 }
1871 }
1872 }
1873 }
1874 }
1875
1876 public static function GetAuditTypes()
1877 {
1878 return [
1879 'CLOUDS_404' => '[CLOUDS_404] ' . GetMessage('CLO_404_ON_MOVED_FILE'),
1880 ];
1881 }
1882
1883 public static function translit($file_name, $safe_chars = '')
1884 {
1885 return CUtil::translit($file_name, LANGUAGE_ID, [
1886 'safe_chars' => '-. ' . $safe_chars,
1887 'change_case' => false,
1888 'max_len' => 255,
1889 ]);
1890 }
1891
1896 public static function FixFileContentType(&$arFile)
1897 {
1898 global $DB;
1899 $fixedContentType = '';
1900
1901 if ($arFile['CONTENT_TYPE'] === 'image/jpg')
1902 {
1903 $fixedContentType = 'image/jpeg';
1904 }
1905 else
1906 {
1907 $hexContentType = unpack('H*', $arFile['CONTENT_TYPE']);
1908 if (
1909 $hexContentType[1] === 'e0f3e4e8ee2f6d706567'
1910 || $hexContentType[1] === 'd0b0d183d0b4d0b8d0be2f6d706567'
1911 )
1912 {
1913 $fixedContentType = 'audio/mpeg';
1914 }
1915 }
1916
1917 if ($fixedContentType !== '')
1918 {
1919 $arFile['CONTENT_TYPE'] = $fixedContentType;
1920 $DB->Query("
1921 UPDATE b_file
1922 SET CONTENT_TYPE = '" . $DB->ForSQL($fixedContentType) . "'
1923 WHERE ID = " . intval($arFile['ID']) . '
1924 ');
1925 CFile::CleanCache($arFile['ID']);
1926 }
1927 }
1928}
$path
Определения access_edit.php:21
static deleteByFilePath($bucketId, $filePath)
Определения filehash.php:339
static endFileOperation($bucketId, $subDir, $fileName)
Определения filesave.php:206
static setFileSize($bucketId, $subDir, $fileName, $fileSize)
Определения filesave.php:186
static startFileOperation($bucketId, $subDir, $fileName, $externalId)
Определения filesave.php:154
static getList(array $parameters=array())
Определения datamanager.php:431
static GetOptionString($module_id, $name, $def="", $site=false, $bExactSite=false)
Определения option.php:8
static GetInstance()
Определения virtual_io.php:60
static GetAllBuckets()
Определения storage_bucket.php:654
static GetList($arOrder=[], $arFilter=[], $arSelect=[])
Определения storage_bucket.php:791
Определения storage.php:5
static GetServiceDescription($ID)
Определения storage.php:88
static GetAuditTypes()
Определения storage.php:1876
static OnAfterFileDeleteDuplicate($original, $duplicate)
Определения storage.php:1576
static $part_size
Определения storage.php:11
const FILE_UPLOAD_ERROR
Определения storage.php:9
static ResizeImageFileDelay(&$arDestinationSize, $sourceFile, $destinationFile, $arResizeParams)
Определения storage.php:605
const FILE_PARTLY_UPLOADED
Определения storage.php:8
static OnAdminListDisplay(&$obList)
Определения storage.php:1743
static FixFileContentType(&$arFile)
Определения storage.php:1896
static $part_count
Определения storage.php:12
static GetServiceByID($ID)
Определения storage.php:44
static OnBeforeProlog()
Определения storage.php:1813
static GetImageSize($path)
Определения storage.php:211
static OnBeforeResizeImage($arFile, $arResizeParams, &$callbackData, &$bNeedResize, &$sourceImageFile, &$cacheImageFileTmp)
Определения storage.php:241
static OnMakeFileArray($arSourceFile, &$arDestination)
Определения storage.php:829
static _init()
Определения storage.php:22
static ResizeImageFileGet($destinationFile)
Определения storage.php:551
static GetServiceLocationList($ID)
Определения storage.php:70
static FindBucketByFile($file_name)
Определения storage.php:1650
static MoveFile($arFile, $obTargetBucket)
Определения storage.php:1084
static CleanUp()
Определения storage.php:1597
static translit($file_name, $safe_chars='')
Определения storage.php:1883
static HasActiveBuckets()
Определения storage.php:1801
static _delete_file($file)
Определения storage.php:1071
static OnBuildGlobalMenu(&$aGlobalMenu, &$aModuleMenu)
Определения storage.php:1693
static FindBucketForFile($arFile, $strFileName)
Определения storage.php:106
static OnFileDelete($arFile)
Определения storage.php:893
static OnFileCopy(&$arFile, $newPath='')
Определения storage.php:974
static FindFileURIByURN($urn, $log_descr='')
Определения storage.php:1670
static OnAfterFileSave($arFile)
Определения storage.php:1567
const FILE_SKIPPED
Определения storage.php:6
static OnFileSave(&$arFile, $strFileName, $strSavePath, $bForceMD5=false, $bSkipExt=false, $dirAdd='')
Определения storage.php:1294
static OnGetFileSRC($arFile)
Определения storage.php:1055
static ResizeImageFileCheck($obBucket, $path)
Определения storage.php:691
static $file_skip_reason
Определения storage.php:17
const FILE_MOVED
Определения storage.php:7
static DeleteDirFilesEx($path)
Определения storage.php:946
static GetServiceList()
Определения storage.php:60
static ResizeImageFileAdd(&$arDestinationSize, $sourceFile, $destinationFile, $arResizeParams, $errorCode=0)
Определения storage.php:569
static CleanUp($ID='')
Определения storage_upload.php:438
static URLEncode($str, $charset, $file_name=false)
Определения util.php:10
static Log($SEVERITY, $AUDIT_TYPE_ID, $MODULE_ID, $ITEM_ID, $DESCRIPTION=false, $SITE_ID=false)
Определения event_log.php:32
static MakeFileArray($path, $mimetype=false, $skipInternal=false, $external_id="")
Определения file.php:2005
if(!is_array($prop["VALUES"])) $tmp
Определения component_props.php:203
$res
Определения filter_act.php:7
$result
Определения get_property_values.php:14
if($ajaxMode) $ID
Определения get_user.php:27
$_SERVER["DOCUMENT_ROOT"]
Определения cron_frame.php:9
global $DB
Определения cron_frame.php:29
global $USER
Определения csv_new_run.php:40
if(( $ACTION=='EXPORT_EDIT'||$ACTION=='EXPORT_COPY') &&$STEP==1) if($STEP > 1) if(( $ACTION=='EXPORT_EDIT'||$ACTION=='EXPORT_COPY') &&$STEP==2) if($STEP >2) $aMenu
Определения csv_new_setup.php:214
$io
Определения csv_new_run.php:98
global $arCloudImageSizeCache
Определения file.php:3434
const BX_CHECK_SHORT_URI(str_starts_with($requestUri, "/bitrix/admin/"))
Определения urlrewrite.php:142
if(file_exists($_SERVER['DOCUMENT_ROOT'] . "/urlrewrite.php")) $uri
Определения urlrewrite.php:61
if($NS['step']==6) if( $NS[ 'step']==7) if(COption::GetOptionInt('main', 'disk_space', 0) > 0) $info
Определения backup.php:924
CheckDirPath($path)
Определения tools.php:2707
ExecuteModuleEventEx($arEvent, $arParams=[])
Определения tools.php:5214
RemoveScriptExtension($check_name)
Определения tools.php:2939
bx_basename($path, $ext="")
Определения tools.php:3269
GetModuleEvents($MODULE_ID, $MESSAGE_ID, $bReturnArray=false)
Определения tools.php:5177
IncludeModuleLangFile($filepath, $lang=false, $bReturnArray=false)
Определения tools.php:3778
GetMessage($name, $aReplace=null)
Определения tools.php:3397
MakeTimeStamp($datetime, $format=false)
Определения tools.php:538
bitrix_sessid_get($varname='sessid')
Определения tools.php:4695
LocalRedirect($url, $skip_security_check=false, $status="302 Found")
Определения tools.php:4005
return false
Определения prolog_main_admin.php:185
if( $daysToExpire >=0 &&$daysToExpire< 60 elseif)( $daysToExpire< 0)
Определения prolog_main_admin.php:393
$ar
Определения options.php:199
$i
Определения factura.php:643
else $a
Определения template.php:137