Господа, я нашел решение данной проблемы. Для тех, кто интересуется
обработкой данных на клиенте (а не на сервере) рассказываю.
Постановка задачи:
в веб-приложении есть контейнер (DIV), в который с помощью AJAX поступает строка HTML-кода "s". Источники содержимого "s" могут быть разные. Нет 100-й гарантии, что в полученном тексте отсутствует зловредный HTML-код. Такой код надо обезвредить. При этом "нормальные" теги должны отработать как положено.В примере топика к зловредному коду отношу тег meta с атрибутом refresh, что приводит к перезагрузке страницы и перенаправлению на другой сайт.
Как решить? Казалось бы просто: найти в DOM соответствующий тег и
стереть его атрибут. Для других (известных мне тегов) это работает. Но почему-то не работало для <meta>.
<html><body>
<script>
var o=document.createElement('DIV');
document.body.appendChild(o);
function mytest()
{
// присваиваем контейнеру html-строку, которая содержит что-то...
o.innerHTML = s;
};
// строка текста, которая может содержать тег meta...
var s = '<div>111<meta http-equiv="refresh" content="3;URL=http://javascript.ru"></div><div>222</div><br>333<meta http-equiv="refresh" content="3;URL=http://javascript.ru"><meta name="refresh" content="3;URL=http://vk.com">444';
</script>
<input type="button" value="Нажмите - произойдёт перезагрузка." onclick= mytest()>
</body></html>
Попробуем обезвредить:
<html><body>
<script>
var o=document.createElement('DIV');
document.body.appendChild(o);
function find_remove_META(o)
{
var metatags = o.getElementsByTagName('META');
for (var i = 0; i < metatags.length; i++)
{
// удаляем атрибут http-equiv="refresh";
// этого уже достаточно, но лучше удалить все атрибуты тега
metatags[i].removeAttribute('http-equiv');
}
};
function mytest()
{
// присваиваем контейнеру html-строку, которая содержит что-то...
o.innerHTML = s;
find_remove_META(o);
};
// строка текста, которая может содержать тег meta...
var s = '<div>111<meta http-equiv="refresh" content="3;URL=http://javascript.ru"></div><div>222</div><br>333<meta http-equiv="refresh" content="3;URL=http://javascript.ru"><meta name="refresh" content="3;URL=http://vk.com">444';
</script>
<input type="button" value="Нажмите - опять перезагрузка??" onclick= mytest()>
</body></html>
К сожалению, несмотря на удаление зловредного свойства перезагрузка произойдёт.
Так вот,
фишка в том, что если перед присвоением html-кода контейнеру предварительно извлечь его из дерева DOM (лишить парента) и только потом произвести чистку тега meta, то всё будет хорошо. По окончании процедуры вставим контейнер на своё место.
В упрощенном виде это выглядит так:
<html><body>
<script>
var o=document.createElement('DIV');
document.body.appendChild(o);
function find_remove_META(o)
{
var metatags = o.getElementsByTagName('META');
for (var i = 0; i < metatags.length; i++)
{
// удаляем атрибут http-equiv="refresh";
// этого уже достаточно, но лучше удалить все атрибуты тега
metatags[i].removeAttribute('http-equiv');
}
};
function mytest()
{
o.parentNode.removeChild(o)
// присваиваем контейнеру html-строку, которая содержит что-то...
o.innerHTML = s;
find_remove_META(o);
document.body.appendChild(o);
};
// строка текста, которая может содержать тег meta...
var s = '<div>111<meta http-equiv="refresh" content="3;URL=http://javascript.ru"></div><div>222</div><br>333<meta http-equiv="refresh" content="3;URL=http://javascript.ru"><meta name="refresh" content="3;URL=http://vk.com">444';
</script>
<input type="button" value="Нажмите - перезагрузки не должно произойти." onclick= mytest()>
</body></html>
Чтобы не манипулировать контейнером (removeChild/appendChild) можно создать "теневой" контейнер (который создан, но никуда не вставлен) и работать с ним. А после чистки html-кода брать его innerHTML и вставлять в другой, видимый на экране контейнер.