简体   繁体   English

制作IRC机器人-如何让人们!eval perl / javascript代码?

[英]Making an IRC bot - how can I let people !eval perl/javascript code?

I'm working on a bot in Perl (based on POE) and so far so good, but I can't figure out how can I add a !js or !perl command to evaluate respective code and return one line of output to be printed into the channel. 我正在Perl(基于POE)中的机器人上工作,到目前为止还不错,但是我无法弄清楚如何添加!js!perl命令来评估各自的代码并返回一行输出打印到通道中。 I found App::EvalServer but I don't get how to use it. 我找到了App :: EvalServer,但我不知道如何使用它。

Thanks for any help! 谢谢你的帮助!

The App::EvalServer module comes with a binary to run as a standalone application . App::EvalServer模块附带一个二进制文件,可作为独立应用程序运行。 You do not put it in your program but rather run it on it's own. 您无需将其放入程序中,而是自己运行。 It opens a port where you can hand it code as a json string. 它打开一个端口,您可以在其中将代码作为json字符串处理。 This does not sound like a good idea to me either. 这对我来说也不是一个好主意。

There is another module you might want to look at called Safe . 您可能还需要查看另一个名为Safe的模块。 I suggest you read through the complete documentation as well as the one to Opcode (linked in the doc) before you do anything with this. 我建议您在执行任何操作之前通读完整的文档以及与操作码相关的文档(在文档中链接)。 YOU CAN DO SERIOUS DAMAGE IF YOU EVALUATE ARBITRARY CODE! 如果您评估任意代码,可能会造成严重损失! Never forget that. 永远别忘了。


UPDATE: 更新:

Here's an example of how to capture the output of print or say from your eval ed code. 这是一个如何从已eval代码中捕获printsay输出的示例。 You can use open with a variable to make print ed output always go to that variable. 您可以将open与变量一起使用,以使print输出始终转到该变量。 If you switch back afterwards you can work with the captured output in your var. 如果之后再切换回去,则可以在var中使用捕获的输出。 This is called an in-memory file . 这称为内存文件

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;

Disclaimer: Use this code at your own risk! 免责声明: 使用此代码需要您自担风险!


Update 2 : After a lengthy discussion in chat, here's what we came up with. 更新2 :经过长时间的聊天讨论,这是我们想到的。 It implements a kind of timeout to stop the execution if the reval is taking to long, eg because of an infinite loop. 如果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;
        }
}

Take a look at perl eval() , you can pass it variables/strings and it will evaluate it as if it's perl code. 看一下perl eval() ,您可以向其传递变量/字符串,它将像Perl代码一样对其进行评估。 Likewise in javascript, there's also an eval() function that performs similarly. 同样在javascript中,还有一个eval()函数的执行效果类似。

However, DO NOT EVALUATE ARBITRARY CODE in either perl or javascript unless you can run it in a completely closed environment (and even then, it's still a bad idea). 但是, 不要在perl或javascript中评估任意代码 ,除非您可以在完全封闭的环境中运行它(即使那样,这仍然不是一个好主意)。 Lot's of people spend lots of time preventing just this from happening . 很多人花费大量时间来阻止这种情况的发生 So that's how you'd do it, but you don't want to do it, really at all. 所以这就是您要做的,但实际上您根本不想做。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM