使用preg_replace将字符串转换为<img/>标记

时间:2012-12-09 09:30:30

标签: php preg-replace

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

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

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

我想要的是用[{1}}标签更改[img:...]所在的位,并获得如下结果

<img>

我尝试了各种愚蠢的变化,这些变化并没有奏效。我并不感到惊讶。

修改

其他信息:

我的情况如下。

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

  2. 图像名称存储在db。

  3. 它们列在具有textarea
  4. 的表单旁边
  5. 在输入文字时我想通过添加以下标签[img:...]来为用户提供一个或多个图像,其中...是点击图像时会复制的链接从用户图库中列出。
  6. 我正在使用Codeigniter并将textarea传递到视图中并进入controller-&gt;模型,在那里它由各种事物的助手进行消毒...... sql / quotes等.XSS也在CI上启用

  7. 然后我想扫描文本,看看用户在哪里有[img:...]标签并将其交换为<img src='http://example.com/_data/025_img.jpg' border='0' /> 标签,并使用图片后跟文字呈现帖子。

  8. 因此,用户的实际输入将是

    <img>

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

4 个答案:

答案 0 :(得分:4)

让我们先轻松一点。

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

那是:

  • 文字[img:
  • 包含的捕获组
    • 由...组成的字符类
      • 不是文字]
      • 的内容
    • 至少重复一次
  • 文字]

通过preg_match运行此操作,匹配数组中的元素1很可能是您可以轻松插入img代码的图片网址。

但你不应该。不是马上。

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

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

Uhoh。这不会很好。

可能想要确保用户声称的URL确实是一个URL。您可以通过调用parse_url来尝试这样做。它将为您提供一系列URL组件。确保该东西具有域和路径,并通过HTTP或HTTPS提供。

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

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

这是一个有效的... ish ...将被parse_url成功解构的网址,并且可能会通过基本检查以确定格式良好。过滤掉空格和引号(单个 double)将是一个很好的起点,但仍有许多事情需要担心。

底线是像这样的标记是XSS, or Cross-site scripting vulnerabilities中的向量。

您可以 通过htmlspecialchars传递网址来缓解某些威胁。这至少会引用引号和括号,并且很难对那些照顾过的人感到讨厌。只要注意字符集的愚蠢,一些非UTF-8字符编码可以包含ASCII引号......

可能想要使用真正的标记语言(即使它只是降价),而可能想要使用基于白名单的HTML过滤器,如{ {3}}结果。这将有助于保护您免受某种程度的精神错乱。

请记住,如果他们出去接你,你只会偏执。网络上到处都是愚蠢的人,他们是恶意的,人们是如此恶毒,以至于它是愚蠢的。

答案 1 :(得分: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可以保持原样,:必须再次转义。之后,任何角色都可以跟随:.* - 问号是将选择变为“ungreedy”,否则,它将匹配到结尾。把它放在(大括号)中,因此它被标记为$matches的输出。之后,再次关闭] - 这就是全部。

更新:请参阅Gumbos评论,:无需转义。

答案 2 :(得分: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. 正则表达式
  2. / - 开始regexpression
    \[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. 接下来使用简单的字符串操作,我可以替换所有主菜

    3. 这样的事情:(注意没有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
      

      这里是playground http://phpfiddle.org/main/code/bbu-e24

答案 3 :(得分:0)

<?php
$str = '[img:http://example.com/_data/025_img.jpg]';
$image = '<img src="'.str_replace(array("[img:","]"),"",$str).'" border="0">';
echo $image;?>