2009-04-20 20 views

Respuesta

5

HTML Purifier es una de las mejores herramientas para el saneamiento de HTML con PHP.

14

Aunque hay mejores maneras, en realidad se podrían dañar los argumentos de las etiquetas HTML con una expresión regular:

<?php 
function stripArgumentFromTags($htmlString) { 
    $regEx = '/([^<]*<\s*[a-z](?:[0-9]|[a-z]{0,9}))(?:(?:\s*[a-z\-]{2,14}\s*=\s*(?:"[^"]*"|\'[^\']*\'))*)(\s*\/?>[^<]*)/i'; // match any start tag 

    $chunks = preg_split($regEx, $htmlString, -1, PREG_SPLIT_DELIM_CAPTURE); 
    $chunkCount = count($chunks); 

    $strippedString = ''; 
    for ($n = 1; $n < $chunkCount; $n++) { 
     $strippedString .= $chunks[$n]; 
    } 

    return $strippedString; 
} 
?> 

Lo anterior probablemente podría ser escrito en menos caracteres, pero hace el trabajo (rápido y sucio) .

-1

También puede consultar html purificador. Es cierto que está bastante hinchado y puede que no se ajuste a tus necesidades si solo contempla este ejemplo específico, pero ofrece una purificación más o menos "a prueba de balas" de posibles html hostiles. También puede elegir permitir o no permitir ciertos atributos (es altamente configurable).

http://htmlpurifier.org/

9

Gaza atributos usando SimpleXML (Estándar en PHP5)

<?php 

// define allowable tags 
$allowable_tags = '<p><a><img><ul><ol><li><table><thead><tbody><tr><th><td>'; 
// define allowable attributes 
$allowable_atts = array('href','src','alt'); 

// strip collector 
$strip_arr = array(); 

// load XHTML with SimpleXML 
$data_sxml = simplexml_load_string('<root>'. $data_str .'</root>', 'SimpleXMLElement', LIBXML_NOERROR | LIBXML_NOXMLDECL); 

if ($data_sxml) { 
    // loop all elements with an attribute 
    foreach ($data_sxml->xpath('descendant::*[@*]') as $tag) { 
     // loop attributes 
     foreach ($tag->attributes() as $name=>$value) { 
      // check for allowable attributes 
      if (!in_array($name, $allowable_atts)) { 
       // set attribute value to empty string 
       $tag->attributes()->$name = ''; 
       // collect attribute patterns to be stripped 
       $strip_arr[$name] = '/ '. $name .'=""/'; 
      } 
     } 
    } 
} 

// strip unallowed attributes and root tag 
$data_str = strip_tags(preg_replace($strip_arr,array(''),$data_sxml->asXML()), $allowable_tags); 

?> 
+0

Esto funciona muy bien, pero sólo si su entrada html está formada correctamente xml. De lo contrario, deberá realizar una limpieza previa de la entrada html antes de realizar el análisis. Esto puede ser bastante tedioso para desinfectar si no tienes el control de la entrada html de origen tampoco. –

7

Aquí es una función que le permitirá se tira de todos los atributos excepto los que desea:

function stripAttributes($s, $allowedattr = array()) { 
    if (preg_match_all("/<[^>]*\\s([^>]*)\\/*>/msiU", $s, $res, PREG_SET_ORDER)) { 
    foreach ($res as $r) { 
    $tag = $r[0]; 
    $attrs = array(); 
    preg_match_all("/\\s.*=(['\"]).*\\1/msiU", " " . $r[1], $split, PREG_SET_ORDER); 
    foreach ($split as $spl) { 
     $attrs[] = $spl[0]; 
    } 
    $newattrs = array(); 
    foreach ($attrs as $a) { 
     $tmp = explode("=", $a); 
     if (trim($a) != "" && (!isset($tmp[1]) || (trim($tmp[0]) != "" && !in_array(strtolower(trim($tmp[0])), $allowedattr)))) { 

     } else { 
      $newattrs[] = $a; 
     } 
    } 
    $attrs = implode(" ", $newattrs); 
    $rpl = str_replace($r[1], $attrs, $tag); 
    $s = str_replace($tag, $rpl, $s); 
    } 
    } 
    return $s; 
} 

En el ejemplo sería:

echo stripAttributes('<p class="one" otherrandomattribute="two">'); 

o si, por ejemplo. desee mantener atributo "class":

echo stripAttributes('<p class="one" otherrandomattribute="two">', array('class')); 

O

Suponiendo que está a enviar un mensaje a una bandeja de entrada y que componen su mensaje con CKeditor, puede asignar la función de la siguiente manera y el eco a la $ variable de mensaje antes de enviar. Tenga en cuenta que la función con el nombre stripAttributes() quitará todas las etiquetas html que sean innecesarias. Lo intenté y funcionó bien. Solo vi el formato que agregué como negrita e.t.c.

$message = stripAttributes($_POST['message']); 

o que pueda echo $message; para la vista previa.

5

Honestamente creo que la única manera sensata de hacerlo es utilizar una lista de atributos y en la biblioteca HTML Purifier. Script de ejemplo aquí:

<html><body> 

<?php 

require_once '../includes/htmlpurifier-4.5.0-lite/library/HTMLPurifier/Bootstrap.php'; 
spl_autoload_register(array('HTMLPurifier_Bootstrap', 'autoload')); 

$config = HTMLPurifier_Config::createDefault(); 
$config->set('HTML.Allowed', 'p,b,a[href],i,br,img[src]'); 
$config->set('URI.Base', 'http://www.example.com'); 
$config->set('URI.MakeAbsolute', true); 

$purifier = new HTMLPurifier($config); 

$dirty_html = " 
    <a href=\"http://www.google.de\">broken a href link</a 
    fnord 

    <x>y</z> 
    <b>c</p> 
    <script>alert(\"foo!\");</script> 

    <a href=\"javascript:alert(history.length)\">Anzahl besuchter Seiten</a> 
    <img src=\"www.example.com/bla.gif\" /> 
    <a href=\"http://www.google.de\">missing end tag 
ende 
"; 

$clean_html = $purifier->purify($dirty_html); 

print "<h1>dirty</h1>"; 
print "<pre>" . htmlentities($dirty_html) . "</pre>"; 

print "<h1>clean</h1>"; 
print "<pre>" . htmlentities($clean_html) . "</pre>"; 

?> 

</body></html> 

Esto produce el siguiente limpia, normas conformes fragmento de HTML:

<a href="http://www.google.de">broken a href link</a>fnord 

y 
<b>c 
<a>Anzahl besuchter Seiten</a> 
<img src="http://www.example.com/www.example.com/bla.gif" alt="bla.gif" /><a href="http://www.google.de">missing end tag 
ende 
</a></b> 

En su caso, la lista blanca serían:

$config->set('HTML.Allowed', 'p'); 
Cuestiones relacionadas