#!perl -w =head1 NAME help - default help plugin for qpsmtpd =head1 DESCRIPTION The B plugin gives the answers for the help command. It can be configured to return C<502 Not implemented>. Without any arguments, the C is set to F<./help/>. =head1 OPTIONS =over 4 =item not_implemented (1|0) If this option is set (and the next argument is true), the plugin answers, that the B command is not implemented =item help_dir /path/to/help/files/ When a client requests help for C the file F is dumped to the client if it exists. =item COMMAND HELPFILE Any other argument pair is treated as command / help file pair. The file is expexted in the F sub directory. If the client calls C the contents of HELPFILE are dumped to him. =back =head1 NOTES The hard coded F path should be changed. =cut my %config = (); sub register { my ($self, $qp, %args) = @_; my ($file, $cmd); unless (%args) { $config{help_dir} = './help/'; } foreach (keys %args) { /^(\w+)$/ or $self->log(LOGWARN, "Invalid argument for the 'help' plugin $_"), next; $cmd = $1; if ($cmd eq 'not_implemented') { $config{'not_implemented'} = $args{'not_implemented'}; } elsif ($cmd eq 'help_dir') { $file = $args{$cmd}; $file =~ m#^([\w\.\-/]+)$# or $self->log(LOGERROR, "Invalid charachters in filename for command $cmd"), next; $config{'help_dir'} = $1; } else { $file = $args{$cmd}; $file =~ m#^([\w\.\-/]+)$# or $self->log(LOGERROR, "Invalid charachters in filename for command $cmd"), next; $file = $1; if ($file =~ m#/#) { -e $file or $self->log(LOGWARN, "No help file for command '$cmd'"), next; } else { $file = "help/$file"; if (-e "help/$file") { ## FIXME: path $file = "help/$file"; } else { $self->log(LOGWARN, "No help file for command '$cmd'"); next; } } $config{lc $cmd} = $file; } } return DECLINED; } sub hook_help { my ($self, $transaction, @args) = @_; my ($help, $cmd); if ($config{not_implemented}) { $self->qp->respond(502, "Not implemented."); return DONE; } return OK, "Try 'HELP COMMAND' for getting help on COMMAND" unless $args[0]; $cmd = lc $args[0]; unless ($cmd =~ /^(\w+)$/) { # else someone could request # "HELP ../../../../../../../../etc/passwd" $self->qp->respond(502, "Invalid command name"); return DONE; } $cmd = $1; if (exists $config{$cmd}) { $help = read_helpfile($config{$cmd}, $cmd) or $self->log(LOGERROR, "failed to open help file for $cmd: $!"), return OK, "No help available for SMTP command: $cmd"; } elsif (exists $config{'help_dir'} && -e $config{'help_dir'} . "/$cmd") { $help = read_helpfile($config{help_dir} . "/$cmd", $cmd) or $self->log(LOGERROR, "failed to open help file for $cmd: $!"), return OK, "No help available for SMTP command: $cmd"; } $help = "No help available for SMTP command: $cmd" # empty file unless $help; return OK, split(/\n/, $help); } sub read_helpfile { my ($file, $cmd) = @_; my $help; open HELP, $file or return undef; { local $/ = undef; $help = ; }; close HELP; return $help; }