加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 大数据 > 正文

perl – 这个使用Switch.pm的代码是否安全?

发布时间:2020-12-15 23:29:24 所属栏目:大数据 来源:网络整理
导读:在我们公司,我们使用这个代码(在最后给出)大约10年,它工作正常. 几天前我们遇到了一些问题,我们不得不重新编写完整的包,我们决定用Damian的Switch模块替换这个代码(为了提高代码的可读性). 一切都对我们很好. 后来我在Perlmonks发现达米安把这个模块放在了下
在我们公司,我们使用这个代码(在最后给出)大约10年,它工作正常.

几天前我们遇到了一些问题,我们不得不重新编写完整的包,我们决定用Damian的Switch模块替换这个代码(为了提高代码的可读性).

一切都对我们很好.

后来我在Perlmonks发现达米安把这个模块放在了下面

Damian modules you shouldn’t use in production because their purpose
is to explore and prototype future core language features.

但它对我们来说工作正常,因为我们没有达到这个模块的限制(我猜).

现在我请大家看一下这两个实现(嵌套if else vs switch),让我知道在新的实现中使用Switch是否正常或是否为我们创造了一些未来的问题?在下面给出的代码中使用Switch是否正常或是否有任何隐藏的错误/问题?

我已经在CPAN和Perlmonks上阅读了这个模块的错误和评论,我想我们的代码远远没有碰到那些错误(我想是这样).

我们使用的是Perl 5.8.5.

PS:我知道Switch的替代方案,我们在Perl 5.10中给出/什么时候,我们可以使用调度表和here指定的其他解决方案,但是现在我们只想比较使用Switch的新实现.

使用嵌套if else

if ($command =~ /^enter$/) {
    $self->show_main_frames();
}       
elsif ($command =~ /^XYZ_MENU/i) {
    $self->show_main_menu($manual,$dbot);
}
elsif ($command =~ /^DBOT/i) {
    $dbot->process();
}
# XML is used for the reminders-history: Request 2666
elsif ($command =~ /^XML_DBOT/i) {
    $dbot->process();
}
elsif ($command =~ /^UGS/i) {
    $ugsui->process();
}
elsif ($command eq "kill") {
    my $login = $self->{COMMON_HASH}{login} || "";
    my $su_login = $self->{CONF}->get("start","SU_LOGIN");
    if ($login eq $su_login) {      
            # usually only certain user with certain permission will be
            # able to do this. 
            $self->do_error("Daemon was killed by ".$login);
            $self->db_connection->disconnect();
            $self->{LOG}->write("User $login killed the daemon",0);
            exit; # this 'exit' actually kill the daemon
    }
    else {
            $self->do_error("User $login tried to kill the daemon. ".
            "This incident will be reported");
            $self->{LOG}->write("User $login tried to kill the daemon",2);
    }
}
elsif ($command eq "logout") {
    # check if we should delete the password cookie
    my $forget_me = $self->{CGI}->param("forget_me") || 0;
    if ($forget_me) {
            $self->{DB_PASSWORD_COOKIE}->delete_cookie();
    }

    $ugsui->do_logout();
    # Cliff edit remove id from logged_in
    $session->remove_session($session->login());
    # delete the session of the user
    delete $self->{SESSIONS}{$session->id()};
    if ($self->{CACHE_TO_FILE}) {
            my $session_data_path = 
                XYZ_DIR
            ."/code/cache/session_data"
        .$session->id();
            unlink($session_data_path);
    }
}
# if we just login we should create all the main frames        
elsif ($command eq "login") {
    # if extra_param holds "command*XXX" the XXX will be placed instead of
    # the command. extra_param holds pairs that are astrics-separated
    my $extra_param = $cgi->param("extra_param");
    $extra_param = "" if (!defined($extra_param));
    $extra_param =~ /command*([^*]+)/i;
    my $other_command = defined($1) ? $1 : "";
    if ($other_command =~ /^dbot/i) { # meanwhile - works only on dbot 
                                  # commands
        $command = $other_command;
            # now we will get the other parameters from the extra_param 
            # (actually including the command that is still in the 
            # $extra_param)         
            while ($extra_param =~ /^*?([^*]+)*([^*]+)(.*)/) {
            $extra_param = $3;
            my $name = $1;
            my $value = $2;     
            $cgi->param(-name => $name,-value => $value);
            }#end while
    }#end if
    else{
    $self->show_main_frames();
    }
}#end elsif
else {
    $self->show_main_frames();
}#end outer else

