/[qa]/trunk/pts/perl/ConfirmationSpool.pm
ViewVC logotype

Contents of /trunk/pts/perl/ConfirmationSpool.pm

Parent Directory Parent Directory | Revision Log Revision Log


Revision 283 - (show annotations) (download)
Fri Feb 1 07:00:57 2002 UTC (11 years, 4 months ago) by hertzog
File size: 4457 byte(s)
Initial revision
1 package ConfirmationSpool;
2
3 # Copyright 2002 Raphaƫl Hertzog <hertzog@debian.org>
4 # Available under the terms of the General Public License version 2
5 # or (at your option) any later version
6
7 use Digest::MD5 qw(md5_hex);
8
9 use strict;
10
11 =head1 ConfirmationSpool
12
13 A confirmation spool is a set of strings that are waiting a confirmation
14 in the form of a key. Usually the key is used to authenticate a mail
15 adress. You get a command with an email adress, and you want to be sure
16 that the email is not forged. You send a confirmation mail indicating
17 to respond with the given "key" (which should not be predictable). Once
18 you get the key back, you're sure that the email is not forged and that
19 the person concerned accepted the command that was sent.
20
21 =head2 my $cs = ConfirmationSpool->new($spooldir)
22
23 When you create a confirmation spool, you need to indicate a directory
24 in which the strings (mails) waiting a confirmation will be stored.
25
26 =cut
27 sub new {
28 my $type = shift;
29 my $class = ref($type) || $type;
30 my $directory = shift;
31
32 die "$directory is not a directory: $!\n" if (! -d $directory);
33
34 my $self = { "dir" => $directory, "sendmail" => "/usr/sbin/sendmail" };
35
36 return bless $self, $class;
37 }
38
39 =head2 $cs->set_confirmation_template($fileorstring)
40
41 Set the file used as a template to ask for a confirmation of something.
42 @CMD@ will be automatically replaced by the string to authenticate. @KEY@
43 will be replaced by the key that the user has to send back to authenticate
44 the command.
45
46 If the file doesn't exist, the param is considered as a string containing
47 the confirmation template.
48
49 The template must be a complete mail ready to be piped into "sendmail -t".
50
51 =cut
52 sub set_confirmation_template {
53 my ($self, $templ) = @_;
54 my $res = "";
55 if (-f $templ) {
56 open(TEMPLATE, "< $templ") || die "Can't open $templ : $!\n";
57 while (defined($_ = <TEMPLATE>)) {
58 $res .= $_;
59 }
60 close(TEMPLATE);
61 } else {
62 $res = $templ;
63 }
64 $self->{'template'} = $res;
65 }
66
67 =head2 $key = $cs->ask_confirmation($email, $string)
68
69 Add a string to be confirmed. Send a confirmation mail (it uses
70 the template set with set_confirmation_template)
71
72 =cut
73 sub ask_confirmation {
74 my ($self, $email, $string, $subst) = @_;
75
76 $subst = { } if (! defined $subst);
77
78 # Generate a unique code
79 srand(time());
80 my @trans = ('A' .. 'Z', 'a' .. 'z', 0 .. 9);
81 my $nb = scalar @trans;
82 my @rand;
83 for(my $i = 0; $i < 16; $i++) { push @rand, int(rand($nb)) }
84 my $key = md5_hex(join("", $string, time(), map { $trans[$_] } @rand));
85
86 # Store the string with the given key
87 open(SPOOL, "> $self->{'dir'}/$key") ||
88 die "Can't write spool file: $!\n";
89 print SPOOL $string;
90 close SPOOL;
91
92 # Send the confirmation message
93 my $msg = $self->{'template'};
94 $msg =~ s/\@EMAIL\@/$email/g;
95 $msg =~ s/\@KEY\@/$key/g;
96 foreach my $varname (keys %{$subst}) {
97 my $name = uc($varname);
98 $msg =~ s/\@$name\@/$subst->{$varname}/g;
99 }
100 open(MAIL, "| $self->{'sendmail'} -oi -t")
101 or die "Can't fork sendmail: $!\n";
102 print MAIL $msg;
103 close MAIL or die "Problem happened while sending mail: $!\n";
104 }
105
106 =head2 $string = $cs->confirm($key)
107
108 Verify that the key confirms a previously sent command. Returns the
109 command if ok, undef otherwise.
110
111 =cut
112 sub confirm {
113 my ($self, $key) = @_;
114
115 # Check in the spool
116 if (! -f "$self->{'dir'}/$key") {
117 return undef;
118 }
119
120 # Return the content of the file
121 my $msg;
122 open(SPOOL, "< $self->{'dir'}/$key") || die "Can't open $key file: $!\n";
123 while (defined($_ = <SPOOL>)) { $msg .= $_ }
124 close SPOOL;
125
126 unlink "$self->{'dir'}/$key";
127
128 return $msg;
129 }
130
131 =head2 $cs->clean()
132
133 Check the spool and remove files that have not been confirmed within
134 3 days.
135
136 =cut
137 sub clean {
138 my ($self) = @_;
139
140 # Read the content of the spool
141 opendir(DIR, $self->{'dir'}) || die "can't opendir $self->{'dir'}: $!";
142 my @files = grep { (! /^\./) && -f "$self->{'dir'}/$_" } readdir(DIR);
143 closedir DIR;
144
145 # Remove old files
146 my $t = time();
147 foreach (@files) {
148 my @stat = stat "$self->{'dir'}/$_";
149 if ($stat[9] + 86400 * 3 < $t) {
150 unlink "$self->{'dir'}/$_";
151 }
152 }
153 }
154
155 =head2 $cs->set_sendmail("/usr/sbin/sendmail");
156
157 Update the path to the sendmail binary. Sendmail is used to send
158 confirmation mails...
159
160 =cut
161 sub set_sendmail {
162 my ($self, $sendmail) = @_;
163 $self->{'sendmail'} = $sendmail;
164 }
165
166 1;

Properties

Name Value
svn:eol-style native
svn:keywords Author Date Id Revision

  ViewVC Help
Powered by ViewVC 1.1.5