71 votes

supprimer la balise script du contenu HTML

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

Je veux juste enlever <script> uniquement. Je ne veux pas supprimer la mise en forme en ligne ou toute autre chose.

Comment puis-je y parvenir ?

Une dernière chose : existe-t-il un autre moyen de supprimer les balises script du HTML ?

3 votes

N'oubliez pas que les balises script ne sont pas les seules parties vulnérables du HTML.

0 votes

Oui, je sais qu'il y a d'autres parties vulnérables aussi, mais j'ai juste besoin d'enlever les balises script.

3 votes

Lire este . Il vous aidera à

3voto

Essayez ceci complet y flexible solution. Elle fonctionne parfaitement, et est basée en partie par un peu de réponses précédentes, mais contient des contrôles de validation supplémentaires, et se débarrasse de implicite HTML de la loadHTML(...) fonction. Elle est divisée en deux fonctions distinctes ( un avec une dépendance précédente, donc ne pas réordonner/réorganiser ) afin que vous puissiez l'utiliser avec plusieurs balises HTML que vous souhaitez supprimer simultanément (c'est-à-dire pas seulement 'script' tags). Par exemple removeAllInstancesOfTag(...) La fonction accepte un array de noms de balises, ou optionnellement un seul en tant que string . Donc, sans plus attendre, voici le code :

/* Remove all instances of a particular HTML tag (e.g. <script>...</script>) from a variable containing raw HTML data. [BEGIN] */

/* Usage Example: $scriptless_html = removeAllInstancesOfTag($html, 'script'); */

if (!function_exists('removeAllInstancesOfTag'))
    {
        function removeAllInstancesOfTag($html, $tag_nm)
            {
                if (!empty($html))
                    {
                        $html = mb_convert_encoding($html, 'HTML-ENTITIES', 'UTF-8'); /* For UTF-8 Compatibility. */
                        $doc = new DOMDocument();
                        $doc->loadHTML($html,LIBXML_HTML_NOIMPLIED|LIBXML_HTML_NODEFDTD|LIBXML_NOWARNING);

                        if (!empty($tag_nm))
                            {
                                if (is_array($tag_nm))
                                    {
                                        $tag_nms = $tag_nm;
                                        unset($tag_nm);

                                        foreach ($tag_nms as $tag_nm)
                                            {
                                                $rmvbl_itms = $doc->getElementsByTagName(strval($tag_nm));
                                                $rmvbl_itms_arr = [];

                                                foreach ($rmvbl_itms as $itm)
                                                    {
                                                        $rmvbl_itms_arr[] = $itm;
                                                    };

                                                foreach ($rmvbl_itms_arr as $itm)
                                                    {
                                                        $itm->parentNode->removeChild($itm);
                                                    };
                                            };
                                    }
                                else if (is_string($tag_nm))
                                    {
                                        $rmvbl_itms = $doc->getElementsByTagName($tag_nm);
                                        $rmvbl_itms_arr = [];

                                        foreach ($rmvbl_itms as $itm)
                                            {
                                                $rmvbl_itms_arr[] = $itm;
                                            };

                                        foreach ($rmvbl_itms_arr as $itm)
                                            {
                                                $itm->parentNode->removeChild($itm); 
                                            };
                                    };
                            };

                        return $doc->saveHTML();
                    }
                else
                    {
                        return '';
                    };
            };
    };

/* Remove all instances of a particular HTML tag (e.g. <script>...</script>) from a variable containing raw HTML data. [END] */

/* Remove all instances of dangerous and pesky <script> tags from a variable containing raw user-input HTML data. [BEGIN] */

/* Prerequisites: 'removeAllInstancesOfTag(...)' */

if (!function_exists('removeAllScriptTags'))
    {
        function removeAllScriptTags($html)
            {
                return removeAllInstancesOfTag($html, 'script');
            };
    };

/* Remove all instances of dangerous and pesky <script> tags from a variable containing raw user-input HTML data. [END] */

Et voici un test exemple d'utilisation :

$html = 'This is a JavaScript retention test.<br><br><span id="chk_frst_scrpt">Congratulations! The first \'script\' tag was successfully removed!</span><br><br><span id="chk_secd_scrpt">Congratulations! The second \'script\' tag was successfully removed!</span><script>document.getElementById("chk_frst_scrpt").innerHTML = "Oops! The first \'script\' tag was NOT removed!";</script><script>document.getElementById("chk_secd_scrpt").innerHTML = "Oops! The second \'script\' tag was NOT removed!";</script>';
echo removeAllScriptTags($html);

J'espère que ma réponse aidera vraiment quelqu'un. Bon courage !

2voto

Binh WPO Points 94

Plus court :

$html = preg_replace("/<script.*?\/script>/s", "", $html);

Lorsque l'on utilise une expression rationnelle, les choses peuvent mal tourner, il est donc plus sûr de procéder de cette manière :

$html = preg_replace("/<script.*?\/script>/s", "", $html) ? : $html;

Ainsi, lorsque l'"accident" se produit, nous obtenons l'original $html au lieu de la chaîne vide.

2voto

tech-e Points 349

Un exemple modifiant la réponse de ctf0. Cela ne devrait faire le preg_replace qu'une seule fois mais aussi vérifier les erreurs et bloquer le code char pour le forward slash.

$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 simplifier encore plus les choses.

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

0 votes

Cela a un inconvénient qui est que si quelqu'un utilise des fichiers d'un dossier script dans le html comme : <img src="/script/email/img.jpg"> <img src="/script/email/img-0.jpg">. Cela créera une capture qui supprimera tout ce qui se trouve entre eux.

2voto

relipse Points 243
function remove_script_tags($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();
    $html = preg_replace('/<!DOCTYPE.*?<html>.*?<body><p>/ims', '', $html);
    $html = str_replace('</p></body></html>', '', $html);
    return $html;
}

La réponse de Dejan était bonne, mais saveHTML() ajoute des balises doctype et body inutiles, ceci devrait permettre de s'en débarrasser. Voir https://3v4l.org/82FNP

3 votes

Non, c'est loadHTML(...) qui l'ajoute. Voir LIBXML_HTML_NODEFDTD y LIBXML_HTML_NOIMPLIED ici : php.net/manual/fr/libxml.constants.php

0 votes

Ok merci James pour la clarification !

1voto

Je me suis débattu avec cette question. J'ai découvert que vous n'avez vraiment besoin que d'une seule fonction. explode('>', $html) ; Le seul dénominateur commun à toute balise est < et >. Ensuite, il s'agit généralement de guillemets ( " ). Vous pouvez extraire des informations si facilement une fois que vous trouvez le dénominateur commun. Voici 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 vois que cela ne fonctionne vraiment que pour les balises script car vous n'aurez jamais de balises script imbriquées. Bien sûr, vous pouvez facilement ajouter plus de code qui fait la même vérification et rassemble les balises imbriquées.

J'appelle cela le codage en accordéon. implode();explode() ; sont les moyens les plus faciles de faire circuler votre logique si vous avez un dénominateur commun.

0 votes

Vous ne devez pas utiliser Regex pour trouver les balises script dans le code HTML. Utilisez DOMDocument pour analyser le document entier et trouver les balises script à supprimer.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X