403Webshell
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 :
current_dir [ Writeable] document_root [ Writeable]

 

Command :


[ Back ]     

Current File : /home/bitrix/ext_www/rospirotorg.ru/bitrix/modules/clouds/classes/general/storage_bucket.php
<?php
IncludeModuleLangFile(__FILE__);

/**
 * @property int $ID
 * @property string $ACTIVE
 * @property int $SORT
 * @property string $READ_ONLY
 * @property string $SERVICE_ID
 * @property string $BUCKET
 * @property string $LOCATION
 * @property string $CNAME
 * @property int $FILE_COUNT
 * @property float $FILE_SIZE
 * @property int $LAST_FILE_ID
 * @property string $PREFIX
 * @property string $SETTINGS
 * @property string $FILE_RULES
 */
class CCloudStorageBucket
{
	protected/*.int.*/$_ID = 0;
	protected/*.array[string]string.*/$arBucket;
	protected $enabledFailover = true;
	protected/*.CCloudStorageBucket.*/$failoverBucket;
	protected $queueFlag = true;
	/** @var CCloudStorageService $service */
	protected/*.CCloudStorageService.*/ $service;
	protected static/*.array[int][string]string.*/$arBuckets;

	/**
	 * @param int $ID
	 * @param bool $enabledFailover
	 */
	public function __construct($ID, $enabledFailover = true)
	{
		$this->_ID = intval($ID);
		if (!$enabledFailover)
		{
			$this->disableFailOver();
		}
	}

	public function disableFailOver()
	{
		$this->enabledFailover = false;
	}

	/**
	 * @return bool
	 */
	public function isFailoverEnabled()
	{
		return $this->enabledFailover;
	}

	/**
	 * @param bool $queueFlag
	 */
	public function setQueueFlag($queueFlag = true)
	{
		$this->queueFlag = (bool)$queueFlag;
	}

	/**
	 * @return bool
	 */
	public function getQueueFlag()
	{
		return $this->queueFlag;
	}

	protected function GetActualBucketId()
	{
		if (
			$this->isFailoverEnabled() && CCloudFailover::IsEnabled()
			&& $this->FAILOVER_ACTIVE === 'Y'
			&& $this->FAILOVER_BUCKET_ID > 0
		)
		{
			return $this->FAILOVER_BUCKET_ID;
		}
		else
		{
			return $this->ID;
		}
	}

	/**
	 * @return array[string]string
	*/
	public function getBucketArray()
	{
		if (!isset($this->arBucket))
		{
			self::_init();
			$this->arBucket = self::$arBuckets[$this->_ID];
			if (
				$this->isFailoverEnabled() && CCloudFailover::IsEnabled()
				&& $this->arBucket['FAILOVER_ACTIVE'] === 'Y'
				&& $this->arBucket['FAILOVER_BUCKET_ID'] > 0
			)
			{
				$this->failoverBucket = new CCloudStorageBucket($this->FAILOVER_BUCKET_ID, false);
				if ($this->failoverBucket->Init())
				{
					$this->arBucket['SERVICE_ID'] = $this->failoverBucket->SERVICE_ID;
					$this->arBucket['BUCKET'] = $this->failoverBucket->BUCKET;
					$this->arBucket['LOCATION'] = $this->failoverBucket->LOCATION;
					$this->arBucket['CNAME'] = $this->failoverBucket->CNAME;
					$this->arBucket['PREFIX'] = $this->failoverBucket->PREFIX;
					$this->arBucket['SETTINGS'] = $this->failoverBucket->SETTINGS;
				}
				else
				{
					$this->failoverBucket = null;
				}
			}
		}

		return $this->arBucket;
	}

	/**
	 * @return CCloudStorageService
	*/
	public function getService()
	{
		return $this->service;
	}

	/**
	 * @param string $str
	 * @return string
	*/
	private static function CompileModuleRule($str)
	{
		$res = [];
		$ar = explode(',', $str);
		foreach ($ar as $s)
		{
			$s = trim($s);
			if ($s !== '')
			{
				$res[$s] = preg_quote($s, '/');
			}
		}
		if (!empty($res))
		{
			return '/^(' . implode('|', $res) . ')$/';
		}
		else
		{
			return '';
		}
	}

	/**
	 * @param string $str
	 * @return string
	*/
	private static function CompileExtentionRule($str)
	{
		$res = [];
		$ar = explode(',', $str);
		foreach ($ar as $s)
		{
			$s = trim($s);
			if ($s !== '')
			{
				$res[$s] = preg_quote('.' . $s, '/');
			}
		}
		if (!empty($res))
		{
			return '/(' . implode('|', $res) . ')$/i';
		}
		else
		{
			return '';
		}
	}

	/**
	 * @param string $str
	 * @return float
	*/
	private static function ParseSize($str)
	{
		static $scale = [
			'' => 1.0,
			'K' => 1024.0,
			'M' => 1048576.0,
			'G' => 1073741824.0,
		];
		$str = mb_strtoupper(trim($str));
		if ($str !== '' && preg_match('/([0-9.]+)(|K|M|G)$/', $str, $match) > 0)
		{
			return doubleval($match[1]) * $scale[$match[2]];
		}
		else
		{
			return 0.0;
		}
	}

