Your IP : 18.217.128.191


Current Path : /var/www/www-root/data/www/monolith-realty.ru/bitrix/modules/main/lib/ui/uploader/
Upload File :
Current File : /var/www/www-root/data/www/monolith-realty.ru/bitrix/modules/main/lib/ui/uploader/uploader.php

<?
namespace Bitrix\Main\UI\Uploader;
use Bitrix\Main\AccessDeniedException;
use Bitrix\Main\ArgumentOutOfRangeException;
use Bitrix\Main\HttpRequest;
use Bitrix\Main\NotImplementedException;
use \Bitrix\Main\UI\FileInputUtility;
use \Bitrix\Main\Web\Json;
use \Bitrix\Main\Context;
use \Bitrix\Main\Loader;
use \Bitrix\Main\Localization\Loc;
use \Bitrix\Main;
Loc::loadMessages(__FILE__);
Loader::registerAutoLoadClasses(
	"main",
	array(
		"bitrix\\main\\ui\\uploader\\storage" => "lib/ui/uploader/storage.php",
		"bitrix\\main\\ui\\uploader\\cloudstorage" => "lib/ui/uploader/storage.php"
	));

class Log implements \ArrayAccess
{
	/*
	 * @var \CBXVirtualFileFileSystem $file
	 */
	protected $file = null;
	var $data = array();

	/**
	 * Log constructor.
	 * @param string $path Path to log file.
	 * @return void
	 */
	function __construct($path)
	{
		try
		{
			$this->file = \CBXVirtualIo::GetInstance()->GetFile($path);

			if ($this->file->IsExists())
			{
				$data = unserialize($this->file->GetContents(), ["allowed_classes" => false]);
				foreach($data as $key => $val)
				{
					if (array_key_exists($key , $this->data) && is_array($this->data[$key]) && is_array($val))
						$this->data[$key] = array_merge($this->data[$key], $val);
					else
						$this->data[$key] = $val;
				}
			}
		}
		catch (\Throwable $e)
		{
			throw new Main\SystemException("Temporary file has wrong structure.", "BXU351.01");
		}
	}

	/**
	 * Saves log.
	 * @param string $key Key of log array.
	 * @param mixed $value value of log array.
	 * @return $this
	 */
	public function setLog($key, $value)
	{
		if (array_key_exists($key, $this->data) && is_array($this->data) && is_array($value))
			$this->data[$key] = array_merge($this->data[$key], $value);
		else
			$this->data[$key] = $value;
		$this->save();

		return $this;
	}

	/**
	 * @param $key
	 * @return mixed
	 */
	public function getValue($key)
	{
		return $this->data[$key];
	}

	/**
	 *
	 */
	public function save()
	{
		try
		{
			$this->file->PutContents(serialize($this->data));
		}
		catch (\Throwable $e)
		{
			throw new Main\SystemException("Temporary file was not saved.", "BXU351.02");
		}
	}

	/**
	 * @return array
	 */
	public function getLog()
	{
		return $this->data;
	}

	/**
	 *
	 */
	public function unlink()
	{
		try
		{
			if ($this->file instanceof \CBXVirtualFileFileSystem && $this->file->IsExists())
				$this->file->unlink();
		}
		catch (\Throwable $e)
		{
			throw new Main\SystemException("Temporary file was not deleted.", "BXU351.03");
		}
	}

	/**
	 * @param mixed $offset
	 * @return bool
	 */
	public function offsetExists($offset): bool
	{
		return array_key_exists($offset, $this->data);
	}

	/**
	 * @param mixed $offset
	 * @return mixed|null
	 */
	#[\ReturnTypeWillChange]
	public function offsetGet($offset)
	{
		if (array_key_exists($offset, $this->data))
			return $this->data[$offset];
		return null;
	}

	/**
	 * @param mixed $offset
	 * @param mixed $value
	 */
	public function offsetSet($offset, $value): void
	{
		$this->setLog($offset, $value);
	}

	/**
	 * @param mixed $offset
	 */
	public function offsetUnset($offset): void
	{
		if (array_key_exists($offset, $this->data))
		{
			unset($this->data[$offset]);
			$this->save();
		}
	}
}

