В данный момент я работаю над проектом, в котором любой пользователь извне может принять участие. В таких условиях приходиться внимательно следить за вводом HTML кода, поэтому я потратил достаточно много времени на написание функционала, отвечающего за фильтрацию пользовательского ввода. Если нежелательные теги и можно отсеять, используя встроенную функцию PHP strip_tags(), то для проверки атрибутов разрешённых HTML тегов придётся изобретать свой велосипед. Для чтения атрибутов, их параметров, названия тегов можно использовать эту функцию:
  1. function read_htmlAttrs ($source, $mb = true)
  2. {
  3.         $m = 'strlen';
  4.         $m_s = 'substr';
  5.                
  6.         if ($mb)
  7.         {
  8.                 $m = 'mb_'.$m;
  9.                 $m_s = 'mb_'.$m_s;
  10.         }
  11.                
  12.         $srcLen = $m ($source);
  13.         $mode = 'full_idle';
  14.                
  15.         for ($x=0; $x<=$srcLen; $x  )
  16.         {
  17.                 $s = $m_s ($source, $x, 1);
  18.  
  19.                 if ($mode=='full_idle' && $s=='<')
  20.                 {
  21.                         if ($m_s ($source, $x, 2)!='</')
  22.                                 $mode = 'read_tag_name';
  23.                                
  24.                                 continue;
  25.                         }
  26.                                
  27.                 if ($mode=='read_tag_name' && preg_match('/[a-zA-Z0-9>\s] /i', $s))
  28.                 {
  29.                         if ($s=='>')
  30.                         {
  31.                                 $mode = 'close_tag';
  32.                                 continue;
  33.                         }
  34.                                        
  35.                         if(preg_match('/[\s] /i', $s))
  36.                         {
  37.                                 $mode='read_attr_name';
  38.                                 continue;
  39.                         }
  40.                                 $tmp['tagName'] .= $s;
  41.                 }
  42.                                
  43.                 if ($mode=='read_attr_name' && preg_match('/[a-zA-Z0-9>=\s] /i', $s))
  44.                 {
  45.                         if ($s=='>')
  46.                         {
  47.                                 $mode = 'close_tag';
  48.                                 continue;
  49.                         }
  50.                                        
  51.                         if ($s=='=')
  52.                         {
  53.                                $mode = 'read_param';
  54.                                 continue;
  55.                         }
  56.                        
  57.                         $tmp['attrName'] .= $s;
  58.                         continue;
  59.                 }
  60.                                
  61.                 if ($mode=='read_param' && preg_match('~[a-zA-Z0-9:>;//#-_\s] ~i', $s))
  62.                 {
  63.                         if(preg_match('/[\s] /i', $s) && $m_s ($source, $x-1, 1)!=':')
  64.                         {
  65.                                 if ($s==' ') continue;
  66.                                 $mode='read_attr_name';
  67.                                 $result['attrName'][] = trim($tmp['attrName']);
  68.                                 $tmp['param'] = str_replace (array('"',"'"), '', $tmp['param']);
  69.                                 $result['param'][] = trim($tmp['param']);
  70.                                 unset($tmp['attrName']);
  71.                                 unset($tmp['param']);
  72.                                 continue;
  73.                         }
  74.                                        
  75.                         if ($s=='/') continue;
  76.                                        
  77.                         if ($s=='>')
  78.                         {
  79.                                 $mode = 'close_tag';
  80.                                 continue;
  81.                                 }
  82.                                 $tmp['param'] .= $s;
  83.                                 continue;
  84.                 }
  85.                        
  86.                 if ($mode=='close_tag')
  87.                 {
  88.                         $mode = 'full_idle';
  89.                         $tmp['param'] = str_replace (array('"',"'"), '', $tmp['param']);
  90.                         $result['tagName'][] = trim($tmp['tagName']);
  91.                         $result['attrName'][] = trim($tmp['attrName']);
  92.                         $result['param'][] =  trim($tmp['param']);
  93.                         unset($tmp);
  94.                 }
  95.        }
  96.    return $result;
  97. }
Функция пройдётся по HTML-вводу и найдя теги (< и >) вернёт массив вида:
  1. (
  2.     [attrName] => Array
  3.         (
  4.             [0] => ass
  5.             [1] => dev
  6.         )
  7.  
  8.     [param] => Array
  9.         (
  10.             [0] => dev
  11.             [1] => ass
  12.         )
  13.  
  14.     [tagName] => Array
  15.         (
  16.             [0] => span
  17.         )
  18.  
  19. )
Это результат работы функции над:
<span ass="dev" dev="ass">ololo</span>
Этот массив можно использовать для замены нежелательных тегов, атрибутов и параметров (например style="padding: 5000px;") ;) Второй, необязательный параметр, задаёт режим чтения. По умолчанию - мультибайтовый (подойдёт для UTF-8). Простейший пример запуска после объявления функции:
$source = read_htmlAtrrs ($_POST['content']);
Пример запуска, с отключением мультибайтовости:
$source = read_htmlAtrrs ($_POST['content'], 0);


Статью пока никто не комментировал. Ваш комментарий может стать первым.

Войдите или зарегистрируйтесь, чтобы написать комментарий.