Author: vetinari
Date: Fri Dec 7 01:15:00 2007
New Revision: 827
Added:
trunk/plugins/help
Log:
add help plugin, hooking the new hook_help
Added: trunk/plugins/help
==============================================================================
--- (empty file)
+++ trunk/plugins/help Fri Dec 7 01:15:00 2007
@@ -0,0 +1,145 @@
+#
+#
+#
+
+=head1 NAME
+
+help - default help plugin for qpsmtpd
+
+=head1 DESCRIPTION
+
+The B<help> plugin gives the answers for the help command. It can be configured
+to return C<502 Not implemented>.
+
+Without any arguments, the C<help_dir> 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<HELP> command is not implemented
+
+=item help_dir /path/to/help/files/
+
+When a client requests help for C<COMMAND> the file F</path/to/help/files/
+. lc(COMMAND)> 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<help/> sub directory. If the client calls C<HELP COMMAND>
+the contents of HELPFILE are dumped to him.
+
+=back
+
+=head1 NOTES
+
+The hard coded F<help/> 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 = <HELP>;
+ };
+ close HELP;
+ return $help;
+}
+
+# vim: ts=4 sw=4 expandtab syn=perl