{
$preTag = null;
$postTag = $source;
$currentSpace = false;
$attr = '';
$tagOpen_start = strpos($source, '<');
while ($tagOpen_start !== false)
{
$preTag .= substr($postTag, 0, $tagOpen_start);
$postTag = substr($postTag, $tagOpen_start);
$fromTagOpen = substr($postTag, 1);
$tagOpen_end = strpos($fromTagOpen, '>');
$nextOpenTag = (strlen($postTag) > $tagOpen_start) ? strpos($postTag, '<', $tagOpen_start + 1) : false;
if (($nextOpenTag !== false) && ($nextOpenTag < $tagOpen_end))
{
$postTag = substr($postTag, 0, $tagOpen_start) . substr($postTag, $tagOpen_start + 1);
$tagOpen_start = strpos($postTag, '<');
continue;
}
if ($tagOpen_end === false)
{
$postTag = substr($postTag, $tagOpen_start + 1);
$tagOpen_start = strpos($postTag, '<');
continue;
}
$tagOpen_nested = strpos($fromTagOpen, '<');
if (($tagOpen_nested !== false) && ($tagOpen_nested < $tagOpen_end))
{
$preTag .= substr($postTag, 0, ($tagOpen_nested + 1));
$postTag = substr($postTag, ($tagOpen_nested + 1));
$tagOpen_start = strpos($postTag, '<');
continue;
}
$tagOpen_nested = (strpos($fromTagOpen, '<') + $tagOpen_start + 1);
$currentTag = substr($fromTagOpen, 0, $tagOpen_end);
$tagLength = strlen($currentTag);
$tagLeft = $currentTag;
$attrSet = array();
$currentSpace = strpos($tagLeft, ' ');
if (substr($currentTag, 0, 1) == '/')
{
$isCloseTag = true;
list ($tagName) = explode(' ', $currentTag);
$tagName = substr($tagName, 1);
}
else
{
$isCloseTag = false;
list ($tagName) = explode(' ', $currentTag);
}
if ((!preg_match("/^[a-z][a-z0-9]*$/i", $tagName)) || (!$tagName) || ((in_array(strtolower($tagName), $this->tagBlacklist)) && ($this->xssAuto)))
{
$postTag = substr($postTag, ($tagLength + 2));
$tagOpen_start = strpos($postTag, '<');
continue;
}
while ($currentSpace !== false)
{
$attr = '';
$fromSpace = substr($tagLeft, ($currentSpace + 1));
$nextEqual = strpos($fromSpace, '=');
$nextSpace = strpos($fromSpace, ' ');
$openQuotes = strpos($fromSpace, '"');
$closeQuotes = strpos(substr($fromSpace, ($openQuotes + 1)), '"') + $openQuotes + 1;
$startAtt = '';
$startAttPosition = 0;
if (preg_match('#\s*=\s*\"#', $fromSpace, $matches, PREG_OFFSET_CAPTURE))
{
$startAtt = $matches[0][0];
$startAttPosition = $matches[0][1];
$closeQuotes = strpos(substr($fromSpace, ($startAttPosition + strlen($startAtt))), '"') + $startAttPosition + strlen($startAtt);
$nextEqual = $startAttPosition + strpos($startAtt, '=');
$openQuotes = $startAttPosition + strpos($startAtt, '"');
$nextSpace = strpos(substr($fromSpace, $closeQuotes), ' ') + $closeQuotes;
}
if ($fromSpace != '/' && (($nextEqual && $nextSpace && $nextSpace < $nextEqual) || !$nextEqual))
{
if (!$nextEqual)
{
$attribEnd = strpos($fromSpace, '/') - 1;
}
else
{
$attribEnd = $nextSpace - 1;
}
if ($attribEnd > 0)
{
$fromSpace = substr($fromSpace, $attribEnd + 1);
}
}
if (strpos($fromSpace, '=') !== false)
{
if (($openQuotes !== false) && (strpos(substr($fromSpace, ($openQuotes + 1)), '"') !== false))
{
$attr = substr($fromSpace, 0, ($closeQuotes + 1));
}
else
{
$attr = substr($fromSpace, 0, $nextSpace);
}
}
else
{
if ($fromSpace != '/')
{
$attr = substr($fromSpace, 0, $nextSpace);
}
}
if (!$attr && $fromSpace != '/')
{
$attr = $fromSpace;
}
$attrSet[] = $attr;
$tagLeft = substr($fromSpace, strlen($attr));
$currentSpace = strpos($tagLeft, ' ');
}
$tagFound = in_array(strtolower($tagName), $this->tagsArray);
if ((!$tagFound && $this->tagsMethod) || ($tagFound && !$this->tagsMethod))
{
if (!$isCloseTag)
{
$preTag .= '<' . $tagName;
for ($i = 0, $count = count($attrSet); $i < $count; $i++)
{
$preTag .= ' ' . $attrSet[$i];
}
if (strpos($fromTagOpen, '</' . $tagName))
{
$preTag .= '>';
}
else
{
$preTag .= ' />';
}
}
else
{
$preTag .= '</' . $tagName . '>';
}
}
$postTag = substr($postTag, ($tagLength + 2));
$tagOpen_start = strpos($postTag, '<');
}
if ($postTag != '<')
{
$preTag .= $postTag;
}
return $preTag;
}