shell bypass 403
<?php
/*
* HTML5 DOMDocument PHP library (extends DOMDocument)
* https://github.com/ivopetkov/html5-dom-document-php
* Copyright (c) Ivo Petkov
* Free to use under the MIT license.
*/
namespace IvoPetkov;
use IvoPetkov\HTML5DOMDocument\Internal\QuerySelectors;
/**
* Represents a live (can be manipulated) representation of an element in a HTML5 document.
*
* @property string $innerHTML The HTML code inside the element.
* @property string $outerHTML The HTML code for the element including the code inside.
* @property \IvoPetkov\HTML5DOMTokenList $classList A collection of the class attributes of the element.
*/
class HTML5DOMElement extends \DOMElement
{
use QuerySelectors;
/**
*
* @var array
*/
static private $foundEntitiesCache = [[], []];
/**
*
* @var array
*/
static private $newObjectsCache = [];
/*
*
* @var HTML5DOMTokenList
*/
private $classList = null;
/**
* Returns the value for the property specified.
*
* @param string $name
* @return string
* @throws \Exception
*/
public function __get(string $name)
{
if ($name === 'innerHTML') {
if ($this->firstChild === null) {
return '';
}
$html = $this->ownerDocument->saveHTML($this);
$nodeName = $this->nodeName;
return preg_replace('@^<' . $nodeName . '[^>]*>|</' . $nodeName . '>$@', '', $html);
} elseif ($name === 'outerHTML') {
if ($this->firstChild === null) {
$nodeName = $this->nodeName;
$attributes = $this->getAttributes();
$result = '<' . $nodeName . '';
foreach ($attributes as $name => $value) {
$result .= ' ' . $name . '="' . htmlentities($value) . '"';
}
if (array_search($nodeName, ['area', 'base', 'br', 'col', 'command', 'embed', 'hr', 'img', 'input', 'keygen', 'link', 'meta', 'param', 'source', 'track', 'wbr']) === false) {
$result .= '></' . $nodeName . '>';
} else {
$result .= '/>';
}
return $result;
}
return $this->ownerDocument->saveHTML($this);
} elseif ($name === 'classList') {
if ($this->classList === null) {
$this->classList = new HTML5DOMTokenList($this, 'class');
}
return $this->classList;
}
throw new \Exception('Undefined property: HTML5DOMElement::$' . $name);
}
/**
* Sets the value for the property specified.
*
* @param string $name
* @param string $value
* @throws \Exception
*/
public function __set(string $name, $value)
{
if ($name === 'innerHTML') {
while ($this->hasChildNodes()) {
$this->removeChild($this->firstChild);
}
if (!isset(self::$newObjectsCache['html5domdocument'])) {
self::$newObjectsCache['html5domdocument'] = new \IvoPetkov\HTML5DOMDocument();
}
$tmpDoc = clone (self::$newObjectsCache['html5domdocument']);
$tmpDoc->loadHTML('<body>' . $value . '</body>', HTML5DOMDocument::ALLOW_DUPLICATE_IDS);
foreach ($tmpDoc->getElementsByTagName('body')->item(0)->childNodes as $node) {
$node = $this->ownerDocument->importNode($node, true);
$this->appendChild($node);
}
return;
} elseif ($name === 'outerHTML') {
if (!isset(self::$newObjectsCache['html5domdocument'])) {
self::$newObjectsCache['html5domdocument'] = new \IvoPetkov\HTML5DOMDocument();
}
$tmpDoc = clone (self::$newObjectsCache['html5domdocument']);
$tmpDoc->loadHTML('<body>' . $value . '</body>', HTML5DOMDocument::ALLOW_DUPLICATE_IDS);
foreach ($tmpDoc->getElementsByTagName('body')->item(0)->childNodes as $node) {
$node = $this->ownerDocument->importNode($node, true);
$this->parentNode->insertBefore($node, $this);
}
$this->parentNode->removeChild($this);
return;
} elseif ($name === 'classList') {
$this->setAttribute('class', $value);
return;
}
throw new \Exception('Undefined property: HTML5DOMElement::$' . $name);
}
/**
* Updates the result value before returning it.
*
* @param string $value
* @return string The updated value
*/
private function updateResult(string $value): string
{
$value = str_replace(self::$foundEntitiesCache[0], self::$foundEntitiesCache[1], $value);
if (strstr($value, 'html5-dom-document-internal-entity') !== false) {
$search = [];
$replace = [];
$matches = [];
preg_match_all('/html5-dom-document-internal-entity([12])-(.*?)-end/', $value, $matches);
$matches[0] = array_unique($matches[0]);
foreach ($matches[0] as $i => $match) {
$search[] = $match;
$replace[] = html_entity_decode(($matches[1][$i] === '1' ? '&' : '&#') . $matches[2][$i] . ';');
}
$value = str_replace($search, $replace, $value);
self::$foundEntitiesCache[0] = array_merge(self::$foundEntitiesCache[0], $search);
self::$foundEntitiesCache[1] = array_merge(self::$foundEntitiesCache[1], $replace);
unset($search);
unset($replace);
unset($matches);
}
return $value;
}
/**
* Returns the updated nodeValue Property
*
* @return string The updated $nodeValue
*/
public function getNodeValue(): string
{
return $this->updateResult($this->nodeValue);
}
/**
* Returns the updated $textContent Property
*
* @return string The updated $textContent
*/
public function getTextContent(): string
{
return $this->updateResult($this->textContent);
}
/**
* Returns the value for the attribute name specified.
*
* @param string $name The attribute name.
* @return string The attribute value.
* @throws \InvalidArgumentException
*/
public function getAttribute($name): string
{
if ($this->attributes->length === 0) { // Performance optimization
return '';
}
$value = parent::getAttribute($name);
return $value !== '' ? (strstr($value, 'html5-dom-document-internal-entity') !== false ? $this->updateResult($value) : $value) : '';
}
/**
* Returns an array containing all attributes.
*
* @return array An associative array containing all attributes.
*/
public function getAttributes(): array
{
$attributes = [];
foreach ($this->attributes as $attributeName => $attribute) {
$value = $attribute->value;
$attributes[$attributeName] = $value !== '' ? (strstr($value, 'html5-dom-document-internal-entity') !== false ? $this->updateResult($value) : $value) : '';
}
return $attributes;
}
/**
* Returns the element outerHTML.
*
* @return string The element outerHTML.
*/
public function __toString(): string
{
return $this->outerHTML;
}
/**
* Returns the first child element matching the selector.
*
* @param string $selector A CSS query selector. Available values: *, tagname, tagname#id, #id, tagname.classname, .classname, tagname.classname.classname2, .classname.classname2, tagname[attribute-selector], [attribute-selector], "div, p", div p, div > p, div + p and p ~ ul.
* @return HTML5DOMElement|null The result DOMElement or null if not found.
* @throws \InvalidArgumentException
*/
public function querySelector(string $selector)
{
return $this->internalQuerySelector($selector);
}
/**
* Returns a list of children elements matching the selector.
*
* @param string $selector A CSS query selector. Available values: *, tagname, tagname#id, #id, tagname.classname, .classname, tagname.classname.classname2, .classname.classname2, tagname[attribute-selector], [attribute-selector], "div, p", div p, div > p, div + p and p ~ ul.
* @return HTML5DOMNodeList Returns a list of DOMElements matching the criteria.
* @throws \InvalidArgumentException
*/
public function querySelectorAll(string $selector)
{
return $this->internalQuerySelectorAll($selector);
}
}