class Uploader
{
	public $files = array();
	public $controlId = "fileUploader";
	public $params = array(
		"allowUpload" => "A",
		"allowUploadExt" => "",
		"copies" => array(
			"default" => array(
				"width" => null,
				"height" => null
			),
		/*	"copyName" => array(
				"width" => 100,
				"height" => 100
			)*/
		),
		"storage" => array(
			"moduleId" => "main",
			"cloud" => false
		)
	);
/*
 * @var string $script Url to uploading page for forming url to view
 * @var string $path Path to temp directory
 * @var string $CID Controller ID
 * @var string $mode
 * @var array $processTime Time limits
 * @var HttpClient $http
*/
	public $script;
	protected $path = "";
	protected $CID = null;
	protected int $version = 0;
	protected $mode = "view";
	protected $param = array();
	protected $requestMethods = array(
		"get" => true,
		"post" => true
	);
	/* @var HttpRequest $request */
	protected $request;
	protected $http;

	const FILE_NAME = "bxu_files";
	const INFO_NAME = "bxu_info";
	const EVENT_NAME = "main_bxu";
	const SESSION_LIST = "MFI_SESSIONS";
	const SESSION_TTL = 86400;

	public function __construct($params = array())
	{
		global $APPLICATION;

		$this->script = $APPLICATION->GetCurPageParam();

		$params = is_array($params) ? $params : array($params);
		$params["copies"] = (isset($params["copies"]) && is_array($params["copies"]) ? $params["copies"] : array()) + $this->params["copies"];
		$params["storage"] = (isset($params["storage"]) && is_array($params["storage"]) ? $params["storage"] : array()) + $this->params["storage"];
		$params["storage"]["moduleId"] = preg_replace("/[^a-z_-]/i", "_", $params["storage"]["moduleId"]);
		$this->params = $params;
		if (array_key_exists("controlId", $params))
			$this->controlId = $params["controlId"];
		if (array_key_exists("events", $params) && is_array($params["events"]))
		{
			foreach($params["events"] as $key => $val)
			{
				$this->setHandler($key, $val);
			}
		}
		unset($this->params["events"]);

		$this->path = \CTempFile::GetDirectoryName(
			12,
			array(
				"bxu",
				$this->params["storage"]["moduleId"],
				md5(serialize(array(
					$this->controlId,
					bitrix_sessid(),
					\CMain::GetServerUniqID()
					))
				)
			)
		);
		$this->request = Context::getCurrent()->getRequest();
	}

	public function setControlId($controlId)
	{
		$this->controlId = $controlId;
	}

	public function setHandler($name, $callback)
	{
		AddEventHandler(self::EVENT_NAME, $name, $callback);
		return $this;
	}
	/**
	 * excludes real paths from array
	 * @param $item - array
	 * @return array
	 */
	protected static function removeTmpPath($item)
	{
		if (is_array($item))
		{
			if (array_key_exists("tmp_name", $item))
			{
				unset($item["tmp_name"]);
			}
			foreach ($item as $key => $val)
			{
				if ($key == "chunksInfo")
				{
					$item[$key]["uploaded"] = count($item[$key]["uploaded"]);
					$item[$key]["written"] = count($item[$key]["written"]);
				}
				else if (is_array($val))
				{
					$item[$key] = self::removeTmpPath($val);
				}
			}
		}
		return $item;
	}

	public static function prepareData($data)
	{
		array_walk_recursive(
			$data,
			function(&$v, $k) {
				if ($k == "error")
				{
					$v = preg_replace("/<(.+?)>/is".BX_UTF_PCRE_MODIFIER, "", $v);
				}
			}
		);
		return self::removeTmpPath($data);
	}

