PHP在htmlspecialchars中显示图像异常


PHP Display Image in htmlspecialchars Exception

我有PHP函数来显示所有HTML代码。

示例:

<?php echo htmlspecialchars("<p>Welcome</p>"); ?>

然后结果将<p>Welcome</p>

现在我需要显示图像<img src="http://nl3.php.net/images/logo.php"/>,但它也会显示代码<img src="http://nl3.php.net/images/logo.php"/>

如何显示图像?

代码描述

代码会在文本中找到每个图像标签<img attr1=value1 attr2=value2 ... />,用new HtmlElement()为每个图像创建自己的图像标签-这个类只是new DOMElement()的自定义轻版本,用占位符替换原始图像标签,在每个图像都用占位符替换后,在这种情况下,我选择这个占位符{#@#IMG_' . $id .'},它对我类型的文本来说足够原始,然后将在整个文本上使用CCD_ 9函数,最后它将用新创建的图像标签替换占位符并返回文本。

代码解释

if (preg_match_all('#<img's+([^>]+?)'s?(/>|>)#i', $text, $matches)) {检查文本是否包含任何图像,如果是,可变$matches将包含三维数组,例如:

array (3)
   0 => array (6)
   |  0 => "<img alt="rolleyes" src="//t.domain.com/default/rolleyes.gif" title="rolleyes" />"
   |  1 => "<img alt="rolleyes" src="//t.domain.com/default/rolleyes.gif" title="rolleyes" />"
   |  2 => "<img alt="rolleyes" src="//t.domain.com/default/rolleyes.gif" title="rolleyes" />"
   |  3 => "<img alt="rolleyes" src="//t.domain.com/default/rolleyes.gif" title="rolleyes" />"
   |  4 => "<img alt="rolleyes" src="//t.domain.com/default/rolleyes.gif" title="rolleyes" />"
   |  5 => "<img alt="rolleyes" src="//t.domain.com/default/rolleyes.gif" title="rolleyes" />"
   1 => array (6)
   |  0 => "alt="rolleyes" src="//t.domain.com/default/rolleyes.gif" title="rolleyes"" 
   |  1 => "alt="rolleyes" src="//t.domain.com/default/rolleyes.gif" title="rolleyes"" 
   |  2 => "alt="rolleyes" src="//t.domain.com/default/rolleyes.gif" title="rolleyes"" 
   |  3 => "alt="rolleyes" src="//t.domain.com/default/rolleyes.gif" title="rolleyes"" 
   |  4 => "alt="rolleyes" src="//t.domain.com/default/rolleyes.gif" title="rolleyes"" 
   |  5 => "alt="rolleyes" src="//t.domain.com/default/rolleyes.gif" title="rolleyes"" 
   2 => array (6)
   |  0 => "/>"
   |  1 => "/>"
   |  2 => "/>"
   |  3 => "/>"
   |  4 => "/>"
   |  5 => "/>"

然后它根据原始<img />属性创建自己的图像,并将其存储在变量$images

foreach ($matches[1] as $id => $imgAttributes) {
    $img = new 'HtmlElement('img');
    $img->addAttributes($imgAttributes);
    $img->attributes([
        'src' => $img->attr('src'),
        'alt' => escapeHtml($img->attr('alt')),
        'title' => escapeHtml($img->attr('title'))
    ]);
    $images[$id] = $img->render();

在我的情况下,我只需要图像中的属性alttitlesrc,如果你不需要在alttitle或其他属性中使用转义HTML,你可以省略这部分代码,并在下一个代码行继续进行一些小的更改:

$text = str_replace($matches[0][$id], '{#@#IMG_' . $id .'}', $text);

它将用占位符'{#@#IMG_' . $id .'}'替换原始文本中的每个图像标签,因此对于exmaple,第一个图像将被替换为原始文本,如:

{#@#IMG_0}

请记住,占位符对于您的文本类型应该足够原始,并且不能包含任何特殊字符,这些字符将被HTML实体的htmlspecialchars()替换。

当每个图像都被自己的占位符替换时,我们可以将特殊字符转换为全文中的HTML实体:

$text = escapeHtml($text);

作为最后一步,我们用图像标签替换文本中的占位符:

foreach ($images as $id => $image) {
    $text = str_replace('{#@#IMG_' . $id . '}', $image, $text);
}

完整代码

function escapeHtml($text)
{
   return htmlspecialchars($text, ENT_QUOTES, 'UTF-8', false);
}
function escapeHtmlKeepImages($text)
{
   if (preg_match_all('#<img's+([^>]+?)'s?(/>|>)#i', $text, $matches)) {
      $images = [];
      foreach ($matches[1] as $id => $imgAttributes) {
            $img = new 'HtmlElement('img');
            $img->addAttributes($imgAttributes);
            $img->attributes([
               'src' => $img->attr('src'),
               'alt' => escapeHtml($img->attr('alt')),
               'title' => escapeHtml($img->attr('title'))
            ]);
            $images[$id] = $img->render();
            $text = str_replace($matches[0][$id], '{#@#IMG_' . $id .'}', $text);
        }
        $text = escapeHtml($text);
        foreach ($images as $id => $image) {
            $text = str_replace('{#@#IMG_' . $id . '}', $image, $text);
        }
    } else {
        $text = escapeHtml($text);
    }
    return $text;
}

不需要处理属性alttitle和其他属性的版本,例如


$text = '
<strong>hello</strong>
<img src="image.gif" alt="something" >><3
how are you?
<img src="signature.gif" alt="signature"  title="signature"/>
';
function  escapeHtml($text)
{
    return htmlspecialchars($text, ENT_QUOTES, 'UTF-8', false);
}
function escapeHtmlKeepImages($text)
{
    if (preg_match_all('#<img's+([^>]+?)'s?(/>|>)#i', $text, $matches)) {
        array_map(
            function ($id, $img) use (&$text) {
                $text = str_replace($img, '{#@#IMG_' . $id . '}', $text);
            },
            array_keys($matches[0]), $matches[0]
        );
        $text = escapeHtml($text);
        array_map(
            function ($id, $img) use (&$text) {
                $text = str_replace('{#@#IMG_' . $id . '}', $img, $text);
            },
            array_keys($matches[0]), $matches[0]
        );
    } else {
        $text = escapeHtml($text);
    }
    return $text;
}
echo escapeHtmlKeepImages($text);

输出:

&lt;strong&gt;hello&lt;/strong&gt;
<img src="image.gif" alt="something" >&gt;&lt;3
how are you?
<img src="signature.gif" alt="signature"  title="signature"/>

我也是PHP和html的初学者。让我试着解决这个问题。

正如我们所看到的"欢迎"的结果,您可以更改为

    <p><?php echo htmlspecialchars("Welcome"); ?></p>

它只显示"欢迎"。我们可以使用与相同的方法来处理

    <img <?php echo htmlspecialchars("src='http://nl3.php.net/images/logo.php");?>/> 

虽然它不是一种好的编程风格,但您可以先解决问题,然后再研究preg_match()。干杯