AnonSec Shell
Server IP : 85.193.89.191  /  Your IP : 3.145.70.44
Web Server : Apache
System : Linux 956367-cx40159.tmweb.ru 3.10.0-1160.105.1.el7.x86_64 #1 SMP Thu Dec 7 15:39:45 UTC 2023 x86_64
User : bitrix ( 600)
PHP Version : 8.1.27
Disable Function : NONE
MySQL : OFF  |  cURL : OFF  |  WGET : ON  |  Perl : ON  |  Python : ON  |  Sudo : ON  |  Pkexec : ON
Directory :  /home/bitrix/www/bitrix/modules/main/lib/web/

Upload File :
current_dir [ Writeable ] document_root [ Writeable ]

 

Command :


[ HOME ]     

Current File : /home/bitrix/www/bitrix/modules/main/lib/web/httpheaders.php
<?php

/**
 * Bitrix Framework
 * @package bitrix
 * @subpackage main
 * @copyright 2001-2022 Bitrix
 */

namespace Bitrix\Main\Web;

use Bitrix\Main\Context;
use Bitrix\Main\Text\Encoding;
use IteratorAggregate;
use Traversable;

class HttpHeaders implements IteratorAggregate
{
	protected array $headers = [];
	protected ?int $status = null;
	protected ?string $reasonPhrase = null;
	protected ?string $version = null;

	/**
	 * @param string[] | string[][] | null $headers
	 */
	public function __construct(array $headers = null)
	{
		if ($headers !== null)
		{
			foreach ($headers as $header => $value)
			{
				$this->add($header, $value);
			}
		}
	}

	/**
	 * Adds a header value.
	 * @param string $name
	 * @param string | array $value
	 * @throws \InvalidArgumentException
	 */
	public function add($name, $value)
	{
		// compatibility
		$name = (string)$name;

		// PSR-7: The implementation SHOULD reject invalid values and SHOULD NOT make any attempt to automatically correct the provided values.
		if ($name == '' || !static::validateName($name))
		{
			throw new \InvalidArgumentException("Invalid header name '{$name}'.");
		}

		if (!is_array($value))
		{
			$value = [$value];
		}

		foreach ($value as $key => $val)
		{
			$value[$key] = (string)$val;
			if (!static::validateValue($value[$key]))
			{
				throw new \InvalidArgumentException("Invalid header value '{$value[$key]}'.");
			}
		}

		$nameLower = strtolower($name);

		if (!isset($this->headers[$nameLower]))
		{
			$this->headers[$nameLower] = [
				'name' => $name,
				'values' => [],
			];
		}
		foreach ($value as $val)
		{
			$this->headers[$nameLower]['values'][] = $val;
		}
	}

	/**
	 * @see https://tools.ietf.org/html/rfc7230#section-3.2
	 * field-name     = token
	 * token          = 1*tchar
	 * tchar          = "!" / "#" / "$" / "%" / "&" / "'" / "*"
	 *                  / "+" / "-" / "." / "^" / "_" / "`" / "|" / "~"
	 *                  / DIGIT / ALPHA
	 */
	protected static function validateName(string $name): bool
	{
		return (strpos($name, "\0") === false && preg_match('/^[a-zA-Z0-9\'`#$%&*+.^_|~!-]+$/', $name));
	}

	/**
     * @see https://tools.ietf.org/html/rfc7230#section-3.2
	 * field-value    = *( field-content / obs-fold )
     * field-content  = field-vchar [ 1*( SP / HTAB ) field-vchar ]
     * field-vchar    = VCHAR / obs-text
     * VCHAR          = %x21-7E
     * obs-text       = %x80-FF
	 */
	protected static function validateValue(string $value): bool
	{
		return (strpos($value, "\0") === false && preg_match('/^[\x20\x09\x21-\x7E\x80-\xFF]*$/', $value));
	}

	/**
	 * Sets (replaces) a header value.
	 * @param string $name
	 * @param string | string[] $value
	 */
	public function set($name, $value)
	{
		$this->delete($name);
		$this->add($name, $value);
	}

	/**
	 * Returns a header value by its name. If $returnArray is true then an array with multiple values is returned.
	 * @param string $name
	 * @param bool $returnArray
	 * @return null | string | string[]
	 */
	public function get($name, $returnArray = false)
	{
		$nameLower = strtolower($name);

		if (isset($this->headers[$nameLower]))
		{
			if ($returnArray)
			{
				return $this->headers[$nameLower]['values'];
			}

			return $this->headers[$nameLower]['values'][0];
		}

		return null;
	}

	/**
	 * Deletes a header or headers by its name.
	 *
	 * @param string $name
	 * @return void
	 */
	public function delete($name)
	{
		$nameLower = strtolower($name);

		if (isset($this->headers[$nameLower]))
		{
			unset($this->headers[$nameLower]);
		}
	}

	/**
	 * Returns true if a header is set.
	 *
	 * @param string $name
	 * @return bool
	 */
	public function has(string $name): bool
	{
		$nameLower = strtolower($name);

		return isset($this->headers[$nameLower]);
	}

	/**
	 * Clears all headers.
	 */
	public function clear()
	{
		$this->headers = [];
	}

	/**
	 * Returns the string representation for an HTTP request.
	 * @return string
	 */
	public function toString()
	{
		$str = "";
		foreach ($this->headers as $header)
		{
			foreach ($header["values"] as $value)
			{
				$str .= $header["name"] . ": " . $value . "\r\n";
			}
		}

		return $str;
	}

	/**
	 * Returns headers as a raw array.
	 * @return array
	 */
	public function toArray()
	{
		return $this->headers;
	}

	/**
	 * Returns the content type part of the Content-Type header in lower case.
	 * @return null|string
	 */
	public function getContentType()
	{
		$contentType = $this->get("Content-Type");
		if ($contentType !== null)
		{
			$parts = explode(";", $contentType);

			// RFC 2045 says: "The type, subtype, and parameter names are not case-sensitive."
			return strtolower(trim($parts[0]));
		}

		return null;
	}

	/**
	 * Returns the specified attribute part of the Content-Type header.
	 * @return null|string
	 */
	public function getContentTypeAttribute(string $attribute)
	{
		$contentType = $this->get('Content-Type');
		if ($contentType !== null)
		{
			$attribute = strtolower($attribute);
			$parts = explode(';', $contentType);

			foreach ($parts as $part)
			{
				$values = explode('=', $part);
				if (strtolower(trim($values[0])) == $attribute)
				{
					return trim($values[1]);
				}
			}
		}

		return null;
	}

	/**
	 * Returns the boundary value of the Content-Type header.
	 * @return null|string
	 */
	public function getBoundary()
	{
		return $this->getContentTypeAttribute('boundary');
	}

	/**
	 * Returns the charset part of the Content-Type header.
	 * @return null|string
	 */
	public function getCharset()
	{
		return $this->getContentTypeAttribute('charset');
	}

	/**
	 * Returns disposition-type part of the Content-Disposition header
	 * @return null|string Disposition-type part of the Content-Disposition header if found or null otherwise.
	 */
	public function getContentDisposition()
	{
		$contentDisposition = $this->get("Content-Disposition");
		if ($contentDisposition !== null)
		{
			$parts = explode(";", $contentDisposition);

			return trim($parts[0]);
		}

		return null;
	}

	/**
	 * Returns a filename from the Content-disposition header.
	 *
	 * @return string|null Filename if it was found in the Content-disposition header or null otherwise.
	 */
	public function getFilename()
	{
		$contentDisposition = $this->get('Content-Disposition');
		if ($contentDisposition !== null)
		{
			$filename = null;
			$encoding = null;

			$contentElements = explode(';', $contentDisposition);
			foreach ($contentElements as $contentElement)
			{
				$contentElement = trim($contentElement);
				if (preg_match('/^filename\*=(.+)\'(.+)?\'(.+)$/', $contentElement, $matches))
				{
					$filename = $matches[3];
					$encoding = $matches[1];
					break;
				}
				elseif (preg_match('/^filename="(.+)"$/', $contentElement, $matches))
				{
					$filename = $matches[1];
				}
				elseif (preg_match('/^filename=(.+)$/', $contentElement, $matches))
				{
					$filename = $matches[1];
				}
			}

			if ($filename <> '')
			{
				$filename = urldecode($filename);

				if ($encoding <> '')
				{
					$charset = Context::getCurrent()->getCulture()->getCharset();
					$filename = Encoding::convertEncoding($filename, $encoding, $charset);
				}
			}

			return $filename;
		}

		return null;
	}

	/**
	 * Retrieve an external iterator
	 * @link https://php.net/manual/en/iteratoraggregate.getiterator.php
	 * @return Traversable An instance of an object implementing <b>Iterator</b> or
	 * <b>Traversable</b>
	 * @since 5.0.0
	 */
	public function getIterator(): Traversable
	{
		$toIterate = [];
		foreach ($this->headers as $header)
		{
			$toIterate[$header['name']] = $header['values'];
		}

		return new \ArrayIterator($toIterate);
	}

	/**
	 * Returns parsed cookies from 'set-cookie' headers.
	 * @return HttpCookies
	 */
	public function getCookies(): HttpCookies
	{
		$cookies = new HttpCookies();

		if ($this->has('set-cookie'))
		{
			foreach ($this->get('set-cookie', true) as $value)
			{
				$cookies->addFromString($value);
			}
		}

		return $cookies;
	}

	/**
	 * Retuns the headers as a two-dimentional array ('name' => values).
	 *
	 * @return string[][]
	 */
	public function getHeaders(): array
	{
		return iterator_to_array($this->getIterator());
	}

	/**
	 * Creates an object from a http response string.
	 *
	 * @param string $response
	 * @return HttpHeaders
	 */
	public static function createFromString(string $response): HttpHeaders
	{
		$headers = new static();

		foreach (explode("\n", $response) as $k => $header)
		{
			if ($k == 0)
			{
				$headers->parseStatus($header);
			}
			elseif (strpos($header, ':') !== false)
			{
				[$headerName, $headerValue] = explode(':', $header, 2);
				$headers->add($headerName, trim($headerValue));
			}
		}

		return $headers;
	}

	/**
	 * @param string $status
	 * @return $this
	 */
	public function parseStatus(string $status): HttpHeaders
	{
		if (preg_match('#^HTTP/(\S+) (\d+) *(.*)#', $status, $find))
		{
			$this->version = $find[1];
			$this->setStatus((int)$find[2], trim($find[3]));
		}

		return $this;
	}

	/**
	 * Sets HTTP status code and prase.
	 *
	 * @param int $status
	 * @param string|null $reasonPhrase
	 * @return $this
	 */
	public function setStatus(int $status, ?string $reasonPhrase = null): HttpHeaders
	{
		$this->status = $status;
		$this->reasonPhrase = $reasonPhrase;

		return $this;
	}

	public function getStatus(): int
	{
		return $this->status ?? 0;
	}

	public function getVersion(): ?string
	{
		return $this->version;
	}

	public function getReasonPhrase(): string
	{
		return $this->reasonPhrase ?? '';
	}
}

Anon7 - 2022
AnonSec Team