【问题标题】:Formatting text from database格式化数据库中的文本
【发布时间】:2025-11-30 10:45:01
【问题描述】:

我的页面上有一个文本区域,允许用户在其中编写文本。为了保留用户在输入时所做的换行符,我使用:

editBox.val().replace(/\r?\n/g, "\r\n");

在数据上传到我正在使用的数据库之前:

$data = mysql_real_escape_string($data);

我这样做是为了保留尽可能多的数据,而不会剥离以后可能有用的数据。这也有助于我保留以后可以允许的可能格式选项。我读到这是一个很好的做法。

问题是

当从数据库中提取数据时,我需要清理它。为此,我正在使用:

function cleanData($data) 
{           
    $data = nl2br($data);
    $data = strip_tags($data,"<br><b><p><i><h1><h2><h3><h4><h5><h6>");
    return $data;
}

我允许某些标签稍后将与自制的所见即所得编辑器一起使用。 但是,这允许用户输入以下内容:

<p title="some junk here">hax</p>

虽然标题属性并不令人讨厌,但其他属性可能会。我不确定用户是否可以添加 class 和 id 属性,但我不明白为什么他们不应该这样做。它还会删除任何看起来像标签的东西,例如表情符号:"*&lt;:o) &lt;- happy clown" 最终会看起来像这样:"*"

我尝试使用:

$data = filter_var($data, FILTER_SANITIZE_SPECIAL_CHARS);

而不是 cleanData 函数,但是这会将我的 &lt;br&gt; 转换后的换行符显示为文本而不是添加换行符。



简而言之,我的问题是:

我似乎找不到清理数据的好方法,因此保留了换行符/br,同时还保留了添加某种所见即所得格式的可能性。我真的不在乎它是 html 标签还是类似 bbCode:[b].


我的问题如下:

有没有更聪明的方法可以做到这一点,或者我的方法只需稍加调整就可以了吗?

你们会怎么做? :) 除非有非常强烈的动机,否则我想避免使用外部库。


PS:我搜索了很多,没有找到满意的答案 - 我也花了很长时间使这篇文章可读和易于理解。我希望我做得对。

【问题讨论】:

  • 你为什么要对从数据库中提取的数据进行 mysql 转义?那假设您将再次将其填充回查询中。同样,real_escape_string() 应该是您在 SQL 中使用字符串之前对字符串执行的 LAST 操作。其他任何事情都可以撤消逃逸并让您再次受到攻击。
  • 我会去外部库,为什么要重新发明*?
  • @MarcB 你是对的。 AFAIK 它也会双重逃脱。该行已被删除,但主要问题仍然存在。谢谢你:)
  • @Vyktor 这主要是一个学习过程——最终结果也可能是商业的,除非许可证完全开放,否则我会遇到问题。你能推荐一个吗? :)
  • 嘿,我真的不记得名字了,我记得它是typo3使用的那个(可能是修改),我试图通过搜索html编辑器在wiki上查找它,但是wikipedia“今天停了”,呵呵。

标签: php javascript jquery mysql


【解决方案1】:

首先,

editBox.val().replace(/\r?\n/g, "\r\n");

这不应该在客户端 (JavaScript) 上完成,而应该在服务器端 (PHP) 上完成,如果你想确定它会发生的话。可以通过禁用 JavaScript 或从其他站点发布来规避它。

关于实际问题,我会使用一些预制标记语言,例如 Textile,这也是 * 上使用的。

但如果您希望允许一些自定义格式,您可以(如您自己建议的那样)使用BB-code[b][i] 等)。我实现这一点的方法是首先使用htmlspecialchars 将所有HTML 特殊字符替换为它们各自的HTML 实体。在此之后,您可以将[b] 等内容替换为&lt;strong&gt; 等。

示例

$str = "See, [b]evil[/b] input<br/>, <i>etc</i>.";
$str = htmlspecialchars($str);
print $str; // "See, [b]evil[/b] input &lt;br/&gt;, &lt;i&gt;etc&lt;/i&gt;."
$str = str_replace(array("[b]","[/b]"),array("<b>","</b>",$str);
print $str; // "See, <b>evil</b> input &lt;br/&gt;, &lt;i&gt;etc&lt;/i&gt;."

为避免错误的标记,您可能应该使用一些正则表达式将 BBcode 替换为 HTML 标记。

【讨论】:

  • 为什么不是客户端?我读到 jquery 在使用 cal 时会去除换行符,并且需要替换。无论是客户端还是服务器,对我来说都没有关系,但我想了解原因。 htmlspecialchars 是否与 filter_var($data, FILTER_SANITIZE_SPECIAL_CHARS); 相同?谢谢你的回答。
  • 如果你想确保你的数据存储在“\r\n”中,你必须在服务器端进行。您不能信任输入数据。不,FILTER_SANITIZE_SPECIAL_CHARS 不完全相同,请参阅Sanitize filters。它没有逃脱那么多。使用FILTER_SANITIZE_FULL_SPECIAL_CHARS 将(如链接所述)与使用htmlspecialchars 相同。
  • 谢谢@Kristian - 好吧,这有点解释了。但是如果我使用过滤器,我应该如何处理换行符?
  • 在我的代码示例的第 4 行,我将所有 BBcode 替换为 HTML 标记。您可以对换行符执行相同的操作,而不是将[b] 替换为&lt;strong&gt;,而是将“\r\n”替换为&lt;br&gt;
  • 好吧,然后我不接受 nl2br() 吗?明天我会做一些初步测试,看看我能把什么缝合在一起。如果结果正确,我会更新帖子并将其标记为已回答。再次感谢您。