作为其名称可能暗示的那样,
strip_tags
应该删除所有 HTML 标签。我们可以通过分析源代码来证明它。下面的分析适用于一个没有第二个参数进行白名单标签的
strip_tags('...')
调用。
首先,关于 HTML 标签的一些理论:标签以
<
开头,后跟非空格字符。如果这个字符串以
?
开头,则
不应该被解析。如果这个字符串以
!--
开头,则被视为注释,接下来的文本也不应该被解析。注释以
-->
结束,在这样的注释中,允许使用像
<
和
>
这样的字符。属性可以出现在标签中,它们的值可以选择由引号字符 (
'
或
"
) 包围。如果存在这样的引号,它必须被关闭,否则如果遇到
>
,则标签未关闭。
代码
<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>
PHP函数strip_tags
在ext/standard/string.c的第4036行中被引用。该函数调用内部函数php_strip_tags_ex。
有两个缓冲区,一个用于输出,另一个用于“HTML标记内部”。一个名为depth
的计数器保存开放角括号(<
)的数量。
变量in_q
包含引号字符('
或"
),如果没有则为0
。最后一个字符存储在变量lc
中。
该函数有五种状态,其中三种在函数上面的描述中提到。根据这些信息和函数体,可以得出以下状态:
- 状态0是输出状态(不在任何标记中)
- 状态1表示我们在普通HTML标记内部(标记缓冲区包含
<
)
- 状态2表示我们在PHP标记内部
- 状态3:我们从输出状态进入,并遇到
<
和!
字符(标记缓冲区包含<!
)
- 状态4:在HTML注释中
我们需要小心,确保没有标签被插入。也就是说,
<
后面不能跟非空格字符。
第4326行检查了一个包含
<
字符的情况,如下所述:
- 如果在引号内(例如
<a href="inside quotes">
),则忽略<
字符(从输出中删除)。
- 如果下一个字符是空格字符,则将
<
添加到输出缓冲区。
- 如果不在HTML标记中,则状态变为
1
(“在HTML标记内”),并将最后一个字符lc
设置为<
- 否则,如果在HTML标记内部,则增加名为
depth
的计数器,并忽略该字符。
如果在标记打开时遇到>
(state == 1
),则in_q
变为0
(“不在引号内”),state
变为0
(“不在标记中”)。标记缓冲区将被丢弃。
对于标记缓冲区进行属性检查(例如'
和"
等字符)。因此,结论是:
strip_tags没有标记白名单时,在标记外部包含是安全的,不会允许任何标记。
“外部标签”指的是不在标签中的文本,例如:
<a href="in tag">outside tag</a>
。文本可能包含
<
和
>
,例如:
>< a>>
。但结果并不是有效的HTML,需要转义
<
、
>
和
&
,特别是
&
。可以使用
htmlspecialchars()
函数进行转义。
没有白名单参数的strip_tags
函数的描述如下:
确保返回的字符串中不存在任何HTML标签。
strip_tags
将会删除更多的文本。 - Damonstrip_tags()
实现的更新链接:https://github.com/php/php-src/blob/master/ext/standard/string.c#L4729 - Sumit