Файл: adultscript-2.0.3-pro/files/libraries/framework/filter/htmlfilter.php
Строк: 143
<?php
defined('_VALID') or die('Restricted Access!');
class VFilter_htmlfilter extends VFilter
{
const MATCHED_NAME = 1;
const MATCHED_VAL = 2;
private $allowed_tags = array();
private $allowed_attrs = array();
private $allowed_prots = array();
private $default_prot;
private $wrap_length;
public function __construct($allowed_tags=array(), $allowed_attrs=array(), $allowed_prots=array(), $default_prot=NULL, $wrap_length=NULL)
{
parent::__construct();
$this->allowed_tags = ($allowed_tags) ? implode('|', $allowed_tags) : implode('|', $this->cfg['allowed_tags']);
$allowed_attrs = ($allowed_attrs) ? $allowed_attrs : $this->cfg['allowed_attributes'];
foreach ($allowed_attrs as $attr) {
$this->allowed_attrs[$attr] = TRUE;
}
$this->allowed_prots = ($allowed_prots) ? implode('|', $allowed_prots) : implode('|', $this->cfg['allowed_protocols']);
$this->default_prot = ($default_prot) ? $default_prot : $this->cfg['default_protocol'];
$this->wrap_length = ($wrap_length) ? $wrap_length : $this->cfg['wrap_length'];
}
public function set_tags($tags=array())
{
$this->allowed_tags = implode('|', $tags);
}
public function set_attrs($attrs=array())
{
foreach ($attrs as $attr) {
$this->allowed_attrs[$attr] = TRUE;
}
}
public function clean($source)
{
// return $this->cleanNoBreak($this->__decode(utf8_clean($source)));
return $this->cleanNoBreak(utf8_clean($source));
}
public function cleanNoBreak($html)
{
static $notags = array('<' => '<', '>' => '>');
$matches = array();
$text = array();
$tags = array();
$tagLog = array();
if (!preg_match('/[<>]/', $html)) {
return $html;
}
$html = preg_replace('#<!--.*?-->#s', '', $html);
$tokens = preg_split("#<s*(/?s*(?:$this->allowed_tags.')[^<]*?)>#si", $html, -1, PREG_SPLIT_DELIM_CAPTURE);
$tokensSize = sizeof($tokens);
if ($tokensSize === 0) {
return strtr($html, $notags);
}
for ($tCtr = 0; $tCtr < $tokensSize; ++$tCtr) {
$token = &$tokens[$tCtr];
if ($tCtr % 2 === 0) {//if it's text, escape all tags
$token = strtr($token, $notags);
$token = preg_replace('#([^s]{80})#', "$1n", $token);
continue;
}
$killTag = FALSE;
preg_match('#s*/?s*([wd-]+)s*#', $token, $matches);
$name = $matches[1];
$newTag = $name;
//cut off everything but the arguments
$token = preg_replace('#^s*/?s*[wd-]+s*(.*?)?/?$#', "$1", $token);
$floor = 0;
$charNum = 0;
$lastMatched = NULL;
$params = array();
while ($charNum < strlen($token)) {//if it is bare tag, then $token will be empty, so this loop will not even start
$char = $token{$charNum};
if ($char == '=') {//equality sign that is not part of param
//this could be one name, or several names without values
$paramNames = preg_split('#s#', substr($token, $floor, $charNum - $floor), -1, PREG_SPLIT_NO_EMPTY);
$lastParamName = array_pop($paramNames);
foreach ($paramNames as $paramName) {//this will give us correct xhtml syntax: name="name"
$params[] = $paramName;
$params[] = $paramName;
}
$params[] = $lastParamName;
$floor = $charNum + 1;
$lastMatched = self::MATCHED_NAME;
} elseif (($char == "'" || $char == '"')) {//entrering quoted string
$floor = $charNum + 1;
$charNum = strpos($token, $char, $floor);//find the closing quote
if ($charNum !== FALSE) {//if its ordinary quoted value
$params[] = trim(substr($token, $floor, $charNum - $floor));
++$charNum;
} else {//if quotes does not ends inside the tag (which is possible because of the way we search for tags)
$params[] = trim(substr($token, $floor));
$charNum = strlen($token);
}
$floor = $charNum;//just in case
//next char will be one after the ending quote, if there are any
} elseif ($lastMatched == self::MATCHED_NAME
&& preg_match('#s#', $char)) {//we match the space after unquoted value
$params[] = trim(substr($token, $floor, $charNum - $floor));
$floor = $charNum + 1;
$lastMatched = self::MATCHED_VAL;
} elseif ($charNum == strlen($token) - 1) {//there is something between param name width equality sign and the end of array
//$params[] = trim(substr($token, $floor));
//could be just unquoted value, or value and single-word param like noshade
$paramNames = preg_split('#s#', substr($token, $floor), -1, PREG_SPLIT_NO_EMPTY);
//$params[] = array_shift($paramNames);
foreach ($paramNames as $paramName) {//this will give us correct xhtml syntax: name="name"
$params[] = $paramName;
$params[] = $paramName;
}
}
++$charNum;
}
//if it is bare tag, then sizeof($params) will be 0, so this loop will not even start
$paramSize = sizeof($params);
for ($ctr = 0; $ctr < $paramSize; ++$ctr) {
if ($ctr % 2 == 1){// if it's odd param i.e. value
if (($params[$ctr-1] == 'src' || $params[$ctr-1] == 'href')
&& !preg_match("#^($this->allowed_prots)s*:#", $params[$ctr])) {
$params[$ctr] = $this->default_prot.':'.$params[$ctr];//neutralize possible javascript
}
} else {//if it's even param i.e. param name
$params[$ctr] = strtolower($params[$ctr]);//needed fo matching
if (!isset($this->allowed_attrs[$params[$ctr]]) OR $this->allowed_attrs[$params[$ctr]] !== TRUE) {
$params[$ctr] = '_'.$params[$ctr].'_';
$killTag = TRUE;
}
}
}
//okay, now we need to re-construct the tag
//$newTag is now set to a tag name
//it is 'bare' tag, than loop will not start
$paramsSize = sizeof($params);
for ($ctr = 0; $ctr < $paramsSize; $ctr += 2) {
$newTag .= ' '.$params[$ctr].'="'.$params[$ctr+1].'"';
}
if ($killTag) {
$newTag = "<$newTag>";
} else {
$newTag = "<$newTag>";
}
$token = $newTag;
}
foreach ($tagLog as $openedTagName) {
$tokens[] = "</$openedTagName>";
}
return join('', $tokens);
}
}
?>