3 # FEX CGI for redirect uploaded files
5 # Author: Ulli Horlacher <framstag@rus.uni-stuttgart.de>
8 use Fcntl qw(:flock :seek :mode);
10 use CGI::Carp qw(fatalsToBrowser);
12 use Digest::MD5 qw(md5_hex);
15 (our $FEXLIB) = $ENV{FEXLIB} =~ /(.+)/;
16 die "$0: no $FEXLIB\n" unless -d $FEXLIB;
18 our ($keep_default,$dkeydir,$akeydir,$mdomain,$logdir,$fra);
21 # load common code, local config : $HOME/lib/fex.ph
22 require "$FEXLIB/fex.pp" or die "$0: cannot load $FEXLIB/fex.pp - $!\n";
24 our $error = 'F*EX redirect ERROR';
26 chdir $spooldir or die "$spooldir - $!\n";
28 my $log = "$logdir/rup.log";
30 $from = $id = $oto = $nto = $file = '';
32 # look for CGI parameters
33 foreach my $v (param) {
35 $vv =~ s/[<>\'\`\"\000-\037]//g;
36 if ($v =~ /^akey$/i and $vv =~ /^(\w+)$/) {
38 } elsif ($v =~ /^(from|user)$/i) {
39 $from = normalize_address($vv);
40 $from .= '@'.$mdomain if $mdomain and $from !~ /@/;
41 } elsif ($v =~ /^id$/i) {
43 } elsif ($v =~ /^file$/i) {
45 $file = untaint(normalize($vv));
46 } elsif ($v =~ /^oto$/i) {
47 $oto = normalize_address($vv);
48 $oto .= '@'.$mdomain if $mdomain and $oto !~ /@/;
49 } elsif ($v =~ /^nto$/i) {
50 $nto = normalize_address($vv);
54 if ($akey and not $from) {
55 if (open $akey,'<',"$akeydir/$akey/@" and $id = getline($akey)) {
57 $from = readlink "$akeydir/$akey";
59 $from = untaint($from);
60 if ($akey ne md5_hex("$from:$id")) {
66 if ($from and -s "$from/\@ALLOWED_RECIPIENTS") {
67 http_die("You are a restricted user");
71 open F,'<',"$from/@" or http_die("wrong user or auth-ID");
74 http_die("wrong user or auth-ID") if $id ne $rid;
76 $akey = untaint(md5_hex("$from:$id"));
77 unlink "$akeydir/$akey";
78 symlink "../$from","$akeydir/$akey";
81 http_die("wrong user or auth-ID");
84 if ($oto and not glob("$oto/$from/*")) {
85 http_die("$oto has no no files in spool from you ($from)");
88 # display HTML form and request user data
89 unless ($from and $id and $file and $oto and $nto) {
90 $head = "$ENV{SERVER_NAME} F*EX redirect";
91 http_header("200 OK");
92 print html_header($head);
94 '<form action="$ENV{SCRIPT_NAME}" method="post"'
95 ' accept-charset="UTF-8" enctype="multipart/form-data">'
99 print "<input type=\"hidden\" name=\"akey\" value=\"$akey\">\n";
103 ' <td><input type="text" name="from" size="80" value="$from"></tr>'
105 ' <td><input type="password" name="id" size="16" value="$id"></tr>'
110 ' <tr><td>old (wrong) recipient:<td>$oto</tr>'
111 ' <input type="hidden" name="oto" value="$oto">'
115 ' <tr><td>old (wrong) recipient:'
116 ' <td><input type="text" name="oto" size="80" value="$oto"></tr>'
119 if ($from and $oto) {
121 ' <tr><td>new recipient:'
122 ' <td><input type="text" name="nto" size="80" value="$nto"></tr>'
123 ' <tr><td>filename: <td><select name="file" size="1">'
126 print "\t<option>$file</option>\n";
128 foreach my $file (glob "$oto/$from/*/data") {
129 next if $file =~ m:/STDFEX/:;
131 if ($filename = filename($file)) {
132 print "\t<option>$filename</option>\n";
141 ' <input type="submit" value="submit">'
144 '<a href="/foc?akey=$akey">back to F*EX operation control</a>'
152 # read aliases from address book
153 if (open my $AB,'<',"$from/\@ADDRESS_BOOK") {
157 if (s/^\s*(\S+)[=\s]+(\S+)//) {
158 my ($alias,$address) = ($1,$2);
159 if ($nto eq $alias) {
168 $nto .= '@'.$mdomain if $mdomain and $nto !~ /@/ and $nto =~ /\w/;
169 checkaddress($nto) or http_die("$nto is not a valid e-mail address");
171 http_die("no new recipient given");
174 if ($oto and $nto and $oto eq $nto) {
175 http_die("new recipient must be other than old recipient");
178 $fkey = urlencode($file);
179 unless (-s "$oto/$from/$fkey/data") {
180 http_die("no upload data found for $file for $oto");
183 if (not -e "$oto/$from/$fkey/data") {
184 if (my $download = slurp("$oto/$from/$fkey/download")) {
186 http_die("$file already downloaded by $download");
188 http_die("$file has gone");
191 mkdirp("$nto/$from");
192 rmrf("$nto/$from/$fkey");
194 if (rename "$oto/$from/$fkey","$nto/$from/$fkey") {
195 mkdirp("$oto/$from/$fkey");
196 if (open $fkey,'>',"$oto/$from/$fkey/error") {
197 print {$fkey} "$from has removed $file\n";
200 unlink "$nto/$from/$fkey/dkey";
201 unlink "$nto/$from/$fkey/notify";
202 unlink "$nto/$from/$fkey/error";
203 unlink "$nto/$from/$fkey/download";
204 if (slurp("$oto/$from/$fkey/$comment") =~ 'NOMAIL') {
205 unlink "$nto/$from/$fkey/comment";
207 $dkey = randstring(8);
208 symlink $dkey,"$nto/$from/$fkey/dkey";
209 symlink "../$nto/$from/$fkey","$dkeydir/$dkey";
210 $filename = filename("$nto/$from/$fkey") || $fkey;
211 notify_locale($dkey,'new');
212 ruplog("$oto/$from/$fkey ==> $nto");
213 http_header("200 OK");
214 print html_header('F*EX redirect');
216 '<h3>F*EX redirect</h3>'
217 'notification of file upload \"$filename\" sent to $nto'
219 '<a href="/foc?akey=$akey">back to F*EX operation control</a>'
223 http_die("redirect $nto/$from/$fkey failed : $!")
229 sub normalize_address {
231 s/[<>;,\s\|\/\'\`\"\000-\037]//g;
243 if (open $log,'>>',$log) {
245 seek $log,0,SEEK_END;
246 printf {$log} "%s [%s_%s] (%s) %s\n",
247 isodate(time),$$,$ENV{REQUESTCOUNT},$fra,$msg;