	/**
	 * @return bool
	 * @throws AccessDeniedException
	 * @throws ArgumentOutOfRangeException
	 * @throws NotImplementedException
	 */
	protected function fillRequireData()
	{
		$this->mode = $this->getRequest("mode");
		if (!in_array($this->mode, array("upload", "delete", "view")))
			throw new ArgumentOutOfRangeException("mode");

		if ($this->mode != "view" && !check_bitrix_sessid())
			throw new AccessDeniedException("Bad sessid.");

		$this->version = (int) $this->getRequest("version");

		$directory = \CBXVirtualIo::GetInstance()->GetDirectory($this->path);
		$directoryExists = $directory->IsExists();
		if (!$directory->Create())
			throw new NotImplementedException("Mandatory directory has not been created.");
		if (!$directoryExists)
		{
			$access = \CBXVirtualIo::GetInstance()->GetFile($directory->GetPath()."/.access.php");
			$content = '<?$PERM["'.$directory->GetName().'"]["*"]="X";?>';

			if (!$access->IsExists() || mb_strpos($access->GetContents(), $content) === false)
			{
				if (($fd = $access->Open('ab')))
				{
					fwrite($fd, $content);
				}
				fclose($fd);
			}
		}

		return false;
	}

	protected function showJsonAnswer($result)
	{
		if (!defined("PUBLIC_AJAX_MODE"))
			define("PUBLIC_AJAX_MODE", true);
		if (!defined("NO_KEEP_STATISTIC"))
			define("NO_KEEP_STATISTIC", "Y");
		if (!defined("NO_AGENT_STATISTIC"))
			define("NO_AGENT_STATISTIC", "Y");
		if (!defined("NO_AGENT_CHECK"))
			define("NO_AGENT_CHECK", true);
		if (!defined("DisableEventsCheck"))
			define("DisableEventsCheck", true);

		require_once(\Bitrix\Main\Application::getInstance()->getContext()->getServer()->getDocumentRoot()."/bitrix/modules/main/include/prolog_before.php");
		global $APPLICATION;

		$APPLICATION->RestartBuffer();

		$version = IsIE();
		if ( !(0 < $version && $version < 10) )
			header('Content-Type:application/json; charset=UTF-8');

		echo Json::encode($result);
		\CMain::finalActions();
		die;
	}

	/**
	 * Sets request methods to check.
	 * @param array $methods Request methods array("get", "post").
	 * @return $this
	 */
	protected function setRequestMethodToCheck(array $methods)
	{
		foreach ($this->requestMethods as $method => $value)
			$this->requestMethods[$method] = in_array($method, $methods);
		return $this;
	}
	/**
	 * @param string $key Array key in request.
	 * @return null|mixed
	 */
	protected function getRequest($key)
	{
		if ($this->requestMethods["post"] &&
			is_array($this->request->getPost(self::INFO_NAME)) &&
			array_key_exists($key, $this->request->getPost(self::INFO_NAME)))
		{
			$res = $this->request->getPost(self::INFO_NAME);
			return $res[$key];
		}
		if ($this->requestMethods["get"] &&
			is_array($this->request->getQuery(self::INFO_NAME)) &&
			array_key_exists($key, $this->request->getQuery(self::INFO_NAME)))
		{
			$res = $this->request->getQuery(self::INFO_NAME);
			return $res[$key];
		}

		return null;
	}

