0

I am using webmin and I am trying to change some settings in a file. I am having problems if the person uses any weird characters that might trip up sed or Perl using the following code:

&execute_command("sed -i 's/^$Pref.*\$/$Pref \"$in{$Pref}\"/g' $DIR/pserver.prefs.cache");

Where execute_command is a webmin function to basically run a special system call. $pref is the preference name such as "SERVERNAME", "OPTION2", etc. and $in{Pref} is going to be the option I want set for the PREF. For example here is a typical pserver.prefs:

SERVERNAME "Test Name"
OWNERPASSWORD "Hd8sdH&3"

Therefore, if we wanted to change SERVERNAME to say Tes"t#&^"@'"@@& and OWNERPASSWORD to *@(&'"@$"(')29 then they would be passed in as $in{Pref}. What is the easiest way to escape the $in{} variables so that they can work OK with sed, or better yet, what is a way I can convert my sed command to a strictly Perl command so that it doesn't have errors?

Update:

Awesome, now I'm just trying to get it to work with and I get this error:

**/bin/sh: -c: line 0: unexpected EOF while looking >for matching `"' /bin/sh: -c: line 1: syntax error: unexpected end of file** 

This does not work:

my $Pref = "&*())(*&'''''^%$#@!"; 
&execute_command("perl -pi -e 's/^SERVERNAME.*\$/SERVERNAME \"\Q$Pref\E\"/g' $DIR/pserver.prefs");

This does:

my $Pref = "&*())(*&^%$#@!"; 
&execute_command("perl -pi -e 's/^SERVERNAME.*\$/SERVERNAME \"\Q$Pref\E\"/g' $DIR/pserver.prefs");
4

2 回答 2

4

Perl 的正则表达式支持包括 \Q 和 \E 运算符,这将导致它避免在其范围内解释正则表达式符号,但它们允许变量插值。

这有效:

$i = '(*&%)*$£(*';

if ($i =~ /\Q$i\E/){
    print "matches!\n";
}

如果没有 \Q 和 \E,您会因为$i.

于 2009-06-26T09:13:31.530 回答
0

最简单的部分就是停止将命令作为单个字符串执行。把壳拿出来。假设您的 execute_command 函数只是在幕后调用系统,请尝试:

execute_command(qw/perl -pi -e/, 's/^SERVERNAME.*$/SERVERNAME "\Q$Pref\E"/g', "$DIR/pserver.prefs");

这更好,但并不完美。毕竟,用户可以输入一些愚蠢的东西,比如“@[system qw:rm -rf /:]”,然后就会发生愚蠢的事情。我认为也有解决这个问题的方法,但最简单的可能是简单地在代码中完成工作。怎么做?也许从 perl 对“-pi”标志所做的事情开始可能会有所帮助。让我们来看看:

$  perl -MO=Deparse -pi -e 's/^SERVERNAME.*$/SERVERNAME "\Qfoo\E"/'
BEGIN { $^I = ""; }
LINE: while (defined($_ = <ARGV>)) {
    s/^SERVERNAME.*$/SERVERNAME "foo"/;
}
continue {
    print $_;
}

也许你可以在你的代码中做同样的事情?不确定复制有多容易,尤其是 $^I 位。最坏的情况,读取文件,写入新文件,删除原始文件,将新文件重命名为原始名称。这将有助于摆脱通过危险垃圾的所有风险。

于 2009-06-26T16:34:38.297 回答