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);
Комментариев пока нет.