简体   繁体   中英

Laravel - escape all HTML characters apart from <img> and <br> tags

I am creating a forum to which I only want img tags to be displayed and all other tags to be securely escaped, but not deleted. What is the best method to accomplish this task other than creating a function from scratch?

I have tried using HTML Purifier, but it strips all the unwanted tags and only keeps the desired ones. Furthermore, I tried other functions such as strip_tags and htmlentities and also the escape operator used in blaede ( {{ }} ) but these functions will either strip the unwanted tags (which I want them to be escaped instead) or escape all the tags (which I also don't want to because I want to keep the <img> and <br> tags. I seen other similar asked questions, but none of them really helped me unfortunately.

So far what I do is using: $post->content = Purifier::clean($request->content); To remove the unwanted tags temporary to prevent XSS.

I expect after the data the user has inserted to be displayed like the following:

Hi all
<script>alert('hi all')</script>
<img src='sun.png'/>

While now the following is being displayed

Hi all
 hi all 
<img src='sun.png'/>

UPDATE:

My question is not duplicated to the question which was marked. Hopefully a moderator will resolve this.

You need to replace <img> and <br> tags with some string placeholders first, do the escaping with htmlentities() and then restore original <img> and <br> tags back. Here's how you can do the trick:

$string = "Hi<br> all<script>alert('hi all')</script><img src='sun.png'/>";

// First we cleanup our string from possible pre-existing placeholders (like $$0, $$1 etc).
$string = preg_replace('~\$\$[0-9]+~', '', $string);

// Then we replace all <img> and <br> tags with such placeholders while
// storing them into $placeholders array.
$placeholders = [];
$i = 0;
$string = preg_replace_callback('~(<img[^>]*>(</img>)?|<br[^>]*>)~', function ($matches) use (&$placeholders, &$i) {
    $key = '$$'.$i++;
    $placeholders[$key] = $matches[0];

    return $key;
}, $string);

// Our string no longer has <img> and <br> tags so we can safely escape
// the rest.
$string = htmlentities($string);

// Lastly we restore <img> and <br> tags by swapping them back instead of their respective placeholders.
foreach ($placeholders as $key => $placeholder) {
    $string = str_replace($key, $placeholder, $string);
}

echo $string;

This code will produce the result:

Hi<br> all&lt;script&gt;alert('hi all')&lt;/script&gt;<img src='sun.png'/>

This solution heavily relies on using regular expressions, so I highly advise you learning on this topic in case later on you will have a need to tweak the code.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM