web-dev-qa-db-fra.com

supprimer la balise de script du contenu HTML

J'utilise HTML Purifier (http://htmlpurifier.org/)

Je veux juste supprimer les balises <script> uniquement. Je ne veux pas supprimer le formatage en ligne ou toute autre chose.

Comment puis-je atteindre cet objectif?

Une dernière chose, at-il un autre moyen de supprimer les balises de script de HTML

51
I-M-JM

Parce que cette question est étiquetée avec regex Je vais répondre avec la solution du pauvre homme dans cette situation:

$html = preg_replace('#<script(.*?)>(.*?)</script>#is', '', $html);

Cependant, les expressions régulières ne permettent pas d'analyser le code HTML/XML, même si vous écrivez l'expression perfect , elle finira par se rompre, cela n'en vaut pas la peine, bien que, dans certains cas, il soit utile corrigez un balisage, et comme il est avec des solutions rapides, oubliez la sécurité . Utilisez regex uniquement sur le contenu/les balises de confiance.

Rappelez-vous que tout ce que l'utilisateur doit entrer doit être considéré comme sûr .

Mieux la solution serait d'utiliser DOMDocument qui est conçu pour cela. Voici un extrait qui montre à quel point il est facile, propre (par rapport à regex), (presque) fiable et (presque) sûr de faire de même:

<?php

$html = <<<HTML
...
HTML;

$dom = new DOMDocument();

$dom->loadHTML($html);

$script = $dom->getElementsByTagName('script');

$remove = [];
foreach($script as $item)
{
  $remove[] = $item;
}

foreach ($remove as $item)
{
  $item->parentNode->removeChild($item); 
}

$html = $dom->saveHTML();

J'ai supprimé le code HTML intentionnellement, car même cela peut bouger .

119
Dejan Marjanovic

Utilisez le PHP DOMDocument parser.

$doc = new DOMDocument();

// load the HTML string we want to strip
$doc->loadHTML($html);

// get all the script tags
$script_tags = $doc->getElementsByTagName('script');

$length = $script_tags->length;

// for each tag, remove it from the DOM
for ($i = 0; $i < $length; $i++) {
  $script_tags->item($i)->parentNode->removeChild($script_tags->item($i));
}

// get the HTML string back
$no_script_html_string = $doc->saveHTML();

Cela m'a fonctionné en utilisant le document HTML suivant:

<!doctype html>
<html>
    <head>
        <meta charset="utf-8">
        <title>
            hey
        </title>
        <script>
            alert("hello");
        </script>
    </head>
    <body>
        hey
    </body>
</html>

Rappelez-vous que l’analyseur DOMDocument requiert PHP 5 ou plus.

36
Alex
$html = <<<HTML
...
HTML;
$dom = new DOMDocument();
$dom->loadHTML($html);
$tags_to_remove = array('script','style','iframe','link');
foreach($tags_to_remove as $tag){
    $element = $dom->getElementsByTagName($tag);
    foreach($element  as $item){
        $item->parentNode->removeChild($item);
    }
}
$html = $dom->saveHTML();
2
prasanthnv

J'avais eu du mal avec cette question. J'ai découvert que tu n'avais vraiment besoin que d'une seule fonction. exploser ('>', $ html); Le dénominateur commun à toute balise est <et>. Ensuite, il s’agit généralement de guillemets ("). Vous pouvez extraire des informations aussi facilement une fois que vous avez trouvé le dénominateur commun. C’est ce que j’ai trouvé:

$html = file_get_contents('http://some_page.html');

$h = explode('>', $html);

foreach($h as $k => $v){

    $v = trim($v);//clean it up a bit

    if(preg_match('/^(<script[.*]*)/ius', $v)){//my regex here might be questionable

        $counter = $k;//match opening tag and start counter for backtrace

        }elseif(preg_match('/([.*]*<\/script$)/ius', $v)){//but it gets the job done

            $script_length = $k - $counter;

            $counter = 0;

            for($i = $script_length; $i >= 0; $i--){
                $h[$k-$i] = '';//backtrace and clear everything in between
                }
            }           
        }
for($i = 0; $i <= count($h); $i++){
    if($h[$i] != ''){
    $ht[$i] = $h[$i];//clean out the blanks so when we implode it works right.
        }
    }
$html = implode('>', $ht);//all scripts stripped.


echo $html;

Je constate que cela ne fonctionne vraiment que pour les balises de script, car vous n’auriez jamais de balises de script imbriquées. Bien sûr, vous pouvez facilement ajouter plus de code effectuant la même vérification et rassembler les balises imbriquées.

Je l'appelle le codage accordéon. imploser (); exploser (); sont les moyens les plus simples d’exploiter votre logique si vous avez un dénominateur commun.

1
ClandestineCoder

utilisez la fonction str_replace pour les remplacer par un espace vide ou quelque chose comme ça

$query = '<script>console.log("I should be banned")</script>';

$badChar = array('<script>','</script>');
$query = str_replace($badChar, '', $query);

echo $query; 
//this echoes console.log("I should be banned")

?>

0

Un moyen simple en manipulant une chaîne.

$str = stripStr($str, '<script', '</script>');

function stripStr($str, $ini, $fin)
{
    while(($pos = mb_stripos($str, $ini)) !== false)
    {
        $aux = mb_substr($str, $pos + mb_strlen($ini));
        $str = mb_substr($str, 0, $pos).mb_substr($aux, mb_stripos($aux, $fin) + mb_strlen($fin));
    }

    return $str;
}
0
José Carlos PHP

Voici une variante simplifiée de la réponse de Dejan Marjanovic:

function removeTags($html, $tag) {
    $dom = new DOMDocument();
    $dom->loadHTML($html);
    foreach (iterator_to_array($dom->getElementsByTagName($tag)) as $item) {
        $item->parentNode->removeChild($item);
    }
    return $dom->saveHTML();
}

Peut être utilisé pour supprimer tout type de tag, y compris <script>:

$scriptlessHtml = removeTags($html, 'script');
0
mae

Un exemple de modification de la réponse de ctf0. Cela ne devrait faire que preg_replace une fois, mais aussi vérifier les erreurs et bloquer le code de caractère pour la barre oblique. 

$str = '<script> var a - 1; <&#47;script>'; 

$pattern = '/(script.*?(?:\/|&#47;|&#x0002F;)script)/ius';
$replace = preg_replace($pattern, '', $str); 
return ($replace !== null)? $replace : $str;  

Si vous utilisez php 7, vous pouvez utiliser l’opérateur null coalesce pour le simplifier encore plus. 

$pattern = '/(script.*?(?:\/|&#47;|&#x0002F;)script)/ius'; 
return (preg_replace($pattern, '', $str) ?? $str); 
0
tech-e

J'utiliserais BeautifulSoup s'il est disponible. Rend ce genre de chose très facile.

Ne pas essayez de le faire avec les expressions rationnelles. De cette façon se trouve la folie.

0
Malvolio
  • c'est une fusion des deux ClandestineCoder & Binh WPO.

le problème avec les flèches de balises de script est qu'elles peuvent avoir plus d'une variante 

ex. (<= &lt; = &amp;lt;) & (> = &gt; = &amp;gt;)

donc au lieu de créer un tableau de configuration avec une variante semblable à bazillion, à mon avis, une meilleure solution serait

return preg_replace('/script.*?\/script/ius', '', $text)
       ? preg_replace('/script.*?\/script/ius', '', $text)
       : $text;

cela supprimera tout ce qui ressemble à script.../script indépendamment du code de la flèche/variante et vous pourrez le tester ici https://regex101.com/r/lK6vS8/1

0
ctf0