使用Switch

switch ($command) 
{
    case /^enter$/      { $self->show_main_frames() }
    case /^XYZ_MENU/i   { $self->show_main_menu($manual,$dbot) }
    case /^DBOT/i       { $dbot->process() }
        case /^XML_DBOT/i   { $dbot->process() }
        case /^UGS/i        { $ugsui->process() }
        case "kill"     {
                my $login = $self->{COMMON_HASH}{login} || "";
                    my $su_login = $self->{CONF}->get("start","SU_LOGIN");
                if ($login eq $su_login) {      
                        # usually only certain user with certain permission will be
                        # able to do this. 
                        $self->do_error("Daemon was killed by ".$login);
                        $self->db_connection->disconnect();
                        $self->{LOG}->write("User $login killed the daemon",0);
                        exit; # this 'exit' actually kill the daemon
                    }
                else    {
                        $self->do_error("User $login tried to kill the daemon. ".
                            "This incident will be reported");
                        $self->{LOG}->write("User $login tried to kill the daemon",2);
                    }
                    }
        case "logout"       {
                    # check if we should delete the password cookie
                    my $forget_me = $self->{CGI}->param("forget_me") || 0;
                    if ($forget_me) {
                            $self->{DB_PASSWORD_COOKIE}->delete_cookie();
                    }

                $ugsui->do_logout();
                # Cliff edit remove id from logged_in
                $session->remove_session($session->login());
                # delete the session of the user
                delete $self->{SESSIONS}{$session->id()};
                    if ($self->{CACHE_TO_FILE}) {
                            my $session_data_path = 
                                XYZ_DIR
                        ."/code/cache/session_data"
                        .$session->id();
                    unlink($session_data_path);
                    }
                    }
        case "login"        {
                # if extra_param holds "command*XXX" the XXX will be placed instead of
                # the command. extra_param holds pairs that are astrics-separated
                my $extra_param = $cgi->param("extra_param");
                $extra_param = "" if (!defined($extra_param));
                $extra_param =~ /command*([^*]+)/i;
                my $other_command = defined($1) ? $1 : "";
                if ($other_command =~ /^dbot/i) 
                    { # meanwhile - works only on dbot 
                                       # commands
                    $command = $other_command;
                        # now we will get the other parameters from the extra_param 
                        # (actually including the command that is still in the 
                        # $extra_param)         
                        while ($extra_param =~ /^*?([^*]+)*([^*]+)(.*)/) {
                        $extra_param = $3;
                        my $name = $1;
                        my $value = $2;     
                        $cgi->param(-name => $name,-value => $value);
                            }#end while
                    }#end if
                else {$self->show_main_frames();}
                }
    else            {$self->show_main_frames();}
} # end switch

解决方法

实际上Switch模块没有为您提供任何“杀手级功能”;使用elsif语句也可以做到这一点,它是安全,稳定的,没有Switch的缺点.这是我在我的项目中得到的Switch的问题(我不再使用它了):

开关是由Perl过滤器制成的.该技术具有以下限制:

>您的源代码实际上是在运行中重写并替换为
后续的elsif陈述.
>一些Perl错误报告会引用错误的行;其中一些显示您在源代码中没有的代码(自动生成的代码).

不是过滤器限制,而是模块本身的限制:

>如果您调用的文件(.pl或.pm)使用Swtich超过1Mbyte大小,则可能导致“神秘错误”(如doc中所述).我可以确认这些错误不会导致Switch模块,并且完全没有意义,所以在编码/文档编制几周后你可以有很长的调试时间.

我建议使用自Perl 5.10以来可用的elsif或given..when语句.所以如果你使用perl 5.8.x – 请使用elsif.

您还可以阅读Switch文档的“限制”段落.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读