[英]Making an IRC bot - how can I let people !eval perl/javascript code?
我正在Perl(基于POE)中的机器人上工作,到目前为止还不错,但是我无法弄清楚如何添加!js
或!perl
命令来评估各自的代码并返回一行输出打印到通道中。 我找到了App :: EvalServer,但我不知道如何使用它。
谢谢你的帮助!
App::EvalServer
模块附带一个二进制文件,可作为独立应用程序运行。 您无需将其放入程序中,而是自己运行。 它打开一个端口,您可以在其中将代码作为json字符串处理。 这对我来说也不是一个好主意。
您可能还需要查看另一个名为Safe的模块。 我建议您在执行任何操作之前通读完整的文档以及与操作码相关的文档(在文档中链接)。 如果您评估任意代码,可能会造成严重损失! 永远别忘了。
更新:
这是一个如何从已eval
代码中捕获print
或say
输出的示例。 您可以将open
与变量一起使用,以使print
输出始终转到该变量。 如果之后再切换回去,则可以在var中使用捕获的输出。 这称为内存文件 。
use strict; use warnings;
use feature 'say';
use Safe;
# Put our STDOUT into a variable
my $printBuffer;
open(my $buffer, '>', \$printBuffer);
# Everything we say and print will go into $printBuffer until we change it back
my $stdout = select($buffer);
# Create a new Safe
my $compartment = new Safe;
$compartment->permit(qw(print)); # for testing
# This is where the external code comes in:
my $external_code = qq~print "Hello World!\n"~;
# Execute the code
my $ret = $compartment->reval($external_code, 1);
# Go back to STDOUT
select($stdout);
printf "The return value of the reval is: %d\n", $ret;
say "The reval's output is:";
say $printBuffer;
# Now you can do whatever you want with your output
$printBuffer =~ s/World/Earth/;
say "After I change it:";
say $printBuffer;
免责声明: 使用此代码需要您自担风险!
更新2 :经过长时间的聊天讨论,这是我们想到的。 如果reval
时间过长(例如由于无限循环),它将实现一种超时来停止执行。
#!/usr/bin/perl
use warnings;
use strict;
use Safe;
use Benchmark qw(:hireswallclock);
my ($t0, $t1); # Benchmark
my $timedOut = 0;
my $userError = 0;
my $printBuffer;
open (my $buffer, '>', \$printBuffer);
my $stdout = select($buffer);
my $cpmt = new Safe;
$cpmt->permit_only(qw(:default :base_io sleep));
eval
{
local $SIG{'ALRM'} = sub { $timedOut = 1; die "alarm\n"};
$t0 = Benchmark->new;
alarm 2;
$cpmt->reval('print "bla\n"; die "In the user-code!";');
# $cpmt->reval('print "bla\n"; sleep 50;');
alarm 0;
$t1 = Benchmark->new;
if ($@)
{
$userError = "The user-code died! $@\n";
}
};
select($stdout);
if ($timedOut)
{
print "Timeout!\n";
my $td = timediff($t1, $t0);
print timestr($td), "\n";
print $printBuffer;
}
else
{
print "There was no timeout...\n";
if ($userError)
{
print "There was an error with your code!\n";
print $userError;
print "But here's your output anyway:\n";
print $printBuffer;
}
else
{
print $printBuffer;
}
}
看一下perl eval() ,您可以向其传递变量/字符串,它将像Perl代码一样对其进行评估。 同样在javascript中,还有一个eval()函数的执行效果类似。
但是, 不要在perl或javascript中评估任意代码 ,除非您可以在完全封闭的环境中运行它(即使那样,这仍然不是一个好主意)。 很多人花费大量时间来阻止这种情况的发生 。 所以这就是您要做的,但实际上您根本不想做。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.