0

我有一个当前是纯文本的评论表单。这很好也很简单,因为我可以使用 strip_tags 和 htmlspecialchars 来去除任何与 HTML 类似的东西。

但是,有计划将其转换为支持多个标签的 HTML 表单<a><b><p><h3>……等等。

我看到的问题是,即使 strip_tag'ing 输入并只保留这些标签仍然会让我对标签内的 XSS 和 jscript 持开放态度。

我知道 HTML Purifier 可以用来解决这个问题,但它看起来真的很笨重、很慢,而且我很难相信没有更好的方法?

我曾考虑使用 BBCode 编辑器,但假设这些将代码作为 BB 插入到数据库中,那么我将如何将其从 BB 转换回 HTML 以显示它?

4

2 回答 2

1

如果您有时间和精力编写自己的验证方案,请考虑下一次,因为这非常复杂。

首先,看看如果不使用递归会发生什么。

坏词:CopyThis

CopyCopyThisThis

这让你

CopyThis

坏话...

于 2013-08-05T09:18:31.340 回答
1

BBCode对于您的问题确实是一个非常简单且有用的解决方案。

我正在使用MarkItUp!编辑器,但您肯定可以找到许多其他人。

然后我将如何将它从 BB 转换回 HTML 以显示它?

答案很简单:你可以使用preg_replace它。

我之前自己实现了这个,所以我可以让你使用我的解析器代码。它翻译基本标签,以及一些自定义标签,如[center]. 添加您自己的标签或替换当前标签非常容易。

该脚本由一个带有正则表达式和替换的巨大数组以及一个preg_replace调用组成。

function replaceBBcode($str) {
    $replace = array(

        // inline text formats
        '/\[b\](.*?)\[\/b\]/is'                         => '<b>$1</b>',
        '/\[i\](.*?)\[\/i\]/is'                         => '<i>$1</i>',
        '/\[u\](.*?)\[\/u\]/is'                         => '<u>$1</u>',
        '/\[s\](.*?)\[\/s\]/is'                         => '<s>$1</s>',
        '/\[sup\](.*?)\[\/sup\]/is'                     => '<sup>$1</sup>',
        '/\[sub\](.*?)\[\/sub\]/is'                     => '<sub>$1</sub>',

        // headings
        '/\[h1\](.*?)\[\/h1\]/is'                       => '<h1>$1</h1>',
        '/\[h2\](.*?)\[\/h2\]/is'                       => '<h2>$1</h2>',
        '/\[h3\](.*?)\[\/h3\]/is'                       => '<h3>$1</h3>',
        '/\[h4\](.*?)\[\/h4\]/is'                       => '<h4>$1</h4>',
        '/\[h5\](.*?)\[\/h5\]/is'                       => '<h5>$1</h5>',

        // formatting tags
        '/\[(?:hr|line)\]/is'                           => '<hr />',
        '/\[br\/?\]/is'                                 => '<br />',

        // links
        '/\[url=([^\]]+)\](.*?)\[\/url\]/is'            => '<a href="$1">$2</a>',
        '/\[link=([^\]]+)\](.*?)\[\/link\]/is'          => '<a href="$1">$2</a>',
        '/\[url\](.*?)\[\/url\]/is'                     => '<a href="$1" title="$1">$1</a>',
        '/\[link\](.*?)\[\/link\]/is'                   => '<a href="$1" title="$1">$1</a>',

        '/\[img=([^\]]+)\]/is'                          => '<img src="$1" alt="" />',

        // text blocks and block formats
        '/\[font=([^\]]+)\](.*?)\[\/font\]/is'          => '<span style="font-family: $1;">$2</span>',
        '/\[size=([0-9]+)\](.*?)\[\/size\]/is'          => '<span style="font-size: $1pt;">$2</span>',
        '/\[color=([^\]]+)\](.*?)\[\/color\]/is'        => '<span style="color: $1;">$2</span>',
        '/\[bgcolor=([^\]]+)\](.*?)\[\/bgcolor\]/is'    => '<span style="background-color: $1;">$2</span>',
        '/\[p\](.*?)\[\/p\]/is'                         => '<p>$1</p>',

        // alignment blocks
        '/\[align=(left|center|right|justify)\](.*?)\[\/align\]/is'     => '<div style="text-align: $1;">$2</div>',
        '/\[center\](.*?)\[\/center\]/is'               => '<div style="text-align: center;">$1</div>',
        '/\[left\](.*?)\[\/left\]/is'                   => '<div style="text-align: left;">$1</div>',
        '/\[right\](.*?)\[\/right\]/is'                 => '<div style="text-align: right;">$1</div>',
        '/\[justify\](.*?)\[\/justify\]/is'             => '<div style="text-align: justify;">$1</div>',

        // lists
        '/\[list=(disc|circle|square)\](.*?)\[\/list\]/is'  => '<ul style="list-style-type:$1;">$2</ul>',
        '/\[list\](.*?)\[\/list\]/is'                   => '<ul>$1</ul>',
        '/\[list=a\](.*?)\[\/list\]/s'                  => '<ol style="list-style-type:lower-alpha;">$1</ol>',
        '/\[LIST=a\](.*?)\[\/LIST\]/s'                  => '<ol style="list-style-type:lower-alpha;">$1</ol>',
        '/\[list=A\](.*?)\[\/list\]/s'                  => '<ol style="list-style-type:upper-alpha;">$1</ol>',
        '/\[LIST=A\](.*?)\[\/LIST\]/s'                  => '<ol style="list-style-type:upper-alpha;">$1</ol>',
        '/\[list=1\](.*?)\[\/list\]/is'                 => '<ol style="list-style-type:decimal;">$1</ol>',
        '/\[list=I\](.*?)\[\/list\]/is'                 => '<ol style="list-style-type:upper-roman;">$1</ol>',
        '/\[\*\]/is'                                    => '<li>',

        // videos
        '/\[(?:youtube|video|media|movie){1}\](?:https?\:\/\/)?(?:www\.)?(?:youtube\.com\/watch\?v=|youtube\.com\/v\/|youtu\.be\/)?([a-z0-9\-\_]+)\[\/(?:youtube|video|media|movie){1}\]/is'
                    => '<iframe width="560" height="315" src="http://www.youtube.com/embed/$1?wmode=opaque" frameborder="0" allowfullscreen></iframe>',
    );

    // do the tags
    $str = preg_replace (array_keys($replace), array_values($replace), $str);  

    return $str; 
}

但是,这不适用于嵌套标签。为了用嵌套标签替换代码,我使用了这样的循环:

$str = "... text to process ...";

// remove unwanted tags
$str = strip_tags($str);

// make entities of special chars (not quotes) 
$str = htmlentities($str, ENT_NOQUOTES, $encoding = 'UTF-8');

$str_old="";

do {
    $str_old=$str;
    $str=replaceBBcode($str);
} while ($str_old != $str);

// now $str contains the final html tags
于 2013-08-04T21:48:22.030 回答