制作一个IRC机器人 - 我怎样才能让人们!eval perl / javascript代码?

时间:2012-06-24 20:42:13

标签: perl irc evaluation poe

我正在研究Perl中的机器人(基于POE),到目前为止一直很好,但我无法弄清楚如何添加!js!perl命令来评估各自编码并返回要打印到通道中的一行输出。我发现App::EvalServer但我不知道如何使用它。

感谢您的帮助!

2 个答案:

答案 0 :(得分:3)

App::EvalServer模块附带一个二进制文件作为standalone application运行。你没有把它放在你的程序中,而是自己运行它。它打开一个端口,您可以将其作为json字符串传递给它。这对我来说听起来也不是一个好主意。

您可能希望查看另一个名为Safe的模块。我建议您在完成任何操作之前先阅读完整的文档以及Opcode(在文档中链接)的文档。 如果您评估任意代码,您可能会遭受严重损害!永远不会忘记这一点。


<强>更新

以下是如何从print ed代码中捕获sayeval的输出的示例。您可以将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;
        }
}

答案 1 :(得分:2)

看看perl eval(),你可以传递变量/字符串,它会像它的perl代码那样评估它。同样在javascript中,还有一个eval()函数,其功能类似。

然而,不要在perl或javascript中评估任意代码,除非您可以在完全封闭的环境中运行它(即便如此,它仍然是一个坏主意)。很多人花了很多时间preventing just this from happening。所以你就是这样做的,但你真的不想这样做。