[英]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.