3 # FEX CGI for redirect uploaded files
5 # Author: Ulli Horlacher <framstag@rus.uni-stuttgart.de>
8 BEGIN { ($ENV{PERLINIT}||'') =~ /(.+)/s and eval $1 }
10 use Fcntl qw(:flock :seek :mode);
11 use Digest::MD5 qw(md5_hex);
14 (our $FEXLIB) = $ENV{FEXLIB} =~ /(.+)/;
15 die "$0: no $FEXLIB\n" unless -d $FEXLIB;
17 our ($keep_default,$dkeydir,$akeydir,$mdomain,@logdir,$fra);
20 # load common code, local config : $HOME/lib/fex.ph
21 require "$FEXLIB/fex.pp" or die "$0: cannot load $FEXLIB/fex.pp - $!\n";
23 our $error = 'F*EX redirect ERROR';
25 chdir $spooldir or die "$spooldir - $!\n";
27 $from = $id = $oto = $nto = $file = '';
29 # look for CGI parameters
32 foreach my $v (keys %PARAM) {
34 $vv =~ s/[<>\'\`\"\000-\037]//g;
35 if ($v =~ /^akey$/i and $vv =~ /^(\w+)$/) {
37 } elsif ($v =~ /^(from|user)$/i) {
38 $from = normalize_address($vv);
39 $from .= '@'.$mdomain if $mdomain and $from !~ /@/;
40 } elsif ($v =~ /^id$/i) {
42 } elsif ($v =~ /^file$/i) {
44 $file = untaint(normalize($vv));
45 } elsif ($v =~ /^oto$/i) {
46 $oto = normalize_address($vv);
47 $oto .= '@'.$mdomain if $mdomain and $oto !~ /@/;
48 } elsif ($v =~ /^nto$/i) {
49 $nto = normalize_address($vv);
53 if ($akey and not $from) {
54 if (open $akey,'<',"$akeydir/$akey/@" and $id = getline($akey)) {
56 $from = readlink "$akeydir/$akey";
58 $from = untaint($from);
59 if ($akey ne md5_hex("$from:$id")) {
65 if ($from and -s "$from/\@ALLOWED_RECIPIENTS") {
66 http_die("You are a restricted user");
70 open F,'<',"$from/@" or http_die("wrong user or auth-ID");
73 http_die("wrong user or auth-ID") if $id ne $rid;
75 $akey = untaint(md5_hex("$from:$id"));
76 unlink "$akeydir/$akey";
77 symlink "../$from","$akeydir/$akey";
80 http_die("wrong user or auth-ID");
83 if ($oto and not glob("$oto/$from/*")) {
84 http_die("$oto has no no files in spool from you ($from)");
87 # display HTML form and request user data
88 unless ($from and $id and $file and $oto and $nto) {
89 $head = "$ENV{SERVER_NAME} F*EX redirect";
90 http_header("200 OK");
91 print html_header($head);
93 '<form action="$ENV{SCRIPT_NAME}" method="post"'
94 ' accept-charset="UTF-8" enctype="multipart/form-data">'
98 print "<input type=\"hidden\" name=\"akey\" value=\"$akey\">\n";
102 ' <td><input type="text" name="from" size="80" value="$from"></tr>'
104 ' <td><input type="password" name="id" size="16" value="$id"></tr>'
109 ' <tr><td>old (wrong) recipient:<td>$oto</tr>'
110 ' <input type="hidden" name="oto" value="$oto">'
114 ' <tr><td>old (wrong) recipient:'
115 ' <td><input type="text" name="oto" size="80" value="$oto"></tr>'
118 if ($from and $oto) {
120 ' <tr><td>new recipient:'
121 ' <td><input type="text" name="nto" size="80" value="$nto"></tr>'
122 ' <tr><td>filename: <td><select name="file" size="1">'
125 print "\t<option>$file</option>\n";
127 foreach my $file (glob "$oto/$from/*/data") {
128 next if $file =~ m:/STDFEX/:;
130 if ($filename = filename($file)) {
131 print "\t<option>$filename</option>\n";
140 ' <input type="submit" value="submit">'
143 '<a href="/foc?akey=$akey">back to F*EX operation control</a>'
151 # read aliases from address book
152 if (open my $AB,'<',"$from/\@ADDRESS_BOOK") {
156 if (s/^\s*(\S+)[=\s]+(\S+)//) {
157 my ($alias,$address) = ($1,$2);
158 if ($nto eq $alias) {
167 $nto .= '@'.$mdomain if $mdomain and $nto !~ /@/ and $nto =~ /\w/;
168 checkaddress($nto) or http_die("$nto is not a valid e-mail address");
170 http_die("no new recipient given");
173 if ($oto and $nto and $oto eq $nto) {
174 http_die("new recipient must be other than old recipient");
177 $fkey = urlencode($file);
178 unless (-s "$oto/$from/$fkey/data") {
179 http_die("no upload data found for $file for $oto");
182 if (not -e "$oto/$from/$fkey/data") {
183 if (my $download = slurp("$oto/$from/$fkey/download")) {
185 http_die("$file already downloaded by $download");
187 http_die("$file has gone");
190 mkdirp("$nto/$from");
191 rmrf("$nto/$from/$fkey");
193 if (rename "$oto/$from/$fkey","$nto/$from/$fkey") {
194 mkdirp("$oto/$from/$fkey");
195 if (open $fkey,'>',"$oto/$from/$fkey/error") {
196 print {$fkey} "$from has removed $file\n";
199 unlink "$nto/$from/$fkey/dkey";
200 unlink "$nto/$from/$fkey/notify";
201 unlink "$nto/$from/$fkey/error";
202 unlink "$nto/$from/$fkey/download";
203 if (slurp("$oto/$from/$fkey/comment")||'' =~ /NOMAIL/) {
204 unlink "$nto/$from/$fkey/comment";
206 $dkey = randstring(8);
207 symlink $dkey,"$nto/$from/$fkey/dkey";
208 symlink "../$nto/$from/$fkey","$dkeydir/$dkey";
209 $filename = filename("$nto/$from/$fkey") || $fkey;
210 notify_locale($dkey,'new');
211 ruplog("$oto/$from/$fkey ==> $nto");
212 http_header("200 OK");
213 print html_header('F*EX redirect');
215 '<h3>F*EX redirect</h3>'
216 'notification of file upload \"$filename\" sent to $nto'
218 '<a href="/foc?akey=$akey">back to F*EX operation control</a>'
222 http_die("redirect $nto/$from/$fkey failed : $!")
228 sub normalize_address {
230 s/[<>;,\s\|\/\'\`\"\000-\037]//g;
241 $msg = sprintf "%s [%s_%s] (%s) %s\n",
242 isodate(time),$$,$ENV{REQUESTCOUNT},$fra,$msg;
244 foreach my $log (@logdir) {
245 if (open $log,'>>',"$log/rup.log") {
247 seek $log,0,SEEK_END;