顾名思义,strip_tags
应该删除所有 HTML 标签。我们可以证明它的唯一方法是分析源代码。下一个分析适用于strip_tags('...')
调用,没有白名单标签的第二个参数。
首先,关于 HTML 标签的一些理论:标签以 a 开头,<
后跟非空白字符。如果此字符串以 a 开头?
,则不应对其进行解析。如果此字符串以 a 开头!--
,则将其视为注释,并且不应解析以下文本。注释以 结尾-->
,在此类注释中,允许使用<
和等字符。属性可以出现在标签中,它们的值可以选择用引号字符(或)>
包围。如果存在这样的引用,则必须关闭它,否则如果遇到 a,则标签不会关闭。'
"
>
该代码<a href="example>xxx</a><a href="second">text</a>
在 Firefox 中被解释为:
<a href="http://example.com%3Exxx%3C/a%3E%3Ca%20href=" second"="">text</a>
ext/standard/string.c 的第 4036 行strip_tags
引用了PHP 函数。该函数调用内部函数 php_strip_tags_ex。
存在两个缓冲区,一个用于输出,另一个用于“内部 HTML 标记”。一个名为的计数器depth
保存开尖括号 ( <
) 的数量。
变量in_q
包含引号字符('
或"
)(如果有),0
否则。最后一个字符存储在变量中lc
。
这些函数有五种状态,其中三种在函数上面的描述中提到过。基于这些信息和函数体,可以导出以下状态:
- 状态 0 是输出状态(不在任何标签中)
- 状态 1 表示我们在一个普通的 html 标签内(标签缓冲区包含
<
)
- 状态 2 表示我们在一个 php 标签内
- 状态 3:我们来自输出状态,遇到了
<
and!
字符(标签缓冲区包含<!
)
- 状态 4:在 HTML 注释内
我们只需要注意不能插入任何标签。也就是说,<
后跟一个非空白字符。第 4326 行<
使用如下所述的字符检查大小写:
- 如果在引号内(例如
<a href="inside quotes">
),<
则忽略该字符(从输出中删除)。
- 如果下一个字符是空白字符,
<
则添加到输出缓冲区。
- 如果在 HTML 标记之外,则状态变为
1
("inside HTML tag") 并且最后一个字符lc
设置为<
- 否则,如果在 HTML 标记内,则命名的计数器
depth
会递增并且字符会被忽略。
如果在标签打开 ( )>
时遇到,则变为("not in a quote") 并变为("not in a tag")。标记缓冲区被丢弃。state == 1
in_q
0
state
0
属性检查(如'
和之类的字符"
)在被丢弃的标记缓冲区上完成。所以结论是:
没有标签白名单的 strip_tags 可以安全地包含在标签之外,不允许任何标签。
“外部标签”是指不在标签中,如在<a href="in tag">outside tag</a>
. 文本可能包含<
and >
,如>< a>>
. 结果不是有效的 HTML,但<
仍需要转义,尤其>
是. 这可以用.&
&
htmlspecialchars()
strip_tags
没有白名单参数的描述是:
确保返回的字符串中不存在 HTML 标记。