	/**
	 * @param string $key
	 * @return mixed
	 */
	public function getParam($key)
	{
		return $this->params[$key];
	}
	/**
	 *
	 * @param bool $checkPost Flag for check post.
	 * @return boolean
	 */
	public function checkPost($checkPost = true)
	{
		if ($checkPost === false && !is_array($this->request->getQuery(self::INFO_NAME)) ||
			$checkPost !== false && !is_array($this->request->getPost(self::INFO_NAME)))
			return false;

		if ($checkPost === false)
			$this->setRequestMethodToCheck(array("get"));

		try
		{
			$this->fillRequireData();
			$cid = FileInputUtility::instance()->registerControl($this->getRequest("CID"), $this->controlId);

			if ($this->mode == "upload")
			{
				$package = new Package(
					$this->path,
					$cid,
					$this->getRequest("packageIndex")
				);
				$package
					->setStorage($this->params["storage"])
					->setCopies($this->params["copies"]);

				$response = $package->checkPost($this->params);

				if ($this->version <= 1)
				{
					$response2 = array();
					foreach ($response as $k => $r)
					{
						$response2[$k] = array(
							"hash" => $r["hash"],
							"status" => $r["status"],
							"file" => $r
						);
						if (isset($r["error"]))
							$response2[$k]["error"] = $r["error"];
					}
					$result = array(
						"status" => $package->getLog("uploadStatus") == "uploaded" ? "done" : "inprogress",
						"package" => array(
							$package->getIndex() => array_merge(
								$package->getLog(),
								array(
									"executed" => $package->getLog("executeStatus") == "executed",
									"filesCount" => $package->getLog("filesCount")
								)
							)
						),
						"report" => array(
							"uploading" => array(
								$package->getCid() => $package->getCidLog()
							)
						),
						"files" => self::prepareData($response2)
					);
					$this->showJsonAnswer($result);
				}
			}
			else if ($this->mode == "delete")
			{
				$cid = FileInputUtility::instance()->registerControl($this->getRequest("CID"), $this->controlId);
				File::deleteFile($cid, $this->getRequest("hash"), $this->path);
			}
			else
			{
				File::viewFile($cid, $this->getRequest("hash"), $this->path);
			}
			return true;
		}
		catch (Main\IO\IoException $e)
		{
			$this->showJsonAnswer(array(
				"status" => "error",
				"error" => "Something went wrong with the temporary file."
			));
		}
		catch (\Exception $e)
		{
			$this->showJsonAnswer(array(
				"status" => "error",
				"error" => $e->getMessage()
			));
		}
		return false;
	}

	/**
	 * @param $hash
	 * @param $file
	 * @param array $canvases
	 * @param array $watermark
	 * @return mixed
	 */
	public function checkCanvases($hash, &$file, $canvases = array(), $watermark = array())
	{
		if (!empty($watermark))
		{
			$file["files"]["default"] = File::createCanvas(
				$file["files"]["default"],
				$file["files"]["default"],
				array(),
				$watermark
			);
		}
		if (is_array($canvases))
		{
			foreach ($canvases as $canvas => $canvasParams)
			{
				if (!array_key_exists($canvas, $file["files"]))
				{
					$source = $file["files"]["default"]; // TODO pick up more appropriate copy by params
					$file["files"][$canvas] = File::createCanvas($source,
						array(
							"code" => $canvas,
							"tmp_name" => mb_substr($source["tmp_name"], 0, -7).$canvas,
							"url" => mb_substr($source["url"], 0, -7).$canvas
						), $canvasParams, $watermark);
				}
			}
		}
		return $file;
	}
	public function deleteFile($hash) {
		$cid = FileInputUtility::instance()->registerControl($this->getRequest("CID"), $this->controlId);
		File::deleteFile($cid, $hash, $this->path);
	}

	/**
	 * @param string $tmpName
	 * @return false|array
	 */
	public static function getPaths($tmpName)
	{
		$docRoot = null;
		$io = \CBXVirtualIo::GetInstance();
		if (($tempRoot = \CTempFile::GetAbsoluteRoot()) && ($strFilePath = $tempRoot.$tmpName) &&
			$io->FileExists($strFilePath) && ($url = File::getUrlFromRelativePath($tmpName)))
		{
			return array(
				"tmp_url" => $url,
				"tmp_name" => $strFilePath
			);
		}
		else if ((($docRoot = \Bitrix\Main\Application::getInstance()->getContext()->getServer()->getDocumentRoot()) && $strFilePath = $docRoot.$tmpName) && $io->FileExists($strFilePath))
		{
			return array(
				"tmp_url" => $tmpName,
				"tmp_name" => $strFilePath
			);
		}
		else if ($io->FileExists($tmpName) && ($docRoot = \Bitrix\Main\Application::getInstance()->getContext()->getServer()->getDocumentRoot()) &&
			mb_strpos($tmpName, $docRoot) === 0)
		{
			return array(
				"tmp_url" => str_replace("//", "/", "/".mb_substr($tmpName, mb_strlen($docRoot))),
				"tmp_name" => $tmpName
			);
		}
		return false;
	}

}