## WP_KSES_HAIR() │ WP 1.0.0
Функция WP_KSES_HAIR
создаёт список атрибутов из строки, содержащей эти атрибуты.
Эта функция выполняет много работы. Она разбивает список атрибутов на массив с данными атрибутов и старается правильно обработать даже странные входные данные. Она добавляет кавычки вокруг значений атрибутов, если те их не содержат, чтобы упростить создание HTML-кода в соответствии с W3C спецификацией HTML. Также она удаляет недопустимые протоколы URL из значений атрибутов и уменьшает дублирование атрибутов, оставляя первый определённый (например, если вы написали foo='bar' foo='baz'
, то результат будет foo='bar'
).
**Пример производительности:**
- 1 вызов — 0.000145 сек (быстро)
- 50000 вызовов — 2.85 сек (быстро)
### Результат работы функции
Функция возвращает массив. Он содержит информацию об атрибутах после обработки.
### Использование
```php
wp_kses_hair( $attr, $allowed_protocols );
Параметры:
$attr
(строка) (обязательный) — список атрибутов из HTML элемента.$allowed_protocols
(массив строк) (обязательный) — массив допустимых протоколов URL.
Примеры использования
Пример 1: Демонстрация работы
$attrs = wp_kses_hair(' src="http://example.com/jpg.jpg" alt="aaaaa" foo=bar', 'http');
/*
$attrs будет содержать:
Array
(
[src] => Array
(
[name] => src
[value] => http://example.com/jpg.jpg
[whole] => src="http://example.com/jpg.jpg"
[vless] => n
)
[alt] => Array
(
[name] => alt
[value] => aaaaa
[whole] => alt="aaaaa"
[vless] => n
)
[foo] => Array
(
[name] => foo
[value] => bar
[whole] => foo="bar"
[vless] => n
)
)
*/
Пример 2: Протокол, который отличается от значения атрибута
Если вы укажете протокол, который отличается, функция просто удалит протокол, оставив URL относительным:
$attrs = wp_kses_hair('src=http://example.com/jpg.jpg', 'https');
/*
Получаем:
Array
(
[src] => Array
(
[name] => src
[value] => //example.com/jpg.jpg
[whole] => src="//example.com/jpg.jpg"
[vless] => n
)
)
*/
Изменения в истории
- С версии 1.0.0 — функция была впервые представлена.
Код функции
Вот реализация функции wp_kses_hair
:
function wp_kses_hair( $attr, $allowed_protocols ) {
$attrarr = array();
$mode = 0;
$attrname = '';
$uris = wp_kses_uri_attributes();
// Проходим по всему списку атрибутов.
while ( strlen( $attr ) !== 0 ) {
$working = 0; // Успешна ли последняя операция?
switch ( $mode ) {
case 0:
if ( preg_match( '/^([_a-zA-Z][-_a-zA-Z0-9:.]*)/', $attr, $match ) ) {
$attrname = $match[1];
$working = 1;
$mode = 1;
$attr = preg_replace( '/^[_a-zA-Z][-_a-zA-Z0-9:.]*/', '', $attr );
}
break;
case 1:
if ( preg_match( '/^s*=s*/', $attr ) ) { // Знак равенства.
$working = 1;
$mode = 2;
$attr = preg_replace( '/^s*=s*/', '', $attr );
break;
}
if ( preg_match( '/^s+/', $attr ) ) { // Атрибут без значения.
$working = 1;
$mode = 0;
if ( false === array_key_exists( $attrname, $attrarr ) ) {
$attrarr[ $attrname ] = array(
'name' => $attrname,
'value' => '',
'whole' => $attrname,
'vless' => 'y',
);
}
$attr = preg_replace( '/^s+/', '', $attr );
}
break;
case 2:
if ( preg_match( '%^"([^"]*)"(s+|/?$)%', $attr, $match ) ) {
// "значение"
$thisval = $match[1];
if ( in_array( strtolower( $attrname ), $uris, true ) ) {
$thisval = wp_kses_bad_protocol( $thisval, $allowed_protocols );
}
if ( false === array_key_exists( $attrname, $attrarr ) ) {
$attrarr[ $attrname ] = array(
'name' => $attrname,
'value' => $thisval,
'whole' => "$attrname="$thisval"",
'vless' => 'n',
);
}
$working = 1;
$mode = 0;
$attr = preg_replace( '/^"[^"]*"(s+|$)/', '', $attr );
break;
}
if ( preg_match( "%^'([^']*)'(s+|/?$)%", $attr, $match ) ) {
// 'значение'
$thisval = $match[1];
if ( in_array( strtolower( $attrname ), $uris, true ) ) {
$thisval = wp_kses_bad_protocol( $thisval, $allowed_protocols );
}
if ( false === array_key_exists( $attrname, $attrarr ) ) {
$attrarr[ $attrname ] = array(
'name' => $attrname,
'value' => $thisval,
'whole' => "$attrname='$thisval'",
'vless' => 'n',
);
}
$working = 1;
$mode = 0;
$attr = preg_replace( "/^'[^']*'(s+|$)/", '', $attr );
break;
}
if ( preg_match( "%^([^s"']+)(s+|/?$)%", $attr, $match ) ) {
// значение
$thisval = $match[1];
if ( in_array( strtolower( $attrname ), $uris, true ) ) {
$thisval = wp_kses_bad_protocol( $thisval, $allowed_protocols );
}
if ( false === array_key_exists( $attrname, $attrarr ) ) {
$attrarr[ $attrname ] = array(
'name' => $attrname,
'value' => $thisval,
'whole' => "$attrname="$thisval"",
'vless' => 'n',
);
}
// Добавляем кавычки для соответствия спецификации HTML от W3C.
$working = 1;
$mode = 0;
$attr = preg_replace( "%^[^s"']+(s+|$)%", '', $attr );
}
break;
} // Конец switch.
if ( 0 === $working ) { // Неправильный формат, удаляем и пробуем снова.
$attr = wp_kses_html_error( $attr );
$mode = 0;
}
} // Конец while.
if ( 1 === $mode && false === array_key_exists( $attrname, $attrarr ) ) {
// Специальный случай для атрибута без значения, например "selected".
$attrarr[ $attrname ] = array(
'name' => $attrname,
'value' => '',
'whole' => $attrname,
'vless' => 'y',
);
}
return $attrarr;
}