如何使用引号转义 php exec() 命令
我使用 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() 来防止恶意数据。 如何正确转义命令和参数以使其正常工作? 我尝试了很多选择,但我无法做出正确的选择。
I use the Exiv2 command line tool on Linux to edit image metadata like so:
exiv2 -M"set Iptc.Application2.Caption String This is my caption....." modify IMG.jpg
I want to execute this from PHP, using a caption provide by a user. This will work if the user enters no special characters:
exec('/usr/local/bin/exiv2 -M"set Iptc.Application2.Caption String '.$caption.'" modify IMG.jpg');
I need to allow the user special characters such as single and double quotes. I would like to use escapeshellcmd() to prevent malicious data. How can I correctly escape the command and the argument so that it works? I have tried many options but I can't get it right.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
是的,这是一个难题,因为该命令使用非标准 shell 参数(就像它自己的小元语言)。 ImageMagick 也有同样的问题。
如果你只是在双引号字符串中使用 escapeshellarg() ,它就会变得毫无用处。 escapeshellcmd() 确实会转义所有特殊字符,并且可以安全地在双引号字符串中使用。 因此,您需要在其周围硬编码单引号以使其正常工作。
escapeshellarg() 在单引号字符串中不起作用的原因是:
Yes, this is a hard problem, because the command is using non-standard shell arguments (like it's own little meta-language). ImageMagick has the same issues.
If you simply use escapeshellarg() within a double-quoted string, it is rendered useless. escapeshellcmd() does escape all special characters, and is safe for use in a double-quoted string. So you need to hard code single quotes around it to make it work right.
The reason escapeshellarg() will not work in a single quoted string is:
使用heredoc怎么样?
要修改它以使用 excapeshellcmd():
What about using heredoc?
To modify this to use excapeshellcmd():
由于 Exiv2 的非标准 shell 参数,要找到一个简单而强大的解决方案来正确处理用户提供的引号并不容易。 还有另一种解决方案可能更加可靠且易于维护,但性能损失较小。
将Exiv2指令写入文件
cmds.txt
,然后调用:从文件中读取指令。
更新:我已经实现了这个方法,它不需要转义用户提供的数据。 该数据直接写入由 Exiv2 读入的文本文件。 Exiv2 命令文件格式非常简单并且以换行符结尾,不允许在值内转义,因此我需要做的就是防止换行符通过,无论如何我都不允许这样做。
Because of Exiv2's non-standard shell arguments, it is not easy to reach a simple and robust solution to handle user-supplied quotes correctly. There is another solution that is likely to be far more reliable and easy to maintain with a small performance penalty.
Write the Exiv2 instructions to a file
cmds.txt
, then call:to read the instructions from the file.
Update: I have implemented this method and it requires no escaping of the user-supplied data. This data is written directly to a text file which is read in by Exiv2. The Exiv2 command file format is very simple and newline-terminated, allow no escaping within values, so all I need to do is prevent newlines from passing through, which I was not allowing anyway.