• Модуль: clouds
  • Путь к файлу: ~/bitrix/modules/clouds/classes/general/storage.php
  • Класс: CCloudStorage
  • Вызов: CCloudStorage::OnFileSave
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 != true
			&& 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 == true? '': 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());
		}

		BitrixCloudsFileSaveTable::startFileOperation(
			$bucket->ID
			,$subDir
			,$newName
			,$arFile["external_id"]
		);

		$targetPath = $bucket->GetFileSRC("/");
		if (mb_strpos($arFile["tmp_name"], $targetPath) === 0)
		{
			$arDbFile = array(
				"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
		{
			$imgArray = CFile::GetImageSize($arFile["tmp_name"], true, false);
			if (is_array($imgArray) && $imgArray[2] == IMAGETYPE_JPEG)
			{
				$exifData = CFile::ExtractImageExif($arFile["tmp_name"]);
				if ($exifData && isset($exifData['Orientation']))
				{
					$properlyOriented = CFile::ImageHandleOrientation($exifData['Orientation'], $arFile["tmp_name"]);
					if ($properlyOriented)
					{
						$jpgQuality = intval(COption::GetOptionString('main', 'image_resize_quality', '95'));
						if ($jpgQuality <= 0 || $jpgQuality > 100)
							$jpgQuality = 95;

						imagejpeg($properlyOriented, $arFile["tmp_name"], $jpgQuality);
						clearstatcache(true, $arFile["tmp_name"]);
					}
					$arFile['size'] = filesize($arFile["tmp_name"]);
				}
			}

			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"] <> '')
			{
				if (is_callable(['CFile', 'lockFileHash']))
				{
					static::$lockId = CFile::lockFileHash($size, $arFile["FILE_HASH"], $bucket->ID);
				}
				$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);
			BitrixCloudsFileSaveTable::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);
			BitrixCloudsFileSaveTable::setFileSize(
				$bucket->ID
				,$subDir
				,$newName
				,$fileSize
			);
		}

		$flashEnabled = !CFile::IsImage($arFile["ORIGINAL_NAME"], $arFile["type"]);
		$imgArray = CFile::GetImageSize($arFile["tmp_name"], true, $flashEnabled);
		if (is_array($imgArray))
		{
			$arFile["WIDTH"] = $imgArray[0];
			$arFile["HEIGHT"] = $imgArray[1];
		}
	}

	if (isset($arFile["old_file"]))
	{
		CFile::Delete($arFile["old_file"]);
	}

	return true;
}