3

这些正则表达式正在杀死我,无论我阅读什么,我都无法理解这个概念。

这是我的问题,我相信它非常容易解决。

[img:http://example.com/_data/025_img.jpg]

我想要的只是用标签更改它显示 [img: ... ] 的位<img>并获得如下结果

<img src='http://example.com/_data/025_img.jpg' border='0' />

我尝试了各种无效的愚蠢变化。我对此并不感到惊讶。

编辑

附加信息:

我的情况如下。

  1. 用户将图像上传到他们的个人资料

  2. 图像名称存储在 db 中。

  3. 它们列在具有 textarea 的表单旁边
  4. 在输入文本时,我想通过添加以下标签 [img: ... ] 为用户提供包含一个或多个图像的位置,其中 ... 是单击列出的图像时将被复制的链接从用户库。
  5. 我正在使用 Codeigniter 并将 textarea 通过视图传递到控制器->模型中,在该模型中,它由助手对各种事物进行清理... sql/quotes 等。XSS 也在 CI 上启用

  6. 然后我想扫描文本并查看用户在哪里拥有 [img: ... ] 标签并将其交换为<img>标签并用图像后跟文本呈现帖子。

因此,用户的实际输入将类似于以下内容

The brown fox jumped over foo bar [img:http://example.com/_data/025_img.jpg] and then went to bed [img:http://example.com/_data/0277_img.jpg] while thinking about [img:http://example.com/_data/1115_img.jpg]

这就是我要求 preg_replace 而不是 preg_match 的原因。preg_match 不会使文本跟随图像。

4

4 回答 4

4

让我们先把简单的事情排除在外。

/\[img:([^\]]+)\]/

那是:

  • 字面意思[img:
  • 一个捕获组,包含
    • 一个字符类,由
      • 不是文字的东西]
    • 至少重复一次
  • 字面意思]

运行此preg_match操作,匹配数组中的元素 1 很可能是您可以轻松插入到img标记中的图像 URL。

但你不应该。不是马上。

首先,这是不安全的。当我写这篇文章时会发生什么?

[img:javascript:alert(document.cookie);]

呃。这不会是好事。

可能想要确保用户声称是 URL 的东西确实是 URL。您可以尝试通过调用来执行此操作parse_url。它将返回一系列 URL 组件。确保事物具有域和路径,并通过 HTTP 或 HTTPS 提供服务。

好的,但是当用户输入this时会发生什么?

[img:http://www.example.com/foo.jpg" onmouseover="alert(document.cookie)"]

这是一个有效的...ish... URL,它将被成功解构parse_url并且很可能通过基本检查以确保格式正确。过滤掉空格和引号(单引号双引号)将是一个很好的起点,但还有更多需要担心的事情。

最重要的是,像这样的标记是XSS跨站点脚本漏洞中的一个向量。

可能可以通过将 URL 传递给htmlspecialchars. 这至少会取消引号和括号,并且很难对那些被照顾的人感到讨厌。请注意字符集的愚蠢,一些非 UTF-8 字符编码可能包含 ASCII 引号......

可能希望为此使用真正的标记语言(即使它只是降价),并且您可能希望在结果上使用基于白名单的 HTML 过滤器,例如HTML Purifier。这将有助于保护您免受某些程度的精神错乱。

请记住,如果他们来抓你,你只会偏执。网络上到处都是愚蠢到恶意的人,以及恶意到愚蠢的人。

于 2012-12-09T09:46:18.297 回答
2

如果您不喜欢正则表达式,则不必使用它们。至少不是为了这个目的。

以下应该做:

$in = "[img:http://example.com/_data/025_img.jpg]";

if (strpos($in, "[img:") === 0)
{
    $in = "<img src='" . substr($in, 5, -1) . "' border='0' />";
}

echo $in;

但是,这将是正则表达式方式:

$in = "[img:http://example.com/_data/025_img.jpg]";

preg_match("~\[img\:(.*?)\]~", $in, $matches);

if ($matches)
{
    echo "<img src='" . $matches[1] . "' border='0' />";
}

简短说明:

模式是:"~\[img\:(.*?)\]~"

~用作模式的分隔符。你的开始[必须被转义,因为它是一个正则表达式字符。img能原地不动,:又得逃。之后,任何字符都可以跟随:.*- 问号是将选择变为“不贪婪”,否则将匹配到最后。将其放入(大括号)中,以便将其标记为$matches. 之后,]再次关闭 - 仅此而已。

更新:见 Gumbos 评论,:不需要转义。

于 2012-12-09T09:39:25.350 回答
1

正则表达式很难,但功能强大。我根本不是大师,所以不认为这是最好的解决方案。

$regEx = '/\[img:http:\/\/[\w]{3,10}\.(com|org|us){1}[\w\/]{5,15}\.(jpg|png|gif){1}\]/i';

$string = 'someting before [img:http://example.com/_data/025_img.png], something after [img:http://example.org/_data/025_img.jpg] and end of the line EOL';
$pstring = $string;
$matches[0] = array();
preg_match_all($regEx, $string, $matches);

匹配数组看起来像:

Array
(
    [0] => Array
        (
            [0] => [img:http://example.com/_data/025_img.png]
            [1] => [img:http://example.org/_data/025_img.jpg]
        )

    [1] => Array
        (
            [0] => com
            [1] => org
        )

    [2] => Array
        (
            [0] => png
            [1] => jpg
        )

)

好的,这里发生了什么:

  1. 正则表达式

/- 开始正则表达式
\[img:http:\/\/- 每个字符串都必须以[img:http://
[\w]{3,10}- 比我预期的只有 3 到 10 个数字、字母和下划线行,这将是域名(虽然我不确定域必须包含下划线,所以优化点)
\.-点
(com|org|us){1}- 其中一个人
[\w\/]{5,15}- 从 5 到 15 行作为路径,请注意我在此处添加了 /
\.- 点
(jpg|png|gif){1}- 其中一个人
\]- 模式结束 -
/i使其不区分大小写

  1. preg_match_all查找给定字符串中的所有匹配项,从分支到括号中的附加子字符串匹配项作为 的第二个和第三个元素$matches,我猜不到为什么,所以如果有人能帮助理解这一点,将不胜感激。

  2. 接下来使用简单的字符串操作,我可以替换所有主菜

像这样的东西:(注意没有if声明,因为我在开头添加了空的 $matches[0],没有的话生活得更好ifs:))

foreach ($matches[0] as $match) {
    $img = str_replace(array('[img:',']'), array('<img src="', '" />'), $match);
    $pstring = str_replace($match, $img, $pstring);
}

您可以使用正则表达式,根据需要使其简单或更复杂。

$pstring输出是

someting before <img src="http://example.com/_data/025_img.png" />, something after <img src="http://example.org/_data/025_img.jpg" /> and end of the line EOL

这是游乐场http://phpfiddle.org/main/code/bbu-e24

于 2012-12-10T00:43:26.280 回答
0
<?php
$str = '[img:http://example.com/_data/025_img.jpg]';
$image = '<img src="'.str_replace(array("[img:","]"),"",$str).'" border="0">';
echo $image;?>
于 2012-12-09T09:42:51.993 回答