PHP->HTML: проверить атрибуты HTML тегов (априори, парсинг HTML)

В данный момент я работаю над проектом, в котором любой пользователь извне может принять участие. В таких условиях приходиться внимательно следить за вводом HTML кода, поэтому я потратил достаточно много времени на написание функционала, отвечающего за фильтрацию пользовательского ввода.

Если нежелательные теги и можно отсеять, используя встроенную функцию PHP strip_tags(), то для проверки атрибутов разрешённых HTML тегов придётся изобретать свой велосипед. Для чтения атрибутов, их параметров, названия тегов можно использовать эту функцию:

function read_htmlAttrs ($source, $mb = true)
{
	$m = 'strlen'; 
	$m_s = 'substr'; 
 
	if ($mb) 
	{
		$m = 'mb_'.$m; 
		$m_s = 'mb_'.$m_s; 
	}
 
	$srcLen = $m ($source);
	$mode = 'full_idle';
 
	for ($x=0; $x<=$srcLen; $x++)
	{
		$s = $m_s ($source, $x, 1);
 
		if ($mode=='full_idle' && $s=='<')
		{
			if ($m_s ($source, $x, 2)!='</') 
				$mode = 'read_tag_name';
 
				continue;
			}
 
		if ($mode=='read_tag_name' && preg_match('/[a-zA-Z0-9>\s]+/i', $s))
		{
			if ($s=='>')
			{
				$mode = 'close_tag';
				continue;
			}
 
			if(preg_match('/[\s]+/i', $s)) 
			{
				$mode='read_attr_name';
				continue;
			}
				$tmp['tagName'] .= $s;
		}
 
		if ($mode=='read_attr_name' && preg_match('/[a-zA-Z0-9>=\s]+/i', $s))
		{
			if ($s=='>')
			{
				$mode = 'close_tag';
				continue;
			}
 
			if ($s=='=')
			{
			       $mode = 'read_param';
				continue;
			}
 
                        $tmp['attrName'] .= $s;
			continue;
		}
 
		if ($mode=='read_param' && preg_match('~[a-zA-Z0-9:>;//#-_\s]+~i', $s))
		{
			if(preg_match('/[\s]+/i', $s) && $m_s ($source, $x-1, 1)!=':') 
			{
				if ($s==' ') continue;
				$mode='read_attr_name';
				$result['attrName'][] = trim($tmp['attrName']);
				$tmp['param'] = str_replace (array('"',"'"), '', $tmp['param']);
				$result['param'][] = trim($tmp['param']);
				unset($tmp['attrName']);
				unset($tmp['param']);
				continue;
			}
 
			if ($s=='/') continue;
 
			if ($s=='>')
			{
				$mode = 'close_tag';
				continue;
				}
				$tmp['param'] .= $s;
				continue;
		}
 
		if ($mode=='close_tag')
		{
			$mode = 'full_idle';
			$tmp['param'] = str_replace (array('"',"'"), '', $tmp['param']);
			$result['tagName'][] = trim($tmp['tagName']);
			$result['attrName'][] = trim($tmp['attrName']);
			$result['param'][] =  trim($tmp['param']);
			unset($tmp);
		}
       }
   return $result;
}

Функция пройдётся по HTML-вводу и найдя теги (< и >) вернёт массив вида:

Array
(
    [attrName] => Array
        (
            [0] => ass
            [1] => dev
        )
 
    [param] => Array
        (
            [0] => dev
            [1] => ass
        )
 
    [tagName] => Array
        (
            [0] => span
        )
 
)

Это результат работы функции над:

<span ass="dev" dev="ass">ololo</span>

Этот массив можно использовать для замены нежелательных тегов, атрибутов и параметров (например style=»padding: 5000px;») ;)

Второй, необязательный параметр, задаёт режим чтения. По умолчанию – мультибайтовый (подойдёт для UTF-8).

Простейший пример запуска после объявления функции:

$source = read_htmlAtrrs ($_POST['content']);

Пример запуска, с отключением мультибайтовости:

$source = read_htmlAtrrs ($_POST['content'], 0);
  • Трэкбеки закрыты
  • Комментарии (0)
  1. Комментариев пока нет.



Введите код с картинки