	/**
	 * @param string $str
	 * @return array[int][int]double
	*/
	private static function CompileSizeRule($str)
	{
		$res = /*.(array[int][int]double).*/[];
		$ar = explode(',', $str);
		foreach ($ar as $s)
		{
			$s = trim($s);
			if ($s !== '')
			{
				$arSize = explode('-', $s);
				if (count($arSize) == 1)
				{
					$res[] = [self::ParseSize($arSize[0]), self::ParseSize($arSize[0])];
				}
				else
				{
					$res[] = [self::ParseSize($arSize[0]), self::ParseSize($arSize[1])];
				}
			}
		}
		return $res;
	}

	/**
	 * @param array[int][string]string $arRules
	 * @return array[int][string]string
	*/
	private static function CompileRules($arRules)
	{
		$arCompiled = /*.(array[int][string]string).*/[];
		if (is_array($arRules))
		{
			foreach ($arRules as $rule)
			{
				if (is_array($rule))
				{
					$arCompiled[] = [
						'MODULE_MASK' => isset($rule['MODULE']) ? self::CompileModuleRule($rule['MODULE']) : '',
						'EXTENTION_MASK' => isset($rule['EXTENSION']) ? self::CompileExtentionRule($rule['EXTENSION']) : '',
						'SIZE_ARRAY' => isset($rule['SIZE']) ? self::CompileSizeRule($rule['SIZE']) : '',
					];
				}
			}
		}
		return $arCompiled;
	}

