-
Notifications
You must be signed in to change notification settings - Fork 74
/
Copy pathhelp
142 lines (115 loc) · 3.78 KB
/
help
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
#!perl -w
=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;
}