perl – 这个使用Switch.pm的代码是否安全?
在我们公司,我们使用这个代码(在最后给出)大约10年,它工作正常.
几天前我们遇到了一些问题,我们不得不重新编写完整的包,我们决定用Damian的Switch模块替换这个代码(为了提高代码的可读性). 一切都对我们很好. 后来我在Perlmonks发现达米安把这个模块放在了下面
但它对我们来说工作正常,因为我们没有达到这个模块的限制(我猜). 现在我请大家看一下这两个实现(嵌套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过滤器制成的.该技术具有以下限制: >您的源代码实际上是在运行中重写并替换为 不是过滤器限制,而是模块本身的限制: >如果您调用的文件(.pl或.pm)使用Swtich超过1Mbyte大小,则可能导致“神秘错误”(如doc中所述).我可以确认这些错误不会导致Switch模块,并且完全没有意义,所以在编码/文档编制几周后你可以有很长的调试时间. 我建议使用自Perl 5.10以来可用的elsif或given..when语句.所以如果你使用perl 5.8.x – 请使用elsif. 您还可以阅读Switch文档的“限制”段落. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |