Mira, hice una función, aver que opinas:
Si el usuario ingresa caracteres no permitidos o etiquetas falsas o etiquetas mal formadas o sin cerrar, etc arrojará una excepción y retornará un contendo en blanco, asi que desde el código final dices que si el input está en blanco entonces el usuario debe volver a ingresar el texto.
Claramente esto funciona para habilitar etiquetas HTML y sólo sirve si el navegador ya envía el contenido en este formato, quiere decir que el usuario tendrá que ingresar su mensaje en un editor thml reducido así como wordpress, por ejemplo usando ckeditor. Así ya no necesitarás transformar las urls a enlaces, simplemente haces que el sitio web desde el lado del input ya integre formato html, o si no, también sirve para sanitizar tus conversiones de enlace con expresión regular y habilitar únicamente a los enlaces, pero sería un tanto redundante, en ves de eso es mejor que el input ya venga con los enlaces construidos por el mismo usuario o creados por javascript.
Saludos.
Código (php) [Seleccionar]
<?php
function parse($string){
// Listado de etiquetas y propiedades permitidas
$availables = array(
// [etiqueta], [propiedades,]
'p' => array('style', 'class', 'id'),
'a' => array('href', 'style', 'class', 'id', 'title'),
'span' => array('style', 'class'),
'b' => array('style', 'class'),
'i' => array('style', 'class'),
's' => array('style', 'class'),
'table' => array('style', 'class', 'id', 'rows', 'cols', 'width'),
'thead' => array(),
'tbody' => array(),
'tr' => array(),
'td' => array(),
'div' => array('style', 'class', 'id'),
'ul' => array('style', 'class', 'id'),
'li' => array('style', 'class')
);
try
{
$dom = new DOMDocument();
@$dom->loadHTML('
<html>
<body>
<div>'.$string.'</div>
</body>
</html>
');
$string = null; // Libera la memoria
}
catch(Exception $e)
{
// Contenido corrupto, etiquetas sin cerrar,
// intento de XSS, etc.
return '';
}
$id = 0;
foreach($dom->getElementsByTagNameNS('', '*') as $tag)
{
$id++;
if($id < 4)
{
continue;
}
if(!in_array($tag->nodeName, array_keys($availables)))
{
// Etiqueta no permitida
$escaped = $dom->createTextNode(htmlspecialchars(
$dom->saveHTML($tag),
ENT_QUOTES
));
$tag->parentNode->replaceChild($escaped, $tag);
}
else
{
// Etiqueta permitida
// Busca todos los atributos de la etiqueta
foreach($tag->attributes as $attribute)
{
// Propiedad no permitida?
if(!in_array(
strtolower($attribute->name),
$availables[strtolower($tag->nodeName)]
))
{
// Elimina el atributo no permitido
$tag->removeAttribute($attribute->name);
}
}
}
}
return trim(substr($dom->saveHTML(
$dom->getElementsByTagName('body')[0]->childNodes[1]
), 5, -6));
}
echo parse('
<ul>
<li><a onclick="alert(0)" style="color:red;"
href="http://google.com/">http://google.com/</a></li>
<li>http://google.com/</li>
<li><script>alert(0)//http://google.com/</script></li>
<li><b>http://google.com/</b></li>
</ul>
');
Código [Seleccionar]
<ul>
<li><a style="color:red;" href="http://google.com/">http://google.com/</a></li>
<li>http://google.com/</li>
<li>&lt;script&gt;alert(0)//http://google.com/&lt;/script&gt;</li>
<li><b>http://google.com/</b></li>
</ul>
Si el usuario ingresa caracteres no permitidos o etiquetas falsas o etiquetas mal formadas o sin cerrar, etc arrojará una excepción y retornará un contendo en blanco, asi que desde el código final dices que si el input está en blanco entonces el usuario debe volver a ingresar el texto.
Claramente esto funciona para habilitar etiquetas HTML y sólo sirve si el navegador ya envía el contenido en este formato, quiere decir que el usuario tendrá que ingresar su mensaje en un editor thml reducido así como wordpress, por ejemplo usando ckeditor. Así ya no necesitarás transformar las urls a enlaces, simplemente haces que el sitio web desde el lado del input ya integre formato html, o si no, también sirve para sanitizar tus conversiones de enlace con expresión regular y habilitar únicamente a los enlaces, pero sería un tanto redundante, en ves de eso es mejor que el input ya venga con los enlaces construidos por el mismo usuario o creados por javascript.
Saludos.