我想要做的是允许用户在需要时发布代码,因此它是可见的并且不会呈现。例如:
<span>
<div id="hkhsdfhu"></div>
</span>
<h1>Hello</h1>
应该变成:
<span>
<div id="hkhsdfhu"></div>
</span>
<h1>Hello</h1>
仅当它包含在<code></code>
标记中时。现在我使用以下函数只允许某些HTML标记并转义任何其他标记:
function allowedHtml($str) {
$allowed_tags = array("b", "strong", "i", "em");
$sans_tags = str_replace(array("<", ">"), array("<",">"), $str);
$regex = sprintf("~<(/)?(%s)>~", implode("|",$allowed_tags));
$with_allowed = preg_replace($regex, "<\\1\\2>", $sans_tags);
return $with_allowed;
}
但是,如果用户将代码包装在<code></code>
标记中并且它包含上述函数中的任何允许的标记,那么这些标记将呈现而不是被转义。如何将<code></code>
标记中的任何内容转义(或仅<
和>
转换为<
和>
)?我知道htmlentities()
,但我不想对整个帖子这样做,只有<code></code>
个标签内的内容。
提前致谢!
答案 0 :(得分:3)
只需使用preg_replace()
一个htmlenteties()
函数就<code>
代码中找到的所有内容执行function allowedHtml($str) {
$str = htmlentities($str, ENT_QUOTES, "UTF-8");
$allowed_tags = array("b", "strong", "i", "em", "code");
foreach ($allowed_tags as $tag) {
$str = preg_replace("#<" . $tag . ">(.*?)</" . $tag . ">#i", "<" . $tag . ">$1</" . $tag . ">", $str);
}
return $str;
}
$reply = allowedHtml($_POST['reply']);
$reply = preg_replace("#\<code\>(.+?)\</code\>#e", "'<code>'.htmlentities('$1', ENT_QUOTES, 'UTF-8').'</code>'", $reply);
$reply = str_replace("&", "&", $reply);
函数
EDITED
allowedHtml()
重写了您的str_replace()
功能并在最后添加了function convertHtml($reply, $revert = false) {
$specials = array("**", "*", "_", "-");
$tags = array("b", "i", "u", "s");
foreach ($tags as $key => $tag) {
$open = "<" . $tag . ">";
$close = "</" . $tag . ">";
if ($revert == true) {
$special = $specials[$key];
$reply = preg_replace("#" . $open . "(.+?)" . $close . "#i", $special . "$1" . $special, $reply);
}
else {
$special = str_replace("*", "\*", $specials[$key]);
$reply = preg_replace("#" . $special . "(.+?)" . $special . "#i", $open . "$1" . $close, $reply);
}
}
return $reply;
}
$reply = htmlentities($reply, ENT_QUOTES, "UTF-8");
$reply = convertHtml($reply);
$reply = preg_replace("#[^\S\r\n]{4}(.+?)(?!.+)#i", "<pre><code>$1</code></pre>", $reply);
$reply = preg_replace("#\</code\>\</pre\>(\s*)\<pre\>\<code\>#i", "$1", $reply);
$reply = nl2br($reply);
$reply = preg_replace("#\<pre\>\<code\>(.*?)\</code\>\</pre\>#se", "'<pre><code>'.convertHtml(str_replace('<br />', '', '$1'), true).'</code></pre>'", $reply);
。
它已经过测试,现在应该可以完美运行:)
更新 - 新解决方案
{{1}}
讨论了另一个解决方案,上面的代码将解决这个问题。它就像Stack Overflow html转换一样,这意味着**变为粗体,*变为斜体,_变为下划线, - 是“删除线”。最重要的是,所有以4个或更多空格开头的行将作为代码输出
答案 1 :(得分:2)
我认为你最好直接使用dom而不是使用正则表达式来解析允许的标签。例如,要遍历dom并转义<code>
标签中的内容,您可以执行以下操作:
$doc = new DOMDocument();
$doc->loadHTML($postHtml);
$codeNode = $doc->getElementsByTagName('code')->item(0);
$escapedCode = htmlspecialchars($codeNode->nodeValue);
答案 2 :(得分:1)
您可以使用preg_replace()进行此操作。只需确保在调用allowedHtml
函数之前调用此函数,以便标记已被替换。
<?php
$post = <<<EOD
I am a person writing a post
How can I write this code?
Example:
<code>
<span>
<div id="hkhsdfhu"></div>
</span>
<h1>Hello</h1>
</code>
Pls help me...
EOD;
$post = preg_replace('/<code>(.*?)<\/code>/ise',
"'<code>' . htmlspecialchars('$1') . '</code>'",
$post);
var_dump($post);
string(201) "I am a person writing a post
How can I write this code?
Example:
<code>
<span>
<div id=\"hkhsdfhu\"></div>
</span>
<h1>Hello</h1>
</code>
Pls help me..."
答案 3 :(得分:1)
这是一个。
$str = preg_replace_callback('/(?<=<code>)(.*?)(?=<\/code>)/si','escape_code',$str);
function escape_code($matches) {
$tags = array('b','strong','i','em');
// declare the tags in this array
$allowed = implode('|',$tags);
$match = htmlentities($matches[0],ENT_NOQUOTES,'UTF-8');
return preg_replace('~<(/)?('.$allowed.')(\s*/)?>~i','<$1$2$3>',$match);
}