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 ArrayIterator;
use DOMElement;
/**
* Represents a set of space-separated tokens of an element attribute.
*
* @property-read int $length The number of tokens.
* @property-read string $value A space-separated list of the tokens.
*/
class HTML5DOMTokenList
{
/**
* @var string
*/
private $attributeName;
/**
* @var DOMElement
*/
private $element;
/**
* @var string[]
*/
private $tokens;
/**
* @var string
*/
private $previousValue;
/**
* Creates a list of space-separated tokens based on the attribute value of an element.
*
* @param DOMElement $element The DOM element.
* @param string $attributeName The name of the attribute.
*/
public function __construct(DOMElement $element, string $attributeName)
{
$this->element = $element;
$this->attributeName = $attributeName;
$this->previousValue = null;
$this->tokenize();
}
/**
* Adds the given tokens to the list.
*
* @param string[] $tokens The tokens you want to add to the list.
* @return void
*/
public function add(string ...$tokens)
{
if (count($tokens) === 0) {
return;
}
foreach ($tokens as $t) {
if (in_array($t, $this->tokens)) {
continue;
}
$this->tokens[] = $t;
}
$this->setAttributeValue();
}
/**
* Removes the specified tokens from the list. If the string does not exist in the list, no error is thrown.
*
* @param string[] $tokens The token you want to remove from the list.
* @return void
*/
public function remove(string ...$tokens)
{
if (count($tokens) === 0) {
return;
}
if (count($this->tokens) === 0) {
return;
}
foreach ($tokens as $t) {
$i = array_search($t, $this->tokens);
if ($i === false) {
continue;
}
array_splice($this->tokens, $i, 1);
}
$this->setAttributeValue();
}
/**
* Returns an item in the list by its index (returns null if the number is greater than or equal to the length of the list).
*
* @param int $index The zero-based index of the item you want to return.
* @return null|string
*/
public function item(int $index)
{
$this->tokenize();
if ($index >= count($this->tokens)) {
return null;
}
return $this->tokens[$index];
}
/**
* Removes a given token from the list and returns false. If token doesn't exist it's added and the function returns true.
*
* @param string $token The token you want to toggle.
* @param bool $force A Boolean that, if included, turns the toggle into a one way-only operation. If set to false, the token will only be removed but not added again. If set to true, the token will only be added but not removed again.
* @return bool false if the token is not in the list after the call, or true if the token is in the list after the call.
*/
public function toggle(string $token, bool $force = null): bool
{
$this->tokenize();
$isThereAfter = false;
$i = array_search($token, $this->tokens);
if (is_null($force)) {
if ($i === false) {
$this->tokens[] = $token;
$isThereAfter = true;
} else {
array_splice($this->tokens, $i, 1);
}
} else {
if ($force) {
if ($i === false) {
$this->tokens[] = $token;
}
$isThereAfter = true;
} else {
if ($i !== false) {
array_splice($this->tokens, $i, 1);
}
}
}
$this->setAttributeValue();
return $isThereAfter;
}
/**
* Returns true if the list contains the given token, otherwise false.
*
* @param string $token The token you want to check for the existence of in the list.
* @return bool true if the list contains the given token, otherwise false.
*/
public function contains(string $token): bool
{
$this->tokenize();
return in_array($token, $this->tokens);
}
/**
* Replaces an existing token with a new token.
*
* @param string $old The token you want to replace.
* @param string $new The token you want to replace $old with.
* @return void
*/
public function replace(string $old, string $new)
{
if ($old === $new) {
return;
}
$this->tokenize();
$i = array_search($old, $this->tokens);
if ($i !== false) {
$j = array_search($new, $this->tokens);
if ($j === false) {
$this->tokens[$i] = $new;
} else {
array_splice($this->tokens, $i, 1);
}
$this->setAttributeValue();
}
}
/**
*
* @return string
*/
public function __toString(): string
{
$this->tokenize();
return implode(' ', $this->tokens);
}
/**
* Returns an iterator allowing you to go through all tokens contained in the list.
*
* @return ArrayIterator
*/
public function entries(): ArrayIterator
{
$this->tokenize();
return new ArrayIterator($this->tokens);
}
/**
* Returns the value for the property specified
*
* @param string $name The name of the property
* @return string The value of the property specified
* @throws \Exception
*/
public function __get(string $name)
{
if ($name === 'length') {
$this->tokenize();
return count($this->tokens);
} elseif ($name === 'value') {
return $this->__toString();
}
throw new \Exception('Undefined property: HTML5DOMTokenList::$' . $name);
}
/**
*
* @return void
*/
private function tokenize()
{
$current = $this->element->getAttribute($this->attributeName);
if ($this->previousValue === $current) {
return;
}
$this->previousValue = $current;
$tokens = explode(' ', $current);
$finals = [];
foreach ($tokens as $token) {
if ($token === '') {
continue;
}
if (in_array($token, $finals)) {
continue;
}
$finals[] = $token;
}
$this->tokens = $finals;
}
/**
*
* @return void
*/
private function setAttributeValue()
{
$value = implode(' ', $this->tokens);
if ($this->previousValue === $value) {
return;
}
$this->previousValue = $value;
$this->element->setAttribute($this->attributeName, $value);
}
}