	/**
	 * @return void
	*/
	private static function _init()
	{
		global $DB, $CACHE_MANAGER;

		if (isset(self::$arBuckets))
		{
			return;
		}

		$cache_id = 'cloud_buckets_v2';
		if (
			CACHED_b_clouds_file_bucket !== false
			&& $CACHE_MANAGER->Read(CACHED_b_clouds_file_bucket, $cache_id, 'b_clouds_file_bucket')
		)
		{
			self::$arBuckets = $CACHE_MANAGER->Get($cache_id);
		}
		else
		{
			self::$arBuckets = /*.(array[int]CCloudStorageBucket).*/[];

			$rs = $DB->Query('
				SELECT *
				FROM b_clouds_file_bucket
				ORDER BY SORT DESC, ID ASC
			');
			while (is_array($ar = $rs->Fetch()))
			{
				if ($ar['FILE_RULES'] != '')
				{
					$arRules = unserialize($ar['FILE_RULES'], ['allowed_classes' => false]);
				}
				else
				{
					$arRules = [];
				}

				$ar['FILE_RULES_COMPILED'] = self::CompileRules($arRules);

				if ($ar['SETTINGS'] != '')
				{
					$arSettings = unserialize($ar['SETTINGS'], ['allowed_classes' => false]);
				}
				else
				{
					$arSettings = [];
				}

				if (is_array($arSettings))
				{
					$ar['SETTINGS'] = $arSettings;
				}
				else
				{
					$ar['SETTINGS'] = [];
				}

				self::$arBuckets[intval($ar['ID'])] = $ar;
			}

			if (CACHED_b_clouds_file_bucket !== false)
			{
				$CACHE_MANAGER->Set($cache_id, self::$arBuckets);
			}
		}
	}

	/**
	 * @param string $name
	 * @return mixed
	*/
	public function __get($name)
	{
		$arBucket = $this->getBucketArray();
		if ($arBucket && array_key_exists($name, $arBucket))
		{
			return $arBucket[$name];
		}
		else
		{
			return null;
		}
	}

	/**
	 * @return bool
	*/
	public function Init()
	{
		if (is_object($this->service))
		{
			return true;
		}
		else
		{
			if ($this->SERVICE_ID)
			{
				$this->service = CCloudStorage::GetServiceByID($this->SERVICE_ID);
			}
			return is_object($this->service);
		}
	}

	/**
	 * @return bool
	*/
	public function RenewToken()
	{
		if ($this->service->tokenHasExpired)
		{
			$arBucket = $this->failoverBucket ? $this->failoverBucket->arBucket : $this->arBucket;
			$newSettings = false;
			foreach (GetModuleEvents('clouds', 'OnExpiredToken', true) as $arEvent)
			{
				$newSettings = ExecuteModuleEventEx($arEvent, [$arBucket]);
				if ($newSettings)
				{
					break;
				}
			}

			if ($newSettings)
			{
				if ($this->failoverBucket)
				{
					$updateResult = $this->failoverBucket->Update(['SETTINGS' => $newSettings]);
					$this->arBucket = null;
				}
				else
				{
					$updateResult = $this->Update(['SETTINGS' => $newSettings]);
				}

				if ($updateResult)
				{
					$this->service->tokenHasExpired = false;
					return true;
				}
			}
		}

		return false;
	}

	/**
	 * @param array[string]string $arSettings
	 * @return bool
	*/
	public function CheckSettings(&$arSettings)
	{
		return $this->service->CheckSettings($this->arBucket, $arSettings);
	}

	/**
	 * @return bool
	*/
	public function CreateBucket()
	{
		return $this->service->CreateBucket($this->arBucket);
	}

	/**
	 * @param mixed $arFile
	 * @param bool $encoded
	 * @return string
	*/
	public function GetFileSRC($arFile, $encoded = true)
	{
		if (is_array($arFile) && isset($arFile['URN']))
		{
			return $this->service->GetFileSRC($this->arBucket, $arFile['URN'], $encoded);
		}
		else
		{
			return preg_replace("'(?<!:)/+'s", '/', $this->service->GetFileSRC($this->arBucket, $arFile, $encoded));
		}
	}

	/**
	 * @param string $filePath
	 * @return bool
	*/
	public function FileExists($filePath)
	{
		$result = $this->service->FileExists($this->arBucket, $filePath);
		if (!$result && $this->RenewToken())
		{
			$result = $this->service->FileExists($this->getBucketArray(), $filePath);
		}
		return $result;
	}

	/**
	 * @param mixed $arFile
	 * @param string $filePath
	 * @return bool
	*/
	public function DownloadToFile($arFile, $filePath)
	{
		$result = $this->service->DownloadToFile($this->arBucket, $arFile, $filePath);
		return $result;
	}

	/**
	 * @param string $filePath
	 * @param mixed $arFile
	 * @return bool
	*/
	public function SaveFile($filePath, $arFile)
	{
		$result = $this->service->SaveFile($this->arBucket, $filePath, $arFile);
		if (!$result && $this->RenewToken())
		{
			$result = $this->service->SaveFile($this->getBucketArray(), $filePath, $arFile);
		}

		if ($result)
		{
			if ($this->queueFlag)
			{
				CCloudFailover::queueCopy($this, $filePath);
			}

			foreach (GetModuleEvents('clouds', 'OnAfterSaveFile', true) as $arEvent)
			{
				ExecuteModuleEventEx($arEvent, [$this, $arFile, $filePath]);
			}
		}
		return $result;
	}

	/**
	 * @param string $filePath
	 * @return bool
	*/
	public function DeleteFile($filePath, $fileSize = null)
	{
		$result = $this->service->DeleteFile($this->arBucket, $filePath);
		if (!$result && $this->RenewToken())
		{
			$result = $this->service->DeleteFile($this->getBucketArray(), $filePath);
		}

		if ($result)
		{
			if ($this->queueFlag)
			{
				CCloudFailover::queueDelete($this, $filePath);
			}

			$eventData = [
				'del' => 'Y',
				'size' => $fileSize,
			];
			foreach (GetModuleEvents('clouds', 'OnAfterDeleteFile', true) as $arEvent)
			{
				ExecuteModuleEventEx($arEvent, [$this, $eventData, $filePath]);
			}
		}
		return $result;
	}

	/**
	 * @param mixed $arFile
	 * @param string $filePath
	 * @return bool
	*/
	public function FileCopy($arFile, $filePath)
	{
		$result = $this->service->FileCopy($this->arBucket, $arFile, $filePath);
		if (!$result && $this->RenewToken())
		{
			$result = $this->service->FileCopy($this->getBucketArray(), $arFile, $filePath);
		}

		if ($result)
		{
			if ($this->queueFlag)
			{
				CCloudFailover::queueCopy($this, $filePath);
			}

			foreach (GetModuleEvents('clouds', 'OnAfterCopyFile', true) as $arEvent)
			{
				ExecuteModuleEventEx($arEvent, [$this, $arFile, $filePath]);
			}
		}
		return $result;
	}

	/**
	 * @param string $sourcePath
	 * @param string $targetPath
	 * @param bool $overwrite
	 * @return bool
	*/
	public function FileRename($sourcePath, $targetPath, $overwrite = true)
	{
		$result = $this->service->FileRename($this->arBucket, $sourcePath, $targetPath, $overwrite);
		if ($result)
		{
			if ($this->queueFlag)
			{
				CCloudFailover::queueRename($this, $sourcePath, $targetPath);
			}

			foreach (GetModuleEvents('clouds', 'OnAfterRenameFile', true) as $arEvent)
			{
				ExecuteModuleEventEx($arEvent, [$this, $sourcePath, $targetPath]);
			}
		}
		return $result;
	}

	/**
	 * @param string $filePath
	 * @param bool $bRecursive
	 * @param int $pageSize
	 * @param string $pageMarker
	 * @return array[string][int]string
	*/
	public function ListFiles($filePath = '/', $bRecursive = false, $pageSize = 0, $pageMarker = '')
	{
		$result = $this->service->ListFiles($this->arBucket, $filePath, $bRecursive, $pageSize, $pageMarker);
		if (!$result && $this->RenewToken())
		{
			$result = $this->service->ListFiles($this->getBucketArray(), $filePath, $bRecursive, $pageSize, $pageMarker);
		}
		return $result;
	}

	/**
	 * @param string $filePath
	 * @return array|false
	*/
	public function GetFileInfo($filePath)
	{
		$DIR_NAME = mb_substr($filePath, 0, mb_strrpos($filePath, '/') + 1);
		$FILE_NAME = mb_substr($filePath, mb_strlen($DIR_NAME));

		$arFileInfo = $this->service->GetFileInfo($this->arBucket, $filePath);
		if ($arFileInfo === false && $this->RenewToken())
		{
			$arFileInfo = $this->service->GetFileInfo($this->getBucketArray(), $filePath);
		}

		if ($arFileInfo === null)
		{
			$arListing = $this->service->ListFiles($this->arBucket, $DIR_NAME, false);
			if (is_array($arListing))
			{
				foreach ($arListing['file'] as $i => $name)
				{
					if ($name === $FILE_NAME)
					{
						return [
							'name' => $name,
							'size' => $arListing['file_size'][$i],
							'mtime' => $arListing['file_mtime'][$i],
							'hash' => $arListing['file_hash'][$i],
						];
					}
				}
			}
		}
		elseif ($arFileInfo)
		{
			$arFileInfo['name'] = $FILE_NAME;
			return $arFileInfo;
		}
		return false;
	}

	/**
	 * @param string $filePath
	 * @return float
	*/
	public function GetFileSize($filePath)
	{
		$fileInfo = $this->GetFileInfo($filePath);
		if ($fileInfo)
		{
			return doubleval($fileInfo['size']);
		}
		else
		{
			return 0.0;
		}
	}

	/**
	 * @return array[int][string]string
	*/
	public static function GetAllBuckets()
	{
		self::_init();
		return self::$arBuckets;
	}

	/**
	 * @param array[string]string $arFields
	 * @param int $ID
	 * @return bool
	*/
	public function CheckFields(&$arFields, $ID)
	{
		global $APPLICATION;
		$aMsg = [];

		if (array_key_exists('ACTIVE', $arFields))
		{
			$arFields['ACTIVE'] = $arFields['ACTIVE'] === 'N' ? 'N' : 'Y';
		}

		if (array_key_exists('READ_ONLY', $arFields))
		{
			$arFields['READ_ONLY'] = $arFields['READ_ONLY'] === 'Y' ? 'Y' : 'N';
		}

		$arServices = CCloudStorage::GetServiceList();
		if (isset($arFields['SERVICE_ID']))
		{
			if (!array_key_exists($arFields['SERVICE_ID'], $arServices))
			{
				$aMsg[] = ['id' => 'SERVICE_ID', 'text' => GetMessage('CLO_STORAGE_WRONG_SERVICE')];
			}
		}

		if (isset($arFields['BUCKET']))
		{
			$arFields['BUCKET'] = trim($arFields['BUCKET']);

			$bBadLength = false;
			if (mb_strpos($arFields['BUCKET'], '.') !== false)
			{
				$arName = explode('.', $arFields['BUCKET']);
				$bBadLength = false;
				foreach ($arName as $str)
				{
					if (mb_strlen($str) < 2 || mb_strlen($str) > 63)
					{
						$bBadLength = true;
					}
				}
			}

			if ($arFields['BUCKET'] == '')
			{
				$aMsg[] = ['id' => 'BUCKET', 'text' => GetMessage('CLO_STORAGE_EMPTY_BUCKET')];
			}
			if (preg_match('/[^a-z0-9._-]/', $arFields['BUCKET']) > 0)
			{
				$aMsg[] = ['id' => 'BUCKET', 'text' => GetMessage('CLO_STORAGE_BAD_BUCKET_NAME')];
			}
			if (mb_strlen($arFields['BUCKET']) < 2 || mb_strlen($arFields['BUCKET']) > 63)
			{
				$aMsg[] = ['id' => 'BUCKET', 'text' => GetMessage('CLO_STORAGE_WRONG_BUCKET_NAME_LENGTH')];
			}
			if ($bBadLength)
			{
				$aMsg[] = ['id' => 'BUCKET', 'text' => GetMessage('CLO_STORAGE_WRONG_BUCKET_NAME_LENGTH2')];
			}
			if (!preg_match('/^[a-z0-9].*[a-z0-9]$/', $arFields['BUCKET']))
			{
				$aMsg[] = ['id' => 'BUCKET', 'text' => GetMessage('CLO_STORAGE_BAD_BUCKET_NAME2')];
			}
			if (preg_match('/(-\\.|\\.-)/', $arFields['BUCKET']) > 0)
			{
				$aMsg[] = ['id' => 'BUCKET', 'text' => GetMessage('CLO_STORAGE_BAD_BUCKET_NAME3')];
			}

			if ($arFields['BUCKET'] <> '')
			{
				$rsBucket = self::GetList([], [
					'=SERVICE_ID' => $arFields['SERVICE_ID'],
					'=BUCKET' => $arFields['BUCKET'],
				]);
				$arBucket = $rsBucket->Fetch();
				if (is_array($arBucket) && $arBucket['ID'] != $ID)
				{
					$aMsg[] = ['id' => 'BUCKET', 'text' => GetMessage('CLO_STORAGE_BUCKET_ALREADY_EXISTS')];
				}
			}
		}

		if (array_key_exists('FAILOVER_ACTIVE', $arFields))
		{
			$arFields['FAILOVER_ACTIVE'] = $arFields['FAILOVER_ACTIVE'] === 'Y' ? 'Y' : 'N';
		}

		if (isset($arFields['FAILOVER_BUCKET_ID']) && $arFields['FAILOVER_BUCKET_ID'] == $ID)
		{
			unset($arFields['FAILOVER_BUCKET_ID']);
		}

		if (array_key_exists('FAILOVER_COPY', $arFields))
		{
			$arFields['FAILOVER_COPY'] = $arFields['FAILOVER_COPY'] === 'Y' ? 'Y' : 'N';
		}

		if (array_key_exists('FAILOVER_DELETE', $arFields))
		{
			$arFields['FAILOVER_DELETE'] = $arFields['FAILOVER_DELETE'] === 'Y' ? 'Y' : 'N';
		}

		if (array_key_exists('FAILOVER_DELETE_DELAY', $arFields))
		{
			$arFields['FAILOVER_DELETE_DELAY'] = (int)$arFields['FAILOVER_DELETE_DELAY'];
		}

		if (array_key_exists('CNAME', $arFields))
		{
			$arFields['CNAME'] = preg_replace('#^https?://#i', '', $arFields['CNAME']);
		}

		if (!empty($aMsg))
		{
			$e = new CAdminException($aMsg);
			$APPLICATION->ThrowException($e);
			return false;
		}
		return true;
	}

	/**
	 * @param array[string]string $arOrder
	 * @param array[string]string $arFilter
	 * @param array[string]string $arSelect
	 * @return CDBResult
	*/
	public static function GetList($arOrder=[], $arFilter=[], $arSelect=[])
	{
		global $DB;

		if (!is_array($arSelect))
		{
			$arSelect = /*.(array[string]string).*/[];
		}
		if (count($arSelect) < 1)
		{
			$arSelect = [
				'ID',
				'ACTIVE',
				'READ_ONLY',
				'SORT',
				'SERVICE_ID',
				'LOCATION',
				'BUCKET',
				'SETTINGS',
				'CNAME',
				'PREFIX',
				'FILE_COUNT',
				'FILE_SIZE',
				'LAST_FILE_ID',
				'FILE_RULES',
				'FAILOVER_ACTIVE',
				'FAILOVER_BUCKET_ID',
				'FAILOVER_COPY',
				'FAILOVER_DELETE',
				'FAILOVER_DELETE_DELAY',
			];
		}

		if (!is_array($arOrder))
		{
			$arOrder = /*.(array[string]string).*/[];
		}

		$arQueryOrder = [];
		foreach ($arOrder as $strColumn => $strDirection)
		{
			$strColumn = mb_strtoupper($strColumn);
			$strDirection = mb_strtoupper($strDirection) === 'ASC' ? 'ASC' : 'DESC';
			switch ($strColumn)
			{
				case 'ID':
				case 'SORT':
					$arSelect[] = $strColumn;
					$arQueryOrder[$strColumn] = $strColumn . ' ' . $strDirection;
					break;
				default:
					break;
			}
		}

		$arQuerySelect = [];
		foreach ($arSelect as $strColumn)
		{
			$strColumn = mb_strtoupper($strColumn);
			switch ($strColumn)
			{
				case 'ID':
				case 'ACTIVE':
				case 'READ_ONLY':
				case 'SORT':
				case 'SERVICE_ID':
				case 'LOCATION':
				case 'BUCKET':
				case 'SETTINGS':
				case 'CNAME':
				case 'PREFIX':
				case 'FILE_COUNT':
				case 'FILE_SIZE':
				case 'LAST_FILE_ID':
				case 'FILE_RULES':
				case 'FAILOVER_ACTIVE':
				case 'FAILOVER_BUCKET_ID':
				case 'FAILOVER_COPY':
				case 'FAILOVER_DELETE':
				case 'FAILOVER_DELETE_DELAY':
					$arQuerySelect[$strColumn] = 's.' . $strColumn;
					break;
			}
		}
		if (count($arQuerySelect) < 1)
		{
			$arQuerySelect = ['ID' => 's.ID'];
		}

		$obQueryWhere = new CSQLWhere;
		$arFields = [
			'ID' => [
				'TABLE_ALIAS' => 's',
				'FIELD_NAME' => 's.ID',
				'FIELD_TYPE' => 'int',
			],
			'ACTIVE' => [
				'TABLE_ALIAS' => 's',
				'FIELD_NAME' => 's.ACTIVE',
				'FIELD_TYPE' => 'string',
			],
			'READ_ONLY' => [
				'TABLE_ALIAS' => 's',
				'FIELD_NAME' => 's.READ_ONLY',
				'FIELD_TYPE' => 'string',
			],
			'SERVICE_ID' => [
				'TABLE_ALIAS' => 's',
				'FIELD_NAME' => 's.SERVICE_ID',
				'FIELD_TYPE' => 'string',
			],
			'BUCKET' => [
				'TABLE_ALIAS' => 's',
				'FIELD_NAME' => 's.BUCKET',
				'FIELD_TYPE' => 'string',
			],
			'FAILOVER_ACTIVE' => [
				'TABLE_ALIAS' => 's',
				'FIELD_NAME' => 's.FAILOVER_ACTIVE',
				'FIELD_TYPE' => 'string',
			],
			'FAILOVER_BUCKET_ID' => [
				'TABLE_ALIAS' => 's',
				'FIELD_NAME' => 's.FAILOVER_BUCKET_ID',
				'FIELD_TYPE' => 'int',
			],
			'FAILOVER_COPY' => [
				'TABLE_ALIAS' => 's',
				'FIELD_NAME' => 's.FAILOVER_COPY',
				'FIELD_TYPE' => 'string',
			],
			'FAILOVER_DELETE' => [
				'TABLE_ALIAS' => 's',
				'FIELD_NAME' => 's.FAILOVER_DELETE',
				'FIELD_TYPE' => 'string',
			],
			'FAILOVER_DELETE_DELAY' => [
				'TABLE_ALIAS' => 's',
				'FIELD_NAME' => 's.FAILOVER_DELETE_DELAY',
				'FIELD_TYPE' => 'int',
			],
		];
		$obQueryWhere->SetFields($arFields);

		if (!is_array($arFilter))
		{
			$arFilter = /*.(array[string]string).*/[];
		}
		$strQueryWhere = $obQueryWhere->GetQuery($arFilter);

		$bDistinct = $obQueryWhere->bDistinctReqired;

		$strSql = '
			SELECT ' . ($bDistinct ? 'DISTINCT' : '') . '
			' . implode(', ', $arQuerySelect) . '
			FROM
				b_clouds_file_bucket s
			' . $obQueryWhere->GetJoins() . '
		';

		if ($strQueryWhere !== '')
		{
			$strSql .= '
				WHERE
				' . $strQueryWhere . '
			';
		}

		if (count($arQueryOrder) > 0)
		{
			$strSql .= '
				ORDER BY
				' . implode(', ', $arQueryOrder) . '
			';
		}

		return $DB->Query($strSql);
	}

	/**
	 * @param array[string]string $arFields
	 * @param bool $createBucket
	 * @return mixed
	*/
	public function Add($arFields, $createBucket = true)
	{
		global $DB, $APPLICATION, $CACHE_MANAGER;
		$strError = '';
		$this->_ID = 0;

		if (!$this->CheckFields($arFields, 0))
		{
			return false;
		}

		$arFields['FILE_COUNT'] = 0;
		if (is_array($arFields['FILE_RULES']))
		{
			$arFields['FILE_RULES'] = serialize($arFields['FILE_RULES']);
		}
		else
		{
			$arFields['FILE_RULES'] = false;
		}

		$this->arBucket = $arFields;
		if ($this->Init())
		{
			if (!$this->CheckSettings($arFields['SETTINGS']))
			{
				return false;
			}
			$this->arBucket['SETTINGS'] = $arFields['SETTINGS'];

			if ($createBucket)
			{
				$creationResult = $this->CreateBucket();
			}
			else
			{
				$creationResult = true;
			}

			if ($creationResult)
			{
				$arFields['SETTINGS'] = serialize($arFields['SETTINGS']);
				$this->_ID = $DB->Add('b_clouds_file_bucket', $arFields);
				self::$arBuckets = null;
				$this->arBucket = null;
				if (CACHED_b_clouds_file_bucket !== false)
				{
					$CACHE_MANAGER->CleanDir('b_clouds_file_bucket');
				}
				return $this->_ID;
			}
			else
			{
				$e = $APPLICATION->GetException();
				if (is_object($e))
				{
					$strError = GetMessage('CLO_STORAGE_CLOUD_ADD_ERROR', ['#error_msg#' => $e->GetString()]);
				}
				else
				{
					$strError = GetMessage('CLO_STORAGE_CLOUD_ADD_ERROR', ['#error_msg#' => 'CSB42343']);
				}
			}
		}
		else
		{
			$strError = GetMessage('CLO_STORAGE_CLOUD_ADD_ERROR', ['#error_msg#' => GetMessage('CLO_STORAGE_UNKNOWN_SERVICE')]);
		}

		$APPLICATION->ResetException();
		$e = new CApplicationException($strError);
		$APPLICATION->ThrowException($e);
		return false;
	}

	/**
	 * @return bool
	*/
	public function Delete()
	{
		global $DB, $APPLICATION, $CACHE_MANAGER;
		$strError = '';

		if ($this->Init())
		{
			$isEmptyBucket = $this->service->IsEmptyBucket($this->arBucket);
			$forceDeleteTry = false;
			if (!$isEmptyBucket && is_object($APPLICATION->GetException()))
			{
				// The bucket was created within wrong s3 region
				if (
					$this->service->GetLastRequestStatus() == 301
					&& $this->service->GetLastRequestHeader('x-amz-bucket-region') !== ''
				)
				{
					$forceDeleteTry = true;
				}
			}

			if ($isEmptyBucket || $forceDeleteTry)
			{
				$isDeleted = $this->service->DeleteBucket($this->arBucket);
				$forceDelete = false;
				if (!$isDeleted && is_object($APPLICATION->GetException()))
				{
					// The bucket was created within wrong s3 region
					if (
						$this->service->GetLastRequestStatus() == 301
						&& $this->service->GetLastRequestHeader('x-amz-bucket-region') !== ''
					)
					{
						$forceDelete = true;
					}
				}

				if ($isDeleted || $forceDelete)
				{
					$res = $DB->Query('DELETE FROM b_clouds_file_bucket WHERE ID = ' . $this->_ID);
					if (CACHED_b_clouds_file_bucket !== false)
					{
						$CACHE_MANAGER->CleanDir('b_clouds_file_bucket');
					}
					if (is_object($res))
					{
						$this->arBucket = null;
						$this->_ID = 0;
						return true;
					}
					else
					{
						$strError = GetMessage('CLO_STORAGE_DB_DELETE_ERROR');
					}
				}
				else
				{
					$e = $APPLICATION->GetException();
					$strError = GetMessage('CLO_STORAGE_CLOUD_DELETE_ERROR', ['#error_msg#' => is_object($e) ? $e->GetString() : '']);
				}
			}
			else
			{
				$e = $APPLICATION->GetException();
				if (is_object($e))
				{
					$strError = GetMessage('CLO_STORAGE_CLOUD_DELETE_ERROR', ['#error_msg#' => $e->GetString()]);
				}
				else
				{
					$strError = GetMessage('CLO_STORAGE_CLOUD_BUCKET_NOT_EMPTY');
				}
			}
		}
		else
		{
			$strError = GetMessage('CLO_STORAGE_CLOUD_DELETE_ERROR', ['#error_msg#' => GetMessage('CLO_STORAGE_UNKNOWN_SERVICE')]);
		}

		$APPLICATION->ResetException();
		$e = new CApplicationException($strError);
		$APPLICATION->ThrowException($e);
		return false;
	}

	/**
	 * @param array[string]string $arFields
	 * @return mixed
	*/
	public function Update($arFields)
	{
		global $DB, $CACHE_MANAGER;

		if ($this->_ID <= 0)
		{
			return false;
		}

		unset($arFields['FILE_COUNT']);
		unset($arFields['SERVICE_ID']);
		unset($arFields['LOCATION']);
		unset($arFields['BUCKET']);

		if (
			array_key_exists('SETTINGS', $arFields)
			&& is_array($arFields['SETTINGS'])
			&& isset($arFields['SETTINGS']['MIGRATE_TO'])
			&& $arFields['SETTINGS']['MIGRATE_TO']
		)
		{
			$this->SERVICE_ID = $arFields['SERVICE_ID'] = $arFields['SETTINGS']['MIGRATE_TO'];
		}

		$this->service = CCloudStorage::GetServiceByID($this->SERVICE_ID);
		if (!is_object($this->service))
		{
			return false;
		}

		if (!$this->CheckFields($arFields, $this->_ID))
		{
			return false;
		}

		if (array_key_exists('FILE_RULES', $arFields))
		{
			if (is_array($arFields['FILE_RULES']))
			{
				$arFields['FILE_RULES'] = serialize($arFields['FILE_RULES']);
			}
			else
			{
				$arFields['FILE_RULES'] = false;
			}
		}

		if (array_key_exists('SETTINGS', $arFields))
		{
			if (!$this->CheckSettings($arFields['SETTINGS']))
			{
				return false;
			}
			$arFields['SETTINGS'] = serialize($arFields['SETTINGS']);
		}

		$strUpdate = $DB->PrepareUpdate('b_clouds_file_bucket', $arFields);
		if ($strUpdate <> '')
		{
			$strSql = '
				UPDATE b_clouds_file_bucket SET
				' . $strUpdate . '
				WHERE ID = ' . $this->_ID . '
			';
			if (!is_object($DB->Query($strSql)))
			{
				return false;
			}
		}

		self::$arBuckets = null;
		$this->arBucket = null;
		if (CACHED_b_clouds_file_bucket !== false)
		{
			$CACHE_MANAGER->CleanDir('b_clouds_file_bucket');
		}

		return $this->_ID;
	}

	/**
	 * @param array[string][int]string $arPOST
	 * @return array[int][string]string
	*/
	public static function ConvertPOST($arPOST)
	{
		$arRules = /*.(array[int][string]string).*/[];

		if (isset($arPOST['MODULE']) && is_array($arPOST['MODULE']))
		{
			foreach ($arPOST['MODULE'] as $i => $MODULE)
			{
				if (!isset($arRules[intval($i)]))
				{
					$arRules[intval($i)] = ['MODULE' => '', 'EXTENSION' => '', 'SIZE' => ''];
				}
				$arRules[intval($i)]['MODULE'] = $MODULE;
			}
		}

		if (isset($arPOST['EXTENSION']) && is_array($arPOST['EXTENSION']))
		{
			foreach ($arPOST['EXTENSION'] as $i => $EXTENSION)
			{
				if (!isset($arRules[intval($i)]))
				{
					$arRules[intval($i)] = ['MODULE' => '', 'EXTENSION' => '', 'SIZE' => ''];
				}
				$arRules[intval($i)]['EXTENSION'] = $EXTENSION;
			}
		}

		if (isset($arPOST['SIZE']) && is_array($arPOST['SIZE']))
		{
			foreach ($arPOST['SIZE'] as $i => $SIZE)
			{
				if (!isset($arRules[intval($i)]))
				{
					$arRules[intval($i)] = ['MODULE' => '', 'EXTENSION' => '', 'SIZE' => ''];
				}
				$arRules[intval($i)]['SIZE'] = $SIZE;
			}
		}

		return $arRules;
	}

	/**
	 * @param string $name
	 * @param string $value
	 * @return void
	*/
	public function setHeader($name, $value)
	{
		$this->service->SetHeader($name, $value);
	}

	/**
	 * @param float $file_size
	 * @param int $file_count
	 * @return CDBResult
	*/
	public function SetFileCounter($file_size, $file_count)
	{
		global $DB, $CACHE_MANAGER;
		$res = $DB->Query('
			UPDATE b_clouds_file_bucket
			SET FILE_COUNT = ' . intval($file_count) . '
			,FILE_SIZE = ' . roundDB($file_size) . '
			WHERE ID = ' . $this->GetActualBucketId() . '
		');

		if (CACHED_b_clouds_file_bucket !== false)
		{
			$CACHE_MANAGER->CleanDir('b_clouds_file_bucket');
		}
		return $res;
	}

	protected static $applyFileCounterJobAdded = false;

	/**
	 * @param float $file_size
	 * @return CDBResult
	*/
	public function IncFileCounter($file_size = 0.0)
	{
		global $DB;

		$res = $DB->Query('
			INSERT INTO b_clouds_size_queue (BUCKET_ID, FILE_COUNT, FILE_SIZE)
			VALUES (' . $this->GetActualBucketId() . ', 1, ' . roundDB($file_size) . ')
		');

		if (defined('BX_CLOUDS_COUNTERS_DEBUG'))
		{
			\CCloudsDebug::getInstance()->endAction();
		}

		if (!static::$applyFileCounterJobAdded)
		{
			static::$applyFileCounterJobAdded = true;
			\Bitrix\Main\Application::getInstance()->addBackgroundJob([__CLASS__, 'ApplyFileCounter'], [], \Bitrix\Main\Application::JOB_PRIORITY_NORMAL);
		}

		return $res;
	}

	/**
	 * @param float $file_size
	 * @return CDBResult
	*/
	public function DecFileCounter($file_size = 0.0)
	{
		global $DB;

		$res = $DB->Query('
			INSERT INTO b_clouds_size_queue (BUCKET_ID, FILE_COUNT, FILE_SIZE)
			VALUES (' . $this->GetActualBucketId() . ', -1, ' . roundDB($file_size) . ')
		');

		if (defined('BX_CLOUDS_COUNTERS_DEBUG'))
		{
			\CCloudsDebug::getInstance()->endAction();
		}

		if (!static::$applyFileCounterJobAdded)
		{
			static::$applyFileCounterJobAdded = true;
			\Bitrix\Main\Application::getInstance()->addBackgroundJob([__CLASS__, 'ApplyFileCounter'], [], \Bitrix\Main\Application::JOB_PRIORITY_NORMAL);
		}

		return $res;
	}

	/**
	 * @return void
	*/
	public static function ApplyFileCounter()
	{
		global $DB, $CACHE_MANAGER;

		$connection = \Bitrix\Main\Application::getConnection();
		if ($connection->lock('CCloudStorageBucket::ApplyFileCounter'))
		{
			$res = $DB->Query('SELECT * FROM b_clouds_size_queue ORDER BY ID');
			$c = 0;
			while ($job = $res->Fetch())
			{
				if ($job['FILE_COUNT'] > 0)
				{
					$DB->Query('
						UPDATE b_clouds_file_bucket
						SET FILE_COUNT = FILE_COUNT + 1
						,FILE_SIZE = FILE_SIZE + ' . $job['FILE_SIZE'] . '
						WHERE ID = ' . $job['BUCKET_ID'] . '
					');
					$c++;

					COption::SetOptionString('main_size', '~cloud', intval(COption::GetOptionString('main_size', '~cloud')) + $job['FILE_SIZE']);
				}
				elseif ($job['FILE_COUNT'] < 0)
				{
					$DB->Query('
						UPDATE b_clouds_file_bucket
						SET FILE_COUNT = case when FILE_COUNT - 1 > 0 then FILE_COUNT - 1 else 0 end
						,FILE_SIZE = case when FILE_SIZE - ' . $job['FILE_SIZE'] . ' > 0 then FILE_SIZE - ' . $job['FILE_SIZE'] . ' else 0 end
						WHERE ID = ' . $job['BUCKET_ID'] . '
					');
					$c++;

					COption::SetOptionString('main_size', '~cloud', intval(COption::GetOptionString('main_size', '~cloud')) - $job['FILE_SIZE']);
				}

				$DB->Query('DELETE FROM b_clouds_size_queue WHERE ID = ' . $job['ID']);
			}

			if ($c > 0 && CACHED_b_clouds_file_bucket !== false)
			{
				$CACHE_MANAGER->CleanDir('b_clouds_file_bucket');
			}

			$connection->unlock('CCloudStorageBucket::ApplyFileCounter');
		}
	}
}

Youez - 2016 - github.com/yon3zu
LinuXploit