3

我在 Linux 上使用 Exiv2 命令行工具来编辑图像元数据,如下所示:

exiv2 -M"set Iptc.Application2.Caption String This is my caption....." modify IMG.jpg

我想使用用户提供的标题从 PHP 执行此操作。如果用户没有输入特殊字符,这将起作用:

exec('/usr/local/bin/exiv2 -M"set Iptc.Application2.Caption String '.$caption.'" modify IMG.jpg');

我需要允许用户使用特殊字符,例如单引号和双引号。我想使用 escapeshellcmd() 来防止恶意数据。如何正确转义命令和参数以使其正常工作?我尝试了很多选择,但我无法做到正确。

4

3 回答 3

5

是的,这是一个难题,因为该命令使用了非标准的 shell 参数(就像它自己的小元语言一样)。ImageMagick 也有同样的问题。

如果您只是在双引号字符串中使用 escapeshellarg(),它就会变得毫无用处。escapeshellcmd() 会转义所有特殊字符,并且在双引号字符串中使用是安全的。因此,您需要在其周围硬编码单引号以使其正常工作。

exec('/usr/local/bin/exiv2 -M"set Iptc.Application2.Caption String \'' . escapeshellcmd($caption) . '\'" modify IMG.jpg');

escapeshellarg() 在单引号字符串中不起作用的原因是:

# for this input:
The smith's "; rm -rf *; echo "went to town

# after escapeshellarg()
'The smith\'s "; rm -rf *; echo "went to town'

# Works fine if left as a top-level argument
/usr/bin/command 'The smith\'s "; rm -rf *; echo "went to town'

# BUT if put in a double-quoted string:
/usr/bin/command "subcommand1 'The smith\'s "; rm -rf *; echo "went to town'"

# it is broken into 3 shell commands:
/usr/bin/command "something and 'The smith\'s ";
rm -rf *;
echo "went to town'"

# bad day...
于 2009-08-10T17:04:41.117 回答
0

使用heredoc怎么样?

$str = <<<'EOD'
/usr/local/bin/exiv2 -M "set Iptc.Application2.Caption String $options" modify IMG.jpg
EOD;
exec($str);

要修改它以使用 excapeshellcmd():

$options = excapeshellcmd($caption);
$command = <<<'EOD'
/usr/local/bin/exiv2 -M"set Iptc.Application2.Caption String $options" modify IMG.jpg
EOD;
exec($command);
于 2009-08-10T17:15:25.247 回答
0

由于 Exiv2 的非标准 shell 参数,很难找到一个简单而强大的解决方案来正确处理用户提供的引号。还有另一种解决方案可能更可靠且易于维护,但性能损失很小。

将 Exiv2 指令写入文件cmds.txt,然后调用:

exiv2 -m cmds.txt IMG.jpg

从文件中读取说明。

更新:我已经实现了这个方法,它不需要转义用户提供的数据。此数据直接写入 Exiv2 读取的文本文件。Exiv2 命令文件格式非常简单且以换行符结尾,不允许在值内转义,所以我需要做的就是防止换行符通过,无论如何我都不允许这样做。

于 2009-08-11T12:09:15.340 回答