Server IP : 80.87.202.40 / Your IP : 216.73.216.169 Web Server : Apache System : Linux rospirotorg.ru 5.14.0-539.el9.x86_64 #1 SMP PREEMPT_DYNAMIC Thu Dec 5 22:26:13 UTC 2024 x86_64 User : bitrix ( 600) PHP Version : 8.2.27 Disable Function : NONE MySQL : OFF | cURL : ON | WGET : ON | Perl : ON | Python : OFF | Sudo : ON | Pkexec : ON Directory : /home/bitrix/ext_www/rospirotorg.ru/bitrix/modules/clouds/classes/general/ |
Upload File : |
<?php IncludeModuleLangFile(__FILE__); class CCloudStorage { const FILE_SKIPPED = 0; const FILE_MOVED = 1; const FILE_PARTLY_UPLOADED = 2; const FILE_UPLOAD_ERROR = 3; public static $part_size = 0; public static $part_count = 0; private static $_services = /*.(array[string]CCloudStorageService).*/ null; public static $file_skip_reason = ''; /** * @return void */ public static function _init() { if (!isset(self::$_services)) { /* @var CCloudStorageService $obService */ $obService = null; self::$_services = /*.(array[string]CCloudStorageService).*/ []; foreach (GetModuleEvents('clouds', 'OnGetStorageService', true) as $arEvent) { $obService = ExecuteModuleEventEx($arEvent); if (is_object($obService)) { self::$_services[$obService->GetID()] = $obService; } } } } /** * @param string $ID * @return CCloudStorageService */ public static function GetServiceByID($ID) { self::_init(); if (array_key_exists($ID, self::$_services)) { return self::$_services[$ID]; } else { return null; } } /** * @return array[string]CCloudStorageService */ public static function GetServiceList() { self::_init(); return self::$_services; } /** * @param string $ID * @return array[string]string|false */ public static function GetServiceLocationList($ID) { $obService = CCloudStorage::GetServiceByID($ID); if (is_object($obService)) { return $obService->GetLocationList(); } else { return /*.(array[string]string).*/ []; } } /** * @param string $ID * @return string */ public static function GetServiceDescription($ID) { $obService = CCloudStorage::GetServiceByID($ID); if (is_object($obService)) { return $obService->GetName(); } else { return ''; } } /** * @param array [string]string $arFile * @param string $strFileName * @return CCloudStorageBucket */ public static function FindBucketForFile($arFile, $strFileName) { if (array_key_exists('size', $arFile) && $arFile['size'] > 0) { $file_size = intval($arFile['size']); } elseif (array_key_exists('FILE_SIZE', $arFile) && $arFile['FILE_SIZE'] > 0) { $file_size = intval($arFile['FILE_SIZE']); } else { $file_size = intval($arFile['file_size']); } self::$file_skip_reason = ''; $activeCounter = 0; $writableCounter = 0; foreach (CCloudStorageBucket::GetAllBuckets() as $bucket) { if ($bucket['ACTIVE'] !== 'Y') { continue; } $activeCounter++; if ($bucket['READ_ONLY'] === 'Y') { continue; } $writableCounter++; foreach ($bucket['FILE_RULES_COMPILED'] as $rule) { if ($rule['MODULE_MASK'] != '') { $bMatchModule = (preg_match($rule['MODULE_MASK'], $arFile['MODULE_ID']) > 0); } else { $bMatchModule = true; } if ($rule['EXTENTION_MASK'] != '') { $bMatchExtention = (preg_match($rule['EXTENTION_MASK'], $strFileName) > 0) || (preg_match($rule['EXTENTION_MASK'], $arFile['ORIGINAL_NAME']) > 0); } else { $bMatchExtention = true; } if ($rule['SIZE_ARRAY']) { $bMatchSize = false; foreach ($rule['SIZE_ARRAY'] as $size) { if ( ($file_size >= $size[0]) && ($size[1] === 0.0 || $file_size <= $size[1]) ) { $bMatchSize = true; } } } else { $bMatchSize = true; } if (!$bMatchModule) { self::$file_skip_reason = 'NO_FILE_MODULE_MATCH'; } elseif (!$bMatchExtention) { self::$file_skip_reason = 'NO_FILE_EXTENTION_MATCH'; } elseif (!$bMatchSize) { self::$file_skip_reason = 'NO_FILE_SIZE_MATCH'; } if ($bMatchModule && $bMatchExtention && $bMatchSize) { return new CCloudStorageBucket(intval($bucket['ID'])); } } } if (!$activeCounter) { self::$file_skip_reason = 'NO_ACTIVE_BUCKETS'; } elseif (!$writableCounter) { self::$file_skip_reason = 'NO_WRITABLE_BUCKETS'; } return null; } public static function GetImageSize($path) { $io = CBXVirtualIo::GetInstance(); $path = $io->GetPhysicalName($path); $image = new \Bitrix\Main\File\Image($path); if (($info = $image->getInfo(false)) !== null) { return [ 0 => $info->getWidth(), 1 => $info->getHeight(), 2 => $info->getFormat(), 3 => $info->getAttributes(), 'mime' => $info->getMime(), ]; } return false; } /** * @param array [string]string $arFile * @param array [string]string $arResizeParams * @param array [string]mixed $callbackData * @param bool $bNeedResize * @param array [string]string $sourceImageFile * @param array [string]string $cacheImageFileTmp * @return bool */ public static function OnBeforeResizeImage($arFile, $arResizeParams, &$callbackData, &$bNeedResize, &$sourceImageFile, &$cacheImageFileTmp) { $callbackData = null; if (intval($arFile['HANDLER_ID']) <= 0) { return false; } $obSourceBucket = new CCloudStorageBucket(intval($arFile['HANDLER_ID'])); if (!$obSourceBucket->Init()) { return false; } $callbackData = /*.(array[string]mixed).*/ []; $callbackData['obSourceBucket'] = $obSourceBucket; //Assume target bucket same as source $callbackData['obTargetBucket'] = $obTargetBucket = $obSourceBucket; //if original file bucket is read only if ($obSourceBucket->READ_ONLY === 'Y') //Try to find bucket with write rights { $bucket = CCloudStorage::FindBucketForFile($arFile, $arFile['FILE_NAME']); if (!is_object($bucket)) { return false; } if ($bucket->Init()) { $callbackData['obTargetBucket'] = $obTargetBucket = $bucket; } } if (!$arFile['SRC']) { $arFile['SRC'] = $obSourceBucket->GetFileSRC($arFile, false); } if (defined('BX_MOBILE') && constant('BX_MOBILE') === true) { $bImmediate = true; } else { $bImmediate = $arResizeParams[5]; } $callbackData['bImmediate'] = $bImmediate; $callbackData['cacheID'] = $arFile['ID'] . '/' . md5(serialize($arResizeParams)); $callbackData['cacheOBJ'] = new CPHPCache; $callbackData['fileDIR'] = '/' . 'resize_cache/' . $callbackData['cacheID'] . '/' . $arFile['SUBDIR']; $callbackData['fileNAME'] = $arFile['FILE_NAME']; $callbackData['fileURL'] = $callbackData['fileDIR'] . '/' . $callbackData['fileNAME']; $result = true; if ($callbackData['cacheOBJ']->StartDataCache(CACHED_clouds_file_resize, $callbackData['cacheID'], 'clouds')) { $cacheImageFile = $obTargetBucket->GetFileSRC($callbackData['fileURL'], false); $arDestinationSize = []; //Check if it is cache file was deleted, but there was a successful resize $delayInfo = $bImmediate ? false : CCloudStorage::ResizeImageFileGet($cacheImageFile); if (is_array($delayInfo) && ($delayInfo['ERROR_CODE'] < 10)) { $callbackData['cacheSTARTED'] = true; if ($arFile['FILE_SIZE'] > 1) { $callbackData['fileSize'] = $arFile['FILE_SIZE']; } $bNeedResize = false; $result = true; } //Check if it is cache file was deleted, but not the file in the cloud elseif ($fs = $obTargetBucket->FileExists($callbackData['fileURL'])) { //If file was resized before the fact was registered if (COption::GetOptionString('clouds', 'delayed_resize') === 'Y') { CCloudStorage::ResizeImageFileAdd( $arDestinationSize, $arFile, $cacheImageFile, $arResizeParams, 9 //already where ); } $callbackData['cacheSTARTED'] = true; if ($fs > 1) { $callbackData['fileSize'] = $fs; } $bNeedResize = false; $result = true; } else { $callbackData['tmpFile'] = CFile::GetTempName('', $arFile['FILE_NAME']); $callbackData['tmpFile'] = preg_replace('#[\\\\/]+#', '/', $callbackData['tmpFile']); if ( !$bImmediate && COption::GetOptionString('clouds', 'delayed_resize') === 'Y' && CCloudStorage::ResizeImageFileDelay( $arDestinationSize, $arFile, $cacheImageFile, $arResizeParams ) ) { $callbackData['cacheSTARTED'] = false; $bNeedResize = false; $callbackData['cacheOBJ']->AbortDataCache(); $callbackData['cacheVARS'] = [ 'cacheImageFile' => $cacheImageFile, 'width' => $arDestinationSize['width'], 'height' => $arDestinationSize['height'], 'size' => null, ]; $result = true; } elseif ($obSourceBucket->DownloadToFile($arFile, $callbackData['tmpFile'])) { $callbackData['cacheSTARTED'] = true; $bNeedResize = true; $sourceImageFile = $callbackData['tmpFile']; $cacheImageFileTmp = CFile::GetTempName('', $arFile['FILE_NAME']); $result = true; } else { $callbackData['cacheSTARTED'] = false; $bNeedResize = false; $callbackData['cacheOBJ']->AbortDataCache(); $result = false; } } } else { $callbackData['cacheSTARTED'] = false; $callbackData['cacheVARS'] = $callbackData['cacheOBJ']->GetVars(); $bNeedResize = false; $result = true; } return $result; } public static function OnAfterResizeImage($arFile, $arResizeParams, &$callbackData, &$cacheImageFile, &$cacheImageFileTmp, &$arImageSize) { global $arCloudImageSizeCache; $io = CBXVirtualIo::GetInstance(); if (!is_array($callbackData)) { return false; } if ($callbackData['cacheSTARTED']) { /** @var CCloudStorageBucket $obTargetBucket */ $obTargetBucket = $callbackData['obTargetBucket']; /** @var CPHPCache $cacheOBJ */ $cacheOBJ = $callbackData['cacheOBJ']; if (isset($callbackData['tmpFile'])) //have to upload to the cloud { $arFileToStore = CFile::MakeFileArray($io->GetPhysicalName($cacheImageFileTmp)); if (!$arFileToStore) { $cacheOBJ->AbortDataCache(); $tmpFile = $io->GetPhysicalName($callbackData['tmpFile']); unlink($tmpFile); @rmdir(mb_substr($tmpFile, 0, -mb_strlen(bx_basename($tmpFile)))); unlink($cacheImageFileTmp); @rmdir(mb_substr($cacheImageFileTmp, 0, -mb_strlen(bx_basename($cacheImageFileTmp)))); $obSourceBucket = new CCloudStorageBucket(intval($arFile['HANDLER_ID'])); if ($obSourceBucket->Init()) { $cacheImageFile = $obSourceBucket->GetFileSRC($arFile, false); } return false; } if (!preg_match('/^image\\//', $arFileToStore['type'])) { $arFileToStore['type'] = $arFile['CONTENT_TYPE']; } if ($obTargetBucket->SaveFile($callbackData['fileURL'], $arFileToStore)) { $cacheImageFile = $obTargetBucket->GetFileSRC($callbackData['fileURL'], false); $arImageSize = static::GetImageSize($cacheImageFileTmp); $arImageSize[2] = filesize($io->GetPhysicalName($cacheImageFileTmp)); $iFileSize = filesize($arFileToStore['tmp_name']); if (!is_array($arImageSize)) { $arImageSize = [0, 0]; } $cacheOBJ->EndDataCache([ 'cacheImageFile' => $cacheImageFile, 'width' => $arImageSize[0], 'height' => $arImageSize[1], 'size' => $arImageSize[2], ]); $tmpFile = $io->GetPhysicalName($callbackData['tmpFile']); unlink($tmpFile); @rmdir(mb_substr($tmpFile, 0, -mb_strlen(bx_basename($tmpFile)))); $arCloudImageSizeCache[$cacheImageFile] = $arImageSize; $obTargetBucket->IncFileCounter($iFileSize); if ( COption::GetOptionString('clouds', 'delayed_resize') === 'Y' && !is_array(CCloudStorage::ResizeImageFileGet($cacheImageFile)) ) { $arDestinationSize = []; CCloudStorage::ResizeImageFileAdd( $arDestinationSize, $arFile, $cacheImageFile, $arResizeParams, 9 //already there ); } } else { $cacheOBJ->AbortDataCache(); $tmpFile = $io->GetPhysicalName($callbackData['tmpFile']); unlink($tmpFile); @rmdir(mb_substr($tmpFile, 0, -mb_strlen(bx_basename($tmpFile)))); unlink($cacheImageFileTmp); @rmdir(mb_substr($cacheImageFileTmp, 0, -mb_strlen(bx_basename($cacheImageFileTmp)))); $obSourceBucket = new CCloudStorageBucket(intval($arFile['HANDLER_ID'])); if ($obSourceBucket->Init()) { $cacheImageFile = $obSourceBucket->GetFileSRC($arFile, false); } return false; } } else //the file is already in the cloud { $source = new \Bitrix\Main\File\Image\Rectangle($arFile['WIDTH'], $arFile['HEIGHT']); $destination = new \Bitrix\Main\File\Image\Rectangle($arResizeParams[0]['width'], $arResizeParams[0]['height']); $source->resize($destination, $arResizeParams[1]); $cacheImageFile = $obTargetBucket->GetFileSRC($callbackData['fileURL'], false); $arImageSize = [ $destination->getWidth(), $destination->getHeight(), $callbackData['fileSize'] ?? $obTargetBucket->GetFileSize($callbackData['fileURL']), ]; $cacheOBJ->EndDataCache([ 'cacheImageFile' => $cacheImageFile, 'width' => $arImageSize[0], 'height' => $arImageSize[1], 'size' => $arImageSize[2], ]); $arCloudImageSizeCache[$cacheImageFile] = $arImageSize; } } elseif (is_array($callbackData['cacheVARS'])) { $cacheImageFile = $callbackData['cacheVARS']['cacheImageFile']; $arImageSize = [ $callbackData['cacheVARS']['width'], $callbackData['cacheVARS']['height'], $callbackData['cacheVARS']['size'], ]; $arCloudImageSizeCache[$cacheImageFile] = $arImageSize; } else { return false; } $delayedResize = $callbackData['bImmediate'] ? false : COption::GetOptionString('clouds', 'delayed_resize') === 'Y'; foreach (GetModuleEvents('clouds', 'OnAfterResizeImage', true) as $arEvent) { $cacheImageFileBefore = $cacheImageFile; ExecuteModuleEventEx($arEvent, [$delayedResize, &$cacheImageFile]); if ($cacheImageFile !== $cacheImageFileBefore && $cacheImageFile) { $arCloudImageSizeCache[$cacheImageFile] = $arCloudImageSizeCache[$cacheImageFileBefore]; } } return true; } public static function ResizeImageFileGet($destinationFile) { global $DB; $destinationFile = preg_replace('/^https?:/i', '', $destinationFile); $destinationFile = CCloudUtil::URLEncode($destinationFile, 'UTF-8', true); $q = $DB->Query(' select ID ,ERROR_CODE ,FILE_ID ,' . $DB->DateToCharFunction('TIMESTAMP_X', 'FULL') . " TIMESTAMP_X from b_clouds_file_resize where TO_PATH = '" . $DB->ForSql($destinationFile) . "' "); $a = $q->Fetch(); return $a; } public static function ResizeImageFileAdd(&$arDestinationSize, $sourceFile, $destinationFile, $arResizeParams, $errorCode = 0) { global $DB; $destinationFile = preg_replace('/^https?:/i', '', $destinationFile); $destinationFile = CCloudUtil::URLEncode($destinationFile, 'UTF-8', true); $q = $DB->Query(' select ID ,ERROR_CODE ,PARAMS ,' . $DB->DateToCharFunction('TIMESTAMP_X', 'FULL') . " TIMESTAMP_X from b_clouds_file_resize where TO_PATH = '" . $DB->ForSql($destinationFile) . "' "); $a = $q->Fetch(); if ($a && $a['ERROR_CODE'] >= 10 && $a['ERROR_CODE'] < 20) { $DB->Query('DELETE from b_clouds_file_resize WHERE ID = ' . $a['ID']); $a = false; } if (!$a) { $arResizeParams['type'] = $sourceFile['CONTENT_TYPE']; $DB->Add('b_clouds_file_resize', [ '~TIMESTAMP_X' => $DB->CurrentTimeFunction(), 'ERROR_CODE' => intval($errorCode), 'PARAMS' => serialize($arResizeParams), 'FROM_PATH' => CCloudUtil::URLEncode($sourceFile['SRC'], 'UTF-8', true), 'TO_PATH' => $destinationFile, 'FILE_ID' => $sourceFile['ID'], ]); } } public static function ResizeImageFileDelay(&$arDestinationSize, $sourceFile, $destinationFile, $arResizeParams) { global $DB; $destinationFile = preg_replace('/^https?:/i', '', $destinationFile); $destinationFile = CCloudUtil::URLEncode($destinationFile, 'UTF-8', true); $q = $DB->Query(' select ID ,ERROR_CODE ,PARAMS ,' . $DB->DateToCharFunction('TIMESTAMP_X', 'FULL') . " TIMESTAMP_X from b_clouds_file_resize where TO_PATH = '" . $DB->ForSql($destinationFile) . "' "); if ($resize = $q->Fetch()) { if ($resize['ERROR_CODE'] < 10) { $arResizeParams = unserialize($resize['PARAMS'], ['allowed_classes' => false]); $id = $resize['ID']; } //Give it a try elseif ( $resize['ERROR_CODE'] >= 10 && $resize['ERROR_CODE'] < 20 && (MakeTimeStamp($resize['TIMESTAMP_X']) + 300/*5min*/) < (time() + CTimeZone::GetOffset()) ) { $DB->Query(' UPDATE b_clouds_file_resize SET ERROR_CODE = 1 WHERE ID=' . $resize['ID'] . ' '); $arResizeParams = unserialize($resize['PARAMS'], ['allowed_classes' => false]); $id = $resize['ID']; } else { return false; } } else { $id = 0; } $arSize = $arResizeParams[0]; $resizeType = $arResizeParams[1]; $arWaterMark = $arResizeParams[2]; // $jpgQuality = $arResizeParams[3]; $arFilters = $arResizeParams[4]; $source = new \Bitrix\Main\File\Image\Rectangle($sourceFile['WIDTH'], $sourceFile['HEIGHT']); $destination = new \Bitrix\Main\File\Image\Rectangle($arSize['width'], $arSize['height']); $bNeedCreatePicture = $source->resize($destination, $resizeType); $bNeedCreatePicture |= is_array($arWaterMark) && !empty($arWaterMark); $bNeedCreatePicture |= is_array($arFilters) && !empty($arFilters); if ($bNeedCreatePicture) { if ($id <= 0) { $arResizeParams['type'] = $sourceFile['CONTENT_TYPE']; $id = $DB->Add('b_clouds_file_resize', [ '~TIMESTAMP_X' => $DB->CurrentTimeFunction(), 'ERROR_CODE' => 2, 'PARAMS' => serialize($arResizeParams), 'FROM_PATH' => CCloudUtil::URLEncode($sourceFile['SRC'], 'UTF-8', true), 'TO_PATH' => $destinationFile, 'FILE_ID' => $sourceFile['ID'], ]); } return $id > 0; } else { return false; } } /** * @param CCloudStorageBucket $obBucket * @param string $path * @return bool */ public static function ResizeImageFileCheck($obBucket, $path) { global $DB; $io = CBXVirtualIo::GetInstance(); $path = preg_replace('/^https?:/i', '', $path); $path = CCloudUtil::URLEncode($path, 'UTF-8', true); $q = $DB->Query(' select ID ,ERROR_CODE ,TO_PATH ,FROM_PATH ,PARAMS ,' . $DB->DateToCharFunction('TIMESTAMP_X', 'FULL') . " TIMESTAMP_X from b_clouds_file_resize where TO_PATH = '" . $DB->ForSql($path) . "' "); $task = $q->Fetch(); if (!$task) { return false; } //File in the Sky with Diamonds if ($task['ERROR_CODE'] == 9) { return true; } //Fatal error if ($task['ERROR_CODE'] >= 20) { return false; } //Recoverable error if ($task['ERROR_CODE'] >= 10 && $task['ERROR_CODE'] < 20) { if ((MakeTimeStamp($task['TIMESTAMP_X']) + 300/*5min*/) > (time() + CTimeZone::GetOffset())) { return false; } } $DB->Query(' UPDATE b_clouds_file_resize SET ERROR_CODE = 11 WHERE ID = ' . $task['ID'] . ' '); $tmpFile = CFile::MakeFileArray($task['FROM_PATH']); // if (!is_array($tmpFile) || !file_exists($tmpFile["tmp_name"])) // { // $tmpFile = CFile::MakeFileArray(\Bitrix\Main\Web\Uri::urnEncode($task["FROM_PATH"], "UTF-8")); // } if (!is_array($tmpFile) || !file_exists($tmpFile['tmp_name'])) { $DB->Query(' UPDATE b_clouds_file_resize SET ERROR_CODE = 22 WHERE ID = ' . $task['ID'] . ' '); return false; } $arResizeParams = unserialize($task['PARAMS'], ['allowed_classes' => false]); if (!is_array($arResizeParams)) { $DB->Query(' UPDATE b_clouds_file_resize SET ERROR_CODE = 23 WHERE ID = ' . $task['ID'] . ' '); return false; } $DB->Query(' UPDATE b_clouds_file_resize SET ERROR_CODE = 14 WHERE ID = ' . $task['ID'] . ' '); $arSize = $arResizeParams[0]; $resizeType = $arResizeParams[1]; $arWaterMark = $arResizeParams[2]; $jpgQuality = $arResizeParams[3]; $arFilters = $arResizeParams[4]; $from_path = $io->GetLogicalName($tmpFile['tmp_name']); $to_path = rawurldecode($task['TO_PATH']); $to_path = CFile::GetTempName('', bx_basename($to_path)); if (!CFile::ResizeImageFile($from_path, $to_path, $arSize, $resizeType, $arWaterMark, $jpgQuality, $arFilters)) { $DB->Query(' UPDATE b_clouds_file_resize SET ERROR_CODE = 25 WHERE ID = ' . $task['ID'] . ' '); return false; } $DB->Query(' UPDATE b_clouds_file_resize SET ERROR_CODE = 16 WHERE ID = ' . $task['ID'] . ' '); $fileToStore = CFile::MakeFileArray($io->GetPhysicalName($to_path)); if ($arResizeParams['type'] && !preg_match('/^image\\//', $fileToStore['type'])) { $fileToStore['type'] = $arResizeParams['type']; } $baseURL = preg_replace('/^https?:/i', '', $obBucket->GetFileSRC('/')); $pathToStore = mb_substr($task['TO_PATH'], mb_strlen($baseURL) - 1); $pathToStore = rawurldecode($pathToStore); if (!$obBucket->SaveFile($pathToStore, $fileToStore)) { $DB->Query(' UPDATE b_clouds_file_resize SET ERROR_CODE = 27 WHERE ID = ' . $task['ID'] . ' '); return false; } $obBucket->IncFileCounter($fileToStore['size']); $DB->Query(' UPDATE b_clouds_file_resize SET ERROR_CODE = 9 WHERE ID = ' . $task['ID'] ); return true; } public static function OnMakeFileArray($arSourceFile, &$arDestination) { if (!is_array($arSourceFile)) { $file = $arSourceFile; if (mb_substr($file, 0, mb_strlen($_SERVER['DOCUMENT_ROOT'])) == $_SERVER['DOCUMENT_ROOT']) { $file = ltrim(mb_substr($file, mb_strlen($_SERVER['DOCUMENT_ROOT'])), '/'); } if (!preg_match('#^https?://#', $file)) { return false; } $bucket = CCloudStorage::FindBucketByFile($file); if (!is_object($bucket)) { return false; } $filePath = mb_substr($file, mb_strlen($bucket->GetFileSRC('/')) - 1); $filePath = rawurldecode($filePath); $io = CBXVirtualIo::GetInstance(); $target = CFile::GetTempName('', bx_basename($filePath)); $target = preg_replace('#[\\\\/]+#', '/', $target); if ($bucket->DownloadToFile($filePath, $target)) { $arDestination = $io->GetPhysicalName($target); } return true; } else { if ($arSourceFile['HANDLER_ID'] <= 0) { return false; } $bucket = new CCloudStorageBucket($arSourceFile['HANDLER_ID']); if (!$bucket->Init()) { return false; } $target = CFile::GetTempName('', $arSourceFile['FILE_NAME']); $target = preg_replace('#[\\\\/]+#', '/', $target); if ($bucket->DownloadToFile($arSourceFile, $target)) { $arDestination['name'] = ($arSourceFile['ORIGINAL_NAME'] <> '' ? $arSourceFile['ORIGINAL_NAME'] : $arSourceFile['FILE_NAME']); $arDestination['size'] = $arSourceFile['FILE_SIZE']; $arDestination['type'] = $arSourceFile['CONTENT_TYPE']; $arDestination['description'] = $arSourceFile['DESCRIPTION']; $arDestination['tmp_name'] = $target; } return true; } } public static function OnFileDelete($arFile) { global $DB; if ($arFile['HANDLER_ID'] <= 0) { return false; } $bucket = new CCloudStorageBucket($arFile['HANDLER_ID']); if ((!$bucket->Init()) || ($bucket->READ_ONLY === 'Y')) { return false; } $result = $bucket->DeleteFile('/' . $arFile['SUBDIR'] . '/' . $arFile['FILE_NAME']); if ($result) { $bucket->DecFileCounter($arFile['FILE_SIZE']); } $path = '/resize_cache/' . $arFile['ID'] . '/'; $arCloudFiles = $bucket->ListFiles($path, true); if (is_array($arCloudFiles['file'])) { $delete_size = 0; foreach ($arCloudFiles['file'] as $i => $file_name) { $tmp = $bucket->DeleteFile($path . $file_name); if ($tmp) { $bucket->DecFileCounter($arCloudFiles['file_size'][$i]); $delete_size += $arCloudFiles['file_size'][$i]; } } /****************************** QUOTA ******************************/ if ($delete_size > 0 && COption::GetOptionInt('main', 'disk_space') > 0) { CDiskQuota::updateDiskQuota('file', $delete_size, 'delete'); } /****************************** QUOTA ******************************/ } $DB->Query(' DELETE FROM b_clouds_file_resize WHERE FILE_ID = ' . intval($arFile['ID']) . ' ', true); \Bitrix\Clouds\FileHashTable::deleteByFilePath($bucket->ID, '/' . $arFile['SUBDIR'] . '/' . $arFile['FILE_NAME']); return $result; } public static function DeleteDirFilesEx($path) { $path = rtrim($path, '/') . '/'; foreach (CCloudStorageBucket::GetAllBuckets() as $bucket) { $obBucket = new CCloudStorageBucket($bucket['ID']); if ( $obBucket->Init() && ($obBucket->READ_ONLY === 'N') && ($obBucket->ACTIVE === 'Y') ) { $arCloudFiles = $obBucket->ListFiles($path, true); if (is_array($arCloudFiles['file'])) { foreach ($arCloudFiles['file'] as $i => $file_name) { $tmp = $obBucket->DeleteFile($path . $file_name); if ($tmp) { $obBucket->DecFileCounter($arCloudFiles['file_size'][$i]); } } } } } } public static function OnFileCopy(&$arFile, $newPath = '') { if ($arFile['HANDLER_ID'] <= 0) { return false; } $bucket = new CCloudStorageBucket($arFile['HANDLER_ID']); if (!$bucket->Init()) { return false; } if ($bucket->READ_ONLY === 'Y') { return false; } $filePath = ''; $newName = ''; if ($newPath !== '') { $filePath = '/' . trim(str_replace('//', '/', $newPath), '/'); } else { $strFileExt = strrchr($arFile['FILE_NAME'], '.'); while (true) { $newName = md5(uniqid(mt_rand(), true)) . $strFileExt; $filePath = '/' . $arFile['SUBDIR'] . '/' . $newName; if (!$bucket->FileExists($filePath)) { break; } } } if ($newPath === '') { if ($arFile['EXTERNAL_ID'] == '') { $arFile['EXTERNAL_ID'] = md5(mt_rand()); } \Bitrix\Clouds\FileSaveTable::startFileOperation( $bucket->ID ,$arFile['SUBDIR'] ,$newName ,$arFile['EXTERNAL_ID'] ); } $result = $bucket->FileCopy($arFile, $filePath); if ($result) { $copySize = $arFile['FILE_SIZE']; $bucket->IncFileCounter($copySize); \Bitrix\Clouds\FileSaveTable::setFileSize( $bucket->ID ,$arFile['SUBDIR'] ,$newName ,$copySize ); if ($newPath !== '') { $arFile['FILE_NAME'] = bx_basename($filePath); $arFile['SUBDIR'] = mb_substr($filePath, 1, -(mb_strlen(bx_basename($filePath)) + 1)); } else { $arFile['FILE_NAME'] = $newName; } } return $result; } public static function OnGetFileSRC($arFile) { if ($arFile['HANDLER_ID'] <= 0) { return false; } $bucket = new CCloudStorageBucket($arFile['HANDLER_ID']); if ($bucket->Init()) { return $bucket->GetFileSRC($arFile, false); } return false; } protected static function _delete_file($file) { if (is_array($file)) { CCloudStorage::OnFileDelete($file); } elseif (is_string($file) && file_exists($file)) { unlink($file); @rmdir(mb_substr($file, 0, -mb_strlen(bx_basename($file)))); } } public static function MoveFile($arFile, $obTargetBucket) { $io = CBXVirtualIo::GetInstance(); self::$file_skip_reason = ''; //Try to find suitable bucket for the file $bucket = CCloudStorage::FindBucketForFile($arFile, $arFile['FILE_NAME']); if (!is_object($bucket)) { return CCloudStorage::FILE_SKIPPED; } if (!$bucket->Init()) { self::$file_skip_reason = 'FAILED_TO_INIT_BUCKET'; return CCloudStorage::FILE_SKIPPED; } //Check if this is same bucket as the target if ($bucket->ID != $obTargetBucket->ID) { self::$file_skip_reason = 'FOUND_BUCKET_DOES_NOT_MATCH_TARGET'; return CCloudStorage::FILE_SKIPPED; } $filePath = '/' . $arFile['SUBDIR'] . '/' . $arFile['FILE_NAME']; $filePath = preg_replace('#[\\\\/]+#', '/', $filePath); if ($bucket->FileExists($filePath)) { self::$file_skip_reason = 'CLOUD_FILE_EXISTS'; return CCloudStorage::FILE_SKIPPED; } if ($arFile['FILE_SIZE'] > $bucket->getService()->GetMinUploadPartSize()) { $obUpload = new CCloudStorageUpload($filePath); if (!$obUpload->isStarted()) { if ($arFile['HANDLER_ID']) { $ar = []; if (!CCloudStorage::OnMakeFileArray($arFile, $ar)) { self::$file_skip_reason = 'FAILED_TO_DOWNLOAD_FILE_1'; return CCloudStorage::FILE_SKIPPED; } if (!isset($ar['tmp_name'])) { self::$file_skip_reason = 'FAILED_TO_DOWNLOAD_FILE_2'; return CCloudStorage::FILE_SKIPPED; } } else { $ar = CFile::MakeFileArray($arFile['ID']); if (!isset($ar['tmp_name'])) { self::$file_skip_reason = 'FAILED_TO_GET_SOURCE_FILE_INFO_1'; return CCloudStorage::FILE_SKIPPED; } } $temp_file = CTempFile::GetDirectoryName(2, 'clouds') . bx_basename($arFile['FILE_NAME']); $temp_fileX = $io->GetPhysicalName($temp_file); CheckDirPath($temp_fileX); if (file_exists($ar['tmp_name'])) { $sourceFile = $ar['tmp_name']; } elseif (file_exists($io->GetPhysicalName($ar['tmp_name']))) { $sourceFile = $io->GetPhysicalName($ar['tmp_name']); } else { self::$file_skip_reason = 'FAILED_TO_FIND_SOURCE_FILE'; return CCloudStorage::FILE_SKIPPED; } if (!copy($sourceFile, $temp_fileX)) { self::$file_skip_reason = 'FAILED_TO_COPY_SOURCE_FILE'; return CCloudStorage::FILE_SKIPPED; } if ($obUpload->Start($bucket->ID, $arFile['FILE_SIZE'], $arFile['CONTENT_TYPE'], $temp_file)) { return CCloudStorage::FILE_PARTLY_UPLOADED; } else { self::$file_skip_reason = 'FAILED_TO_START_UPLOAD'; return CCloudStorage::FILE_SKIPPED; } } else { $temp_file = $obUpload->getTempFileName(); $temp_fileX = $io->GetPhysicalName($temp_file); $fp = fopen($temp_fileX, 'rb'); if (!is_resource($fp)) { self::$file_skip_reason = 'FAILED_TO_READ_SOURCE_FILE'; return CCloudStorage::FILE_SKIPPED; } $pos = $obUpload->GetPos(); if ($pos >= filesize($temp_fileX)) { if ($obUpload->Finish()) { $bucket->IncFileCounter(filesize($temp_fileX)); if ($arFile['HANDLER_ID']) { self::_delete_file($arFile); } else { $ar = CFile::MakeFileArray($arFile['ID']); $fileNameX = $io->GetPhysicalName($ar['tmp_name']); self::_delete_file($fileNameX); } return CCloudStorage::FILE_MOVED; } else { self::$file_skip_reason = 'FAILED_TO_FINISH_UPLOAD'; return CCloudStorage::FILE_SKIPPED; } } fseek($fp, $pos); self::$part_count = $obUpload->GetPartCount(); self::$part_size = $obUpload->getPartSize(); $part = fread($fp, self::$part_size); while ($obUpload->hasRetries()) { if ($obUpload->Next($part)) { return CCloudStorage::FILE_PARTLY_UPLOADED; } } self::$file_skip_reason = 'FAILED_TO_UPLOAD_FILE_CHUNK'; return CCloudStorage::FILE_SKIPPED; } } else { if ($arFile['HANDLER_ID']) { $ar = []; if (!CCloudStorage::OnMakeFileArray($arFile, $ar)) { self::$file_skip_reason = 'FAILED_TO_DOWNLOAD_FILE_3'; return CCloudStorage::FILE_SKIPPED; } if (!isset($ar['tmp_name'])) { self::$file_skip_reason = 'FAILED_TO_DOWNLOAD_FILE_4'; return CCloudStorage::FILE_SKIPPED; } } else { $ar = CFile::MakeFileArray($arFile['ID']); if (!isset($ar['tmp_name'])) { self::$file_skip_reason = 'FAILED_TO_GET_SOURCE_FILE_INFO_2'; return CCloudStorage::FILE_SKIPPED; } } $res = $bucket->SaveFile($filePath, $ar); if ($res) { $bucket->IncFileCounter(filesize($ar['tmp_name'])); if ($arFile['HANDLER_ID']) { self::_delete_file($arFile); } else { self::_delete_file($ar['tmp_name']); } self::$file_skip_reason = 'FAILED_TO_UPLOAD_FILE'; return CCloudStorage::FILE_MOVED; } else { //delete temporary copy if ($arFile['HANDLER_ID']) { self::_delete_file($ar['tmp_name']); } return CCloudStorage::FILE_SKIPPED; } } } public static function OnFileSave(&$arFile, $strFileName, $strSavePath, $bForceMD5 = false, $bSkipExt = false, $dirAdd = '') { if (!$arFile['tmp_name'] && !array_key_exists('content', $arFile)) { return false; } if (array_key_exists('bucket', $arFile)) { $bucket = $arFile['bucket']; } else { $bucket = CCloudStorage::FindBucketForFile($arFile, $strFileName); } if (!is_object($bucket)) { return false; } if (!$bucket->Init()) { return false; } $original = null; $copySize = false; $subDir = ''; $filePath = ''; if (array_key_exists('bucket', $arFile)) { $newName = bx_basename($arFile['tmp_name']); $prefix = $bucket->GetFileSRC('/'); $subDir = mb_substr($arFile['tmp_name'], mb_strlen($prefix)); $subDir = mb_substr($subDir, 0, -mb_strlen($newName) - 1); } else { if (array_key_exists('content', $arFile)) { $arFile['tmp_name'] = CTempFile::GetFileName(bx_basename($arFile['name'])); CheckDirPath($arFile['tmp_name']); $fp = fopen($arFile['tmp_name'], 'ab'); if ($fp) { fwrite($fp, $arFile['content']); fclose($fp); } } if ( !$bForceMD5 && COption::GetOptionString('main', 'save_original_file_name', 'N') == 'Y' ) { if (COption::GetOptionString('main', 'convert_original_file_name', 'Y') == 'Y') { $newName = CCloudStorage::translit($strFileName); } else { $newName = $strFileName; } } else { $strFileExt = ($bSkipExt ? '' : strrchr($strFileName, '.')); $newName = md5(uniqid(mt_rand(), true)) . $strFileExt; } //check for double extension vulnerability $newName = RemoveScriptExtension($newName); $dir_add = $dirAdd; if (empty($dir_add)) { while (true) { $dir_add = md5(mt_rand()); $dir_add = mb_substr($dir_add, 0, 3) . '/' . $dir_add; $subDir = trim(trim($strSavePath, '/') . '/' . $dir_add, '/'); $filePath = '/' . $subDir . '/' . $newName; if (!$bucket->FileExists($filePath)) { break; } } } else { $subDir = trim(trim($strSavePath, '/') . '/' . $dir_add, '/'); $filePath = '/' . $subDir . '/' . $newName; } if (!isset($arFile['external_id'])) { $arFile['external_id'] = md5(mt_rand()); } \Bitrix\Clouds\FileSaveTable::startFileOperation( $bucket->ID ,$subDir ,$newName ,$arFile['external_id'] ); $targetPath = $bucket->GetFileSRC('/'); if (mb_strpos($arFile['tmp_name'], $targetPath) === 0) { $arDbFile = [ 'SUBDIR' => '', 'FILE_NAME' => mb_substr($arFile['tmp_name'], mb_strlen($targetPath)), 'CONTENT_TYPE' => $arFile['type'], ]; //get the file hash $arFile['FILE_HASH'] = ''; if (COption::GetOptionString('main', 'control_file_duplicates', 'N') === 'Y') { $info = $bucket->GetFileInfo('/' . $arDbFile['FILE_NAME']); if ($info) { $arFile['FILE_HASH'] = $info['hash']; $copySize = $info['size']; } } //control of duplicates if ($arFile['FILE_HASH'] <> '') { $original = CFile::FindDuplicate($copySize, $arFile['FILE_HASH'], $bucket->ID); if ($original !== null) { $arFile['original_file'] = $original; } } //copy only if the file is not a duplicate if ($original === null) { $copyPath = $bucket->FileCopy($arDbFile, $filePath); if (!$copyPath) { return false; } if ($copySize === false) { $info = $bucket->GetFileInfo('/' . urldecode(mb_substr($copyPath, mb_strlen($targetPath)))); if ($info) { $copySize = $info['size']; } else { return false; } } } } else { if (!$bucket->SaveFile($filePath, $arFile)) { return false; } //get the file hash $arFile['FILE_HASH'] = ''; $size = 0; if (COption::GetOptionString('main', 'control_file_duplicates', 'N') === 'Y') { $info = $bucket->GetFileInfo($filePath); if ($info) { $arFile['FILE_HASH'] = $info['hash']; $size = $info['size']; } } //control of duplicates if ($arFile['FILE_HASH'] <> '') { $original = CFile::FindDuplicate($size, $arFile['FILE_HASH'], $bucket->ID); if ($original !== null) { $arFile['original_file'] = $original; //we don't need the duplicate anymore $bucket->DeleteFile($filePath); } } } } $arFile['HANDLER_ID'] = $bucket->ID; $arFile['WIDTH'] = 0; $arFile['HEIGHT'] = 0; if ($original === null) { $arFile['SUBDIR'] = $subDir; $arFile['FILE_NAME'] = $newName; } else { //points to the original's physical path $arFile['SUBDIR'] = $original->getFile()->getSubdir(); $arFile['FILE_NAME'] = $original->getFile()->getFileName(); } if (array_key_exists('bucket', $arFile)) { $arFile['WIDTH'] = $arFile['width']; $arFile['HEIGHT'] = $arFile['height']; $arFile['size'] = $arFile['file_size']; } elseif ($copySize !== false) { $arFile['WIDTH'] = $arFile['width']; $arFile['HEIGHT'] = $arFile['height']; $arFile['size'] = $copySize; //if the file is a duplicate we shouldn't increase the size counter if ($original === null) { $bucket->IncFileCounter($copySize); \Bitrix\Clouds\FileSaveTable::setFileSize( $bucket->ID ,$subDir ,$newName ,$copySize ); } } else { //if the file is a duplicate we shouldn't increase the size counter if ($original === null) { $fileSize = filesize($arFile['tmp_name']); $bucket->IncFileCounter($fileSize); \Bitrix\Clouds\FileSaveTable::setFileSize( $bucket->ID ,$subDir ,$newName ,$fileSize ); } $image = new \Bitrix\Main\File\Image($arFile['tmp_name']); $flashEnabled = !CFile::IsImage($arFile['ORIGINAL_NAME'], $arFile['type']); $info = $image->getInfo($flashEnabled); if ($info !== null) { $arFile['WIDTH'] = $info->getWidth(); $arFile['HEIGHT'] = $info->getHeight(); } } if (isset($arFile['old_file'])) { CFile::Delete($arFile['old_file']); } return true; } public static function OnAfterFileSave($arFile) { \Bitrix\Clouds\FileSaveTable::endFileOperation( $arFile['HANDLER_ID'] ,$arFile['SUBDIR'] ,$arFile['FILE_NAME'] ); } public static function OnAfterFileDeleteDuplicate($original, $duplicate) { $result = false; if ($original->getHandlerId() > 0) { $bucket = new CCloudStorageBucket($original->getHandlerId()); if ($bucket->Init()) { $duplicatePath = '/' . $duplicate->getSubdir() . '/' . $duplicate->getFileName(); \Bitrix\Clouds\FileHashTable::deleteByFilePath($original->getHandlerId(), $duplicatePath); $result = $bucket->DeleteFile($duplicatePath, $duplicate->getFileSize()); if ($result) { $bucket->DecFileCounter($duplicate->getFileSize()); } } } return $result; } public static function CleanUp() { $buckets = []; $date = new \Bitrix\Main\Type\DateTime(); $date->add('-1D'); $savedFiles = \Bitrix\Clouds\FileSaveTable::getList([ 'filter' => [ '<TIMESTAMP_X' => $date, ], 'limit' => 100, // ~10 sec ]); while ($saveFile = $savedFiles->fetchObject()) { $dbFile = CFile::GetList([], [ 'EXTERNAL_ID' => $saveFile->getExternalId(), 'SUBDIR' => $saveFile->getSubdir(), 'FILE_NAME' => $saveFile->getFileName(), 'HANDLER_ID' => $saveFile->getBucketId(), ]); if ($dbFile->Fetch()) { $saveFile->delete(); } else { $bucketId = $saveFile->getBucketId(); if (!isset($buckets[$bucketId])) { $buckets[$bucketId] = new \CCloudStorageBucket($bucketId); } $bucket = $buckets[$bucketId]; if ($bucket->Init()) { $filePath = '/' . $saveFile->getSubdir() . '/' . $saveFile->getFileName(); if ($bucket->DeleteFile($filePath)) { $fileSize = $saveFile->getFileSize(); if ($fileSize >= 0) { $bucket->DecFileCounter($fileSize); } } $saveFile->delete(); } } } CCloudStorageUpload::CleanUp(); return 'CCloudStorage::CleanUp();'; } public static function FindBucketByFile($file_name) { foreach (CCloudStorageBucket::GetAllBuckets() as $bucket) { if ($bucket['ACTIVE'] == 'Y') { $obBucket = new CCloudStorageBucket($bucket['ID']); if ($obBucket->Init()) { $prefix = $obBucket->GetFileSRC('/'); if (mb_substr($file_name, 0, mb_strlen($prefix)) === $prefix) { return $obBucket; } } } } return false; } public static function FindFileURIByURN($urn, $log_descr = '') { foreach (CCloudStorageBucket::GetAllBuckets() as $bucket) { if ($bucket['ACTIVE'] == 'Y') { $obBucket = new CCloudStorageBucket($bucket['ID']); if ($obBucket->Init() && $obBucket->FileExists($urn)) { $uri = $obBucket->GetFileSRC($urn); if ($log_descr && COption::GetOptionString('clouds', 'log_404_errors') === 'Y') { CEventLog::Log('WARNING', 'CLOUDS_404', 'clouds', $uri, $log_descr); } return $uri; } } } return ''; } public static function OnBuildGlobalMenu(&$aGlobalMenu, &$aModuleMenu) { global $USER; if (!$USER->CanDoOperation('clouds_browse')) { return; } //When UnRegisterModuleDependences is called from module uninstall //cached EventHandlers may be called if (defined('BX_CLOUDS_UNINSTALLED')) { return; } $aMenu = [ 'parent_menu' => 'global_menu_content', 'section' => 'clouds', 'sort' => 150, 'text' => GetMessage('CLO_STORAGE_MENU'), 'title' => GetMessage('CLO_STORAGE_TITLE'), 'icon' => 'clouds_menu_icon', 'page_icon' => 'clouds_page_icon', 'items_id' => 'menu_clouds', 'items' => [] ]; $rsBuckets = CCloudStorageBucket::GetList(['SORT' => 'DESC', 'ID' => 'ASC']); while ($arBucket = $rsBuckets->Fetch()) { $aMenu['items'][] = [ 'text' => $arBucket['BUCKET'], 'url' => 'clouds_file_list.php?lang=' . LANGUAGE_ID . '&bucket=' . $arBucket['ID'] . '&path=/', 'more_url' => [ 'clouds_file_list.php?bucket=' . $arBucket['ID'], ], 'title' => '', 'page_icon' => 'clouds_page_icon', 'items_id' => 'menu_clouds_bucket_' . $arBucket['ID'], 'module_id' => 'clouds', 'items' => [] ]; } if (!empty($aMenu['items'])) { $aModuleMenu[] = $aMenu; } } public static function OnAdminListDisplay(&$obList) { global $USER; if ($obList->table_id !== 'tbl_fileman_admin') { return; } if (!is_object($USER) || !$USER->CanDoOperation('clouds_upload')) { return; } static $clouds = null; if (!isset($clouds)) { $clouds = []; $rsClouds = CCloudStorageBucket::GetList(['SORT' => 'DESC', 'ID' => 'ASC']); while ($arStorage = $rsClouds->Fetch()) { if ($arStorage['READ_ONLY'] == 'N' && $arStorage['ACTIVE'] == 'Y') { $clouds[$arStorage['ID']] = $arStorage['BUCKET']; } } } if (empty($clouds)) { return; } foreach ($obList->aRows as $obRow) { if ($obRow->arRes['TYPE'] === 'F') { $ID = 'F' . $obRow->arRes['NAME']; $file = $obRow->arRes['NAME']; $path = mb_substr($obRow->arRes['ABS_PATH'], 0, -mb_strlen($file)); $arSubMenu = []; foreach ($clouds as $id => $bucket) { $arSubMenu[] = [ 'TEXT' => $bucket, '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()) . "');" ]; } $obRow->aActions[] = [ 'TEXT' => GetMessage('CLO_STORAGE_UPLOAD_MENU'), 'MENU' => $arSubMenu, ]; } } } public static function HasActiveBuckets() { foreach (CCloudStorageBucket::GetAllBuckets() as $bucket) { if ($bucket['ACTIVE'] === 'Y') { return true; } } return false; } public static function OnBeforeProlog() { if (defined('BX_CHECK_SHORT_URI') && BX_CHECK_SHORT_URI) { $upload_dir = '/' . trim(COption::GetOptionString('main', 'upload_dir', 'upload'), '/') . '/'; $request_uri = rawurldecode($_SERVER['REQUEST_URI']); foreach (CCloudStorageBucket::GetAllBuckets() as $arBucket) { if ($arBucket['ACTIVE'] == 'Y') { $obBucket = new CCloudStorageBucket($arBucket['ID']); if ($obBucket->Init()) { $bucketUrl = $obBucket->GetFileSRC('/'); $bucketPrefix = rtrim(parse_url($bucketUrl, PHP_URL_PATH), '/'); $prefixMatch = $bucketPrefix ? '(?:' . $bucketPrefix . '|)' : ''; $match = []; if ( COption::GetOptionString('clouds', 'delayed_resize') === 'Y' && preg_match('#^' . $prefixMatch . '(/resize_cache/.*$)#', $request_uri, $match) ) { session_write_close(); $to_file = $obBucket->GetFileSRC($match[1], false); if (CCloudStorage::ResizeImageFileCheck($obBucket, $to_file)) { $cache_time = 3600 * 24 * 30; // 30 days header('Cache-Control: max-age=' . $cache_time); header('Expires: ' . gmdate('D, d M Y H:i:s', time() + $cache_time) . ' GMT'); header_remove('Pragma'); LocalRedirect(\Bitrix\Main\Web\Uri::urnEncode($to_file, 'UTF-8'), true, '301 Moved Permanently'); } } elseif ( !preg_match('/[?&]/', $request_uri) && $obBucket->FileExists($request_uri) ) { if (COption::GetOptionString('clouds', 'log_404_errors') === 'Y') { CEventLog::Log('WARNING', 'CLOUDS_404', 'clouds', $_SERVER['REQUEST_URI'], $_SERVER['HTTP_REFERER']); } LocalRedirect($obBucket->GetFileSRC($request_uri), true); } elseif (mb_strpos($request_uri, $upload_dir) === 0) { $check_url = mb_substr($request_uri, mb_strlen($upload_dir) - 1); if ($obBucket->FileExists($check_url)) { if (COption::GetOptionString('clouds', 'log_404_errors') === 'Y') { CEventLog::Log('WARNING', 'CLOUDS_404', 'clouds', $_SERVER['REQUEST_URI'], $_SERVER['HTTP_REFERER']); } LocalRedirect($obBucket->GetFileSRC($check_url), true); } } } } } } } public static function GetAuditTypes() { return [ 'CLOUDS_404' => '[CLOUDS_404] ' . GetMessage('CLO_404_ON_MOVED_FILE'), ]; } public static function translit($file_name, $safe_chars = '') { return CUtil::translit($file_name, LANGUAGE_ID, [ 'safe_chars' => '-. ' . $safe_chars, 'change_case' => false, 'max_len' => 255, ]); } /** * @param array [string]string $arFile * @return void */ public static function FixFileContentType(&$arFile) { global $DB; $fixedContentType = ''; if ($arFile['CONTENT_TYPE'] === 'image/jpg') { $fixedContentType = 'image/jpeg'; } else { $hexContentType = unpack('H*', $arFile['CONTENT_TYPE']); if ( $hexContentType[1] === 'e0f3e4e8ee2f6d706567' || $hexContentType[1] === 'd0b0d183d0b4d0b8d0be2f6d706567' ) { $fixedContentType = 'audio/mpeg'; } } if ($fixedContentType !== '') { $arFile['CONTENT_TYPE'] = $fixedContentType; $DB->Query(" UPDATE b_file SET CONTENT_TYPE = '" . $DB->ForSQL($fixedContentType) . "' WHERE ID = " . intval($arFile['ID']) . ' '); CFile::CleanCache($arFile['ID']); } } }