X-Git-Url: https://git.treefish.org/fex.git/blobdiff_plain/e60096926213ce02293a261254ff065cae44c1c8..cdeb354c4dbb11b683f9f8c5db2861f3dc572c61:/cgi-bin/fup diff --git a/cgi-bin/fup b/cgi-bin/fup index b1e01e6..2a799ac 100755 --- a/cgi-bin/fup +++ b/cgi-bin/fup @@ -10,6 +10,7 @@ BEGIN { ($ENV{PERLINIT}||'') =~ /(.+)/s and eval $1 } +use utf8; use Encode; use Fcntl qw':flock :seek :mode'; use IO::Handle; @@ -37,7 +38,7 @@ our (@registration_hosts,@demo,@file_link_dirs); our ($FEXHOME); our ($spooldir,$durl,$tmpdir,@logdir,$logdir,$docdir,$hostname,$admin,$fra); our ($keep_default,$recipient_quota,$sender_quota,$fex_yourself); -our ($sendmail,$mdomain,$fop_auth,$mail_auth,$faillog); +our ($sendmail,$mdomain,$fop_auth,$mail_auth,$faillog,$amdl); our ($dkeydir,$ukeydir,$akeydir,$skeydir,$gkeydir,$xkeydir); our ($MB,$DS); our $RB; # read POST bytes (total) @@ -57,7 +58,8 @@ my @header; # HTTP entity header my $fileid; # file ID my $captive; my $muser; # main user fur sub or group user - +my %specific; # upload specific KEEP and AUTODELETE parameters + # load common code, local config: $FEXLIB/fex.ph require "$FEXLIB/fex.pp"; @@ -66,7 +68,7 @@ our ($info_1,$info_2,$info_login); $locale = $ENV{LOCALE} || 'english'; foreach ( - "/var/lib/fex/locale/$locale/lib/fup.pl", + "/var/lib/fex/locale/$locale/lib/fup.pl", "$FEXLIB/fup.pl", ) { if (-f) { @@ -108,7 +110,8 @@ if ($addto) { my %to; foreach $to (@to) { $to{$to} = 1 } push @to,$addto unless $to{$addto}; - if ($submit and @to == 1) { $addto = '' } + # user has submitted with [select from your address book] ? + # if ($submit and @to == 1) { $addto = '' } } $to = join(',',@to); @@ -129,7 +132,7 @@ if ($from and $id_forgotten and $mail_authid and not ($fop_auth or $nomail)) { # public recipients? (needs no auth-ID for sender) if ($to and $id and $id eq 'PUBLIC' and @public_recipients) { - + unless ($from) { http_die("missing sender e-mail address"); } @@ -146,12 +149,12 @@ if ($to and $id and $id eq 'PUBLIC' and @public_recipients) { } # anonymous upload from enabled IP? -if ($from =~ /^anonymous@/ and +if ($from =~ /^anonymous@/ and @anonymous_upload and ipin($ra,@anonymous_upload)) { $id = $rid = $anonymous = 'anonymous'; if ($to =~ /^anonymous/) { @to = ($to); - $autodelete{$to} = $autodelete = 'NO'; + $autodelete{$to} = $autodelete = $specific{'autodelete'}||'NO'; } $nomail = $anonymous; } @@ -161,7 +164,7 @@ $comment = 'NOMAIL' if $nomail and not $comment; # one time token if ($okey) { $to = "@to" or http_die("no recipient specified"); - $from = readlink "$to/\@OKEY/$okey" + $from = readlink "$to/\@OKEY/$okey" or http_die("no upload key \"$okey\" - ". "request another one from $to"); $from = untaint($from); @@ -199,10 +202,9 @@ if ($from and $id and not ($gkey or $skey or $public or $okey)) { # set akey link for HTTP sessions # (need original id for consistant non-moving akey) if (-d $akeydir and open $idf,'<',"$from/@" and my $id = getline($idf)) { - $akey = untaint(md5_hex("$from:$id")); - mksymlink("$akeydir/$akey","../$from"); - # show URL from fexsend - if ($from eq $to and $comment eq '*') { + # akey for webbrowser or fexsend special + if (not $sid or ($from eq $to and ($comment eq '*')) or $command) { + $akey = untaint(md5_hex("$from:$id")); mksymlink("$akeydir/$akey","../$from"); } } @@ -252,12 +254,12 @@ if ($akey and $dkey and $command eq 'COPY') { http_die("File not found"); } if (-e "$to/$to/$file/data") { - http_die("File $file already exists in your outgoing spool") - if (readlink("$to/$to/$file/id")||$to) ne + http_die("File $file already exists in your outgoing spool") + if (readlink("$to/$to/$file/id")||$to) ne (readlink("$to/$from/$file/id")||$from); } else { mkdirp("$to/$to/$file"); - link "$to/$from/$file/data","$to/$to/$file/data" + link "$to/$from/$file/data","$to/$to/$file/data" or http_die("cannot link to $to/$to/$file/data - $!\n"); copy("$to/$from/$file/filename","$to/$to/$file/filename"); copy("$to/$from/$file/id","$to/$to/$file/id"); @@ -302,7 +304,7 @@ if ($akey and $dkey and $command eq 'DELETE') { "" ); &reexec; - } else { + } else { my $s = $!; http_header('404 Not Found'); print html_header($head); @@ -315,7 +317,7 @@ if ($akey and $dkey and $command eq 'DELETE') { # special commands if (($from and $id and $rid eq $id or $gkey or $skey) and $command) { - + if ($command eq 'CHECKQUOTA') { http_die("illegal command \"$command\"") if $public or $anonymous; nvt_print('HTTP/1.1 204 OK'); @@ -390,9 +392,9 @@ if (($from and $id and $rid eq $id or $gkey or $skey) and $command) { $filename = <$file>; close $file; } - if ($filename and length $filename) { + if ($filename and length $filename) { $filename = html_quote($filename); - } else { + } else { $filename = '???'; } if (open $file,'<',"$file/comment") { @@ -401,22 +403,22 @@ if (($from and $id and $rid eq $id or $gkey or $skey) and $command) { } my $rkeep = untaint(readlink "$file/keep"||$keep_default) - int((time-mtime("$file/filename"))/$DS); - if ($comment =~ /NOMAIL/ or + if ($comment =~ /NOMAIL/ or (readlink "$to/\@NOTIFICATION"||'') =~ /^no/i) { - printf "%8s MB [%s d] %s/%s/%s\n", + printf "%8s MB (%2s d) %s/%s/%s\n", $size, $rkeep, $durl, $dkey, urlencode(basename($file)); } else { - printf "%8s MB [%s d] %s%s %s\n", + printf "%8s MB (%2s d) %s%s %s\n", $size, $rkeep, untaint("/fup?akey=$akey&dkey=$dkey&command=RENOTIFY"), $filename, $comment ? qq' "$comment"' : '', - $file eq $nfile ? + $file eq $nfile ? " → notification e-mail has been resent" : ""; } @@ -428,7 +430,7 @@ if (($from and $id and $rid eq $id or $gkey or $skey) and $command) { '' )); exit; - } + } if ($command =~ /^LIST(RECEIVED)?$/) { http_die("illegal command \"$command\"") if $public or $anonymous; @@ -458,20 +460,21 @@ if (($from and $id and $rid eq $id or $gkey or $skey) and $command) { $filename = <$file>; close $file; } - if ($filename and length $filename) { + if ($filename and length $filename) { $filename = html_quote($filename); - } else { + } else { $filename = '???'; } if (open $file,'<',"$file/comment") { $comment = untaint(html_quote(getline($file))); close $file; } - my $rkeep = untaint(readlink "$file/keep"||$keep_default) + my $rkeep = untaint(readlink "$file/keep"||$keep_default) - int((time-mtime("$file/filename"))/$DS); - printf "%8s MB [%s d] %s%s\n", + printf "%8s MB (%2s d) %s %s%s\n", $size, $rkeep, + stat("$file/download")?'+':'-', untaint("/fup?akey=$akey&dkey=$dkey&command=FORWARD"), $filename, $comment?qq( "$comment"):''; @@ -482,7 +485,7 @@ if (($from and $id and $rid eq $id or $gkey or $skey) and $command) { '

back to F*EX operation control' '' )); - } + } # list received files else { $to = $from; @@ -512,9 +515,9 @@ if (($from and $id and $rid eq $id or $gkey or $skey) and $command) { $filename = <$file>; close $file; } - if ($filename and length $filename) { + if ($filename and length $filename) { $filename = html_quote($filename); - } else { + } else { $filename = '???'; } if (open $file,'<',"$file/comment") { @@ -522,13 +525,13 @@ if (($from and $id and $rid eq $id or $gkey or $skey) and $command) { $comment = ' "'.$comment.'"'; close $file; } - my $rkeep = untaint(readlink "$file/keep"||$keep_default) + my $rkeep = untaint(readlink "$file/keep"||$keep_default) - int((time-mtime("$file/filename"))/$DS); printf "[delete] ", $akey,$dkey; printf "[forward] ", $akey,$dkey; - printf "%8s MB (%s d) %s%s\n", + printf "%8s MB (%2s d) %s%s\n", $size,$rkeep,$url,$filename,$comment; } } @@ -541,11 +544,11 @@ if (($from and $id and $rid eq $id or $gkey or $skey) and $command) { )); } exit; - } - + } + if ($command eq 'LISTSENT') { http_die("illegal command \"$command\"") if $public or $anonymous; - # show download URLs + # show download URLs http_header('200 OK'); print html_header($head); print "

Download URLs of files you have sent\n"; @@ -571,7 +574,7 @@ if (($from and $id and $rid eq $id or $gkey or $skey) and $command) { )); exit; } - + if ($command eq 'FOPLOG') { http_die("illegal command \"$command\"") if $public or $anonymous; if (open my $log,"$logdir/fop.log") { @@ -588,14 +591,14 @@ if (($from and $id and $rid eq $id or $gkey or $skey) and $command) { } exit; } - + if ($command eq 'RECEIVEDLOG') { http_die("illegal command \"$command\"") if $public or $anonymous; if (open my $log,"$logdir/fup.log") { http_header('200 OK'); while (<$log>) { next if /\sSTDFEX\s/; - if (/\d+$/) { + if (/\d+$/) { my @F = split; if ($F[5] eq $to) { s/ \[[\d_]+\]//; @@ -613,7 +616,7 @@ if (($from and $id and $rid eq $id or $gkey or $skey) and $command) { http_header('200 OK'); while (<$log>) { next if /\sSTDFEX\s/; - if (/(\S+\@\S+)/ and $1 eq $from) { + if (/(\S+\@\S+)/ and $1 eq $from) { s/ \[[\d_]+\]//; print; } @@ -630,11 +633,12 @@ if (($from and $id and $rid eq $id or $gkey or $skey) and $command) { foreach my $to (@group?@group:@to) { # my $options = sprintf "(autodelete=%s,keep=%s,locale=%s)", # readlink "$to/\@LOCALE"||$locale||$locale{$to}||$default_locale; - my $options = sprintf "(autodelete=%s,keep=%s,locale=%s,notification=%s)", + # my $options = sprintf "(autodelete=%s,keep=%s,locale=%s,notification=%s)", + my $options = sprintf "(autodelete=%s,keep=%s,locale=%s)", $autodelete{$to}||$autodelete, $keep{$to}||$keep_default, - readlink("$to/\@LOCALE")||$default_locale, - readlink("$to/\@NOTIFICATION")||'full'; + readlink("$to/\@LOCALE")||$locale{$to}||$default_locale; + # readlink("$to/\@NOTIFICATION")||'full'; nvt_print("X-Recipient: $to $options"); } nvt_print(''); @@ -656,7 +660,7 @@ if (($from and $id and $rid eq $id or $gkey or $skey) and $command) { http_die("illegal parameter $del"); } $del = untaint($del); - + if (unlink("$del/data") or unlink("$del/upload")) { if (open F,'>',"$del/error") { print F "$file has been deleted by $from\n"; @@ -665,7 +669,7 @@ if (($from and $id and $rid eq $id or $gkey or $skey) and $command) { http_header('200 OK',"X-File: $del"); print html_header($head); print "

$file deleted

\n"; - } else { + } else { http_header("404 Not Found"); print html_header($head); print "

$file not deleted

\n"; @@ -695,16 +699,16 @@ if ($from and $id and $rid eq $id and open my $ipr,"$from/\@UPLOAD_HOSTS") { } } -# quotas +# quotas if ($from and $id and $rid eq $id and @to and not $flink and not $seek) { my ($quota,$du); - + # check sender quota ($quota,$du) = check_sender_quota($muser||$from); if ($quota and $du+$cl/$MB > $quota) { http_die("you are overquota"); } - + # check recipient quota foreach my $to (@to) { ($quota,$du) = check_recipient_quota($to); @@ -731,7 +735,7 @@ if (not $addto and $fop_auth and $id and $id eq $rid and $from and @to) { if (open $idf,'<',"$to/@") { $to_reg = getline($idf); close $idf; - } + } # sub user? elsif (open $idf,'<',"$from/\@SUBUSER") { while (<$idf>) { @@ -755,7 +759,7 @@ if (not $addto and $fop_auth and $id and $id eq $rid and $from and @to) { } $to = join(',',@to); - + if ($to =~ /^@(.+)/) { if ($nomail) { http_die("server runs in NOMAIL mode - groups ($to) are not allowed"); @@ -788,18 +792,18 @@ if ($from and $id and $id eq $rid and $faillog) { # display HTML form and request user data unless ($file) { - if ($test) { $cgi = $test } + if ($test) { $cgi = $test } else { $cgi = $ENV{SCRIPT_NAME} } $cgi = 'fup'; - + # delete old cookies on logout referer my @cookies; if ($logout and my $cookie = $ENV{HTTP_COOKIE}) { while ($cookie =~ s/(\w+key)=\w+//) { - push @cookies,"Set-Cookie: $1=; Max-Age=0; Discard"; + push @cookies,"Set-Cookie: $1=x; path=/; expires=Thu, 01 Jan 1970 00:00:00 GMT"; } } - + if (($akey or $skey or $gkey) and $from and -d $from) { # save default locale for this user if (not $locale and ($ENV{HTTP_COOKIE}||'') =~ /\blocale=(\w+)/) { @@ -811,7 +815,7 @@ unless ($file) { http_header('200 OK',@cookies); # print html_header($head,''); print html_header($head); - + if ($http_client =~ /(Konqueror|w3m)/) { pq(qq( '


' @@ -824,11 +828,11 @@ unless ($file) { } # default "fex yourself" setting? - if ($from and $id and $id eq $rid and not $addto + if ($from and $id and $id eq $rid and not $addto and not ($gkey or $skey or $okey or $public or $anonymous) and (not @to or "@to" eq $from) and -f "$from/\@FEXYOURSELF") - { + { @to = ($from); $nomail = 'fexyourself'; } @@ -838,9 +842,11 @@ unless ($file) { and not ($gkey or $skey or $okey or $public or $anonymous)) { present_locales('/fup'); - + + # print "[$addto] [$submit] [@to]

\n"; + @ab = (""); - + # select menu from server address book if (open my $AB,'<',"$from/\@ADDRESS_BOOK") { while (<$AB>) { @@ -848,12 +854,13 @@ unless ($file) { if (/(\S+)[=\s]+(\S+@[\w.-]+\S*)/) { $_ = "$1 <$2>"; s/,.*/,.../g; + s/:.*/>/; push @ab,""; } } close $AB; } - + unless (@to) { unless ($nomail) { foreach (glob "$from/\@GROUP/*") { @@ -864,7 +871,7 @@ unless ($file) { } } } - + my $ab64 = b64("from=$from&id=$id"); # '

' ' ' ' ' - ' ' + ' ' '
sender: $from
sender: $from
recipient(s):' '
' )); @@ -908,6 +915,11 @@ unless ($file) { foreach my $rd (@local_rdomains) { print "*\@$rd\n"; } + } elsif (/^\@LOCAL_USERS/) { + foreach (glob "*/@") { + s:/.::; + print "$_\n"; + } } else { print "$_\n"; } @@ -925,14 +937,14 @@ unless ($file) { 'user config & operation control' )); } - + if ($from eq $admin ) { pq(qq( '

' 'server config & admin control' )); } - + if (0 and -f "$docdir/FIX.jar") { print "

\n"; if ($public) { print "" } @@ -942,13 +954,23 @@ unless ($file) { print "Alternate Java client (for files > 2 GB or sending of more than one file)\n"; } print &logout; - if (-x "$FEXHOME/cgi-bin/login") { - print $info_login||$info_1; - } - print "\n"; + pq(qq( + '


' + '' + 'Warning: the recipient must not be a mailing list,' + 'because after download the file will be no more available!' + '
' + 'Contact fexmaster if you want to fex to a mailing list,' + 'he can allow multiple downloads for specific addresses.' + '

' + 'Use a F*EX client if you want to send more than one file or resume an interrupted upload.' + '' + '

' + )); + print $info_1; exit; - } - + } + # ask for filename if ($from and ($id or $okey)) { $to = $group if $group; @@ -957,16 +979,14 @@ unless ($file) { pq(qq( '\n"; exit; @@ -1809,7 +1903,7 @@ sub showstatus { "no file data received - does your file exist or is it >2GB?") } html_error($error,"file size unknown") unless $tsize =~ /^\d+$/; - + http_header('200 OK'); if (open $ukey,'<',"$ukey/filename") { local $/; @@ -1817,14 +1911,14 @@ sub showstatus { close $ukey; } http_die("no filename?!") unless $file; - + my $ssize = $tsize; if ($ssize<2097152) { $ssize = sprintf "%d kB",int($ssize/1024); } else { $ssize = sprintf "%d MB",int($ssize/1048576); } - + pq(qq( "" "

" @@ -1836,7 +1930,7 @@ sub showstatus { "
" "
" )); - + # wait for upload file for (1..9) { last if -f $upload or -f $data; @@ -1847,13 +1941,13 @@ sub showstatus { print $wclose; exit; } - + $SIG{ALRM} = sub { die "TIMEOUT in showstatus: no (more) data received\n" }; alarm($timeout*2); - + $t0 = $t1 = time; $osize = $percent = $npercent = 0; - + for ($percent = 0; $percent<100; sleep(1)) { $t2 = time; $nsize = -s $upload; @@ -1877,7 +1971,7 @@ sub showstatus { # so, updating more often is contra-productive if ($t2>$t1+5 or $npercent>$percent) { $percent = $npercent; - $t1 = $t2; + $t1 = $t2; $tm = int(($t2-$t0)/60); $ts = $t2-$t0-$tm*60; $tt = sprintf("%d:%02d",$tm,$ts); @@ -1889,7 +1983,7 @@ sub showstatus { )) or last; } } - + alarm(0); if ($npercent == 100) { print "

file successfully transferred

\n"; @@ -1934,26 +2028,26 @@ sub get_file { http_die("$filed locked: a download is currently in progress"); } } - + # prepare upload foreach $to (@to) { $to =~ s/:\w+=.*//; # remove options from address $filed = "$to/$from/$fkey"; $nupload = "$filed/upload"; # upload for next recipient mkdirp($filed); - + # upload already prepared (for first recipient)? if ($upload) { # link upload for next recipient unless ($upload eq $nupload or -r $upload and -r $nupload and - (stat $upload)[1] == (stat $nupload)[1]) + (stat $upload)[1] == (stat $nupload)[1]) { unlink $nupload; link $upload,$nupload; } - } - + } + # first recipient => create upload else { $upload = $nupload; @@ -2005,7 +2099,7 @@ sub get_file { symlink "../$filed","$ukeydir/$uid"; } } - + unlink "$filed/autodelete", "$filed/error", "$filed/restrictions", @@ -2021,7 +2115,7 @@ sub get_file { "$filed/comment", "$filed/notify"; unlink "$filed/size" unless $seek; - + # showstatus needs file name and size # fexsend needs full file size (+$seek) $fh = "$filed/filename"; @@ -2035,19 +2129,19 @@ sub get_file { unless ($seek) { if ($::filesize > 0) { # total file size as reported by POST - mksymlink("$filed/size",$::filesize) + mksymlink("$filed/size",$::filesize) or die "cannot write $filed/size - $!\n"; } else { # file size as counted - mksymlink("$filed/size",$filesize) + mksymlink("$filed/size",$filesize) or die "cannot write $filed/size - $!\n"; } } } - + if ($from eq "@to") { # special "fex yourself" - mksymlink("$filed/autodelete",'NO'); + mksymlink("$filed/autodelete",$specific{'autodelete'}||'NO'); } else { $autodelete{$to} = $autodelete unless $autodelete{$to}; if ($autodelete{$to} =~ /^(DELAY|NO|\d+)$/i) { @@ -2077,24 +2171,24 @@ sub get_file { if ($replyto and $replyto =~ /.@./) { mksymlink("$filed/replyto",$replyto); } - + my $arh = "$from/\@ALLOWED_RHOSTS"; if (-s $arh) { copy($arh,"$filed/restrictions"); } - + if (@header and open $fh,'>',"$filed/header") { print {$fh} join("\n",@header),"\n"; close $fh; } - + if ((readlink "$to/\@NOTIFICATION"||'') =~ /^no/i) { $nomail{$to} = 'NOTIFICATION'; } if ($nomail) { open $fh,'>',"$filed/notify" and close $fh; - } + } if ($comment) { if (open $fh,'>',"$filed/comment") { print {$fh} encode_utf8($comment); @@ -2106,17 +2200,17 @@ sub get_file { unless ($dkey = readlink("$filed/dkey") and -l "$dkeydir/$dkey") { $dkey = randstring(8); unlink "$dkeydir/$dkey"; - symlink "../$filed","$dkeydir/$dkey" + symlink "../$filed","$dkeydir/$dkey" or http_die("cannot symlink $dkeydir/$dkey ($!)"); unlink "$filed/dkey"; symlink $dkey,"$filed/dkey"; } - + } # extra download (XKEY)? if ($anonymous and $fkey =~ /^afex_\d/ or - $from eq "@to" and $comment =~ s:^//(.*)$:NOMAIL:) + $from eq "@to" and $comment =~ s:^//(.*)$:NOMAIL:) { $xkey = $1||$fkey; $nomail = $comment; @@ -2125,15 +2219,15 @@ sub get_file { if (-e $x) { http_die("extra download key $xkey already exists"); } - symlink "../$from/$from/$fkey",$x + symlink "../$from/$from/$fkey",$x or http_die("cannot symlink $x - $!\n"); unlink "$x/xkey"; symlink $xkey,"$x/xkey"; } } - + } - + # file link? if ($flink) { # upload link has been already created, no data to read any more @@ -2147,7 +2241,7 @@ sub get_file { # at last, read (real) file data $t0 = time(); - + # streaming data? if ($cl == -1) { alarm($timeout*2); @@ -2161,11 +2255,11 @@ sub get_file { } # size of transferred file, without end boundary $ndata = untaint($fb-$ebl); - } - + } + # normal file with known file size else { - + if ($fpsize) { debuglog(sprintf("still awaiting %d+%d = %d bytes", $fpsize,$ebl,$fpsize+$ebl)); @@ -2179,7 +2273,7 @@ sub get_file { } # read until end boundary, not EOF while ($RB < $cl-$ebl) { - $b = $cl-$ebl-$RB; + $b = $cl-$ebl-$RB; $b = $bs if $b > $bs; # max wait for 1 kB/s, but at least 10 s # $timeout = $b/1024; @@ -2213,17 +2307,17 @@ sub get_file { } $RB += $ebl; $ndata = untaint($fb); - } + } alarm(0); - + unless ($nostore) { close $upload; # or die "cannot close $upload - $!\n";; - + # throuput in kB/s $tt = (time-$t0) || 1; mksymlink("$filed/speed",int($fb/1024/$tt)); - + unless ($ndata) { http_die( "No file data received!". @@ -2231,12 +2325,12 @@ sub get_file { " File too big (browser-limit: 2 GB!)?" ); } - + $to = join(',',@to); - + # streaming upload? if ($cl == -1) { - + open $upload,'<',$upload or http_die("internal error - cannot read upload"); seek $upload,$ndata+2,0; $_ = <$upload>||''; @@ -2245,12 +2339,12 @@ sub get_file { } close $upload; truncate $upload,$ndata; - + } else { - + # truncate boundary string # truncate $upload,$ndata+$uss if -s $upload > $ndata+$uss; - + # incomplete? if ($cl != $RB) { fuplog($to,$fkey,$ndata,'(aborted)'); @@ -2260,19 +2354,19 @@ sub get_file { http_die("read $RB bytes, but CONTENT_LENGTH announces $cl bytes"); } } - + # multipost, not complete if ($::filesize > -s $upload) { http_header('206 Partial OK'); exit; } - + # save error? if (-s $upload > ($::filesize||$filesize)) { fuplog($to,$fkey,$ndata,'(write error: upload > filesize)'); http_die("internal server error while writing file data"); } - + } fuplog($to,$fkey,$ndata); debuglog("upload successfull, dkey=$dkey"); @@ -2287,7 +2381,7 @@ sub check_rr { my @to = @_; my $rr = "$from/\@ALLOWED_RECIPIENTS"; my ($allowed,$to,$ar,$rd); - + if (-s $rr and open $rr,'<',$rr) { $restricted = $rr; @@ -2300,7 +2394,7 @@ sub check_rr { chomp; s/#.*//; s/\s//g; - + if (/^\@LOCAL_RDOMAINS/) { $ar = '(@'; foreach (@local_rdomains) { @@ -2311,26 +2405,29 @@ sub check_rr { $ar .= '|[^\@]+\@' . $rd; } $ar .= ')'; + } elsif (/^\@LOCAL_USERS/ and -s "$to/@") { + $allowed = 1; + last; } else { # allow wildcard *, but not regexps $ar = quotemeta $_; $ar =~ s/\\\*/[^@]*/g; } - + if ($to =~ /^$ar$/i) { $allowed = 1; last; } - + } - + unless ($allowed) { fuplog("ERROR: $from not allowed to fex to $to"); debuglog("$to not in $spooldir/$from/\@ALLOWED_RECIPIENTS"); http_die("You ($from) are not allowed to fex to $to"); } } - + close $rr; } } @@ -2340,24 +2437,24 @@ sub check_rr { sub expand { my @users = @_; my @ua; - + foreach my $u (my @loop = @users) { - if ($u =~ /^anonymous(_\d+)?$/) { + if ($u =~ /^anonymous(_\d+)?$/) { $u = "$u\@$hostname"; } - if ($u eq 'nettest') { + if ($u eq 'nettest') { if ($mdomain and -d "$u\@$mdomain") { $u .= "\@$mdomain" } elsif (-d "$u\@$hostname") { - $u .= "\@$hostname" + $u .= "\@$hostname" } } - if ($u =~ /@/) { push @ua,$u } - elsif ($mdomain) { push @ua,"$u\@$mdomain" } - elsif (-d "$u\@$hostname") { push @ua,"$u\@$hostname" } + if ($u =~ /@/) { push @ua,$u } + elsif ($mdomain) { push @ua,"$u\@$mdomain" } + elsif (-d "$u\@$hostname") { push @ua,"$u\@$hostname" } else { push @ua,$u } } - + return wantarray ? @ua : join(',',@ua); } @@ -2366,11 +2463,14 @@ sub expand { sub forward { my $file = shift; my ($nfile,$to,$AB); - my ($filename); + my ($filename,$keep); my (%to); http_die("no file data for $file") unless -f "$file/data"; + $keep = $::keep||$keep_default; + if (my $mt = mtime("$file/data")) { $keep += int((time-$mt)/$DS) } + if (@to) { # check recipients restriction @@ -2404,11 +2504,11 @@ sub forward { } } + @to = keys %to; + http_header('200 OK'); print html_header($head); - @to = keys %to; - foreach my $to (my @loop = @to) { $to =~ s/:\w+=.*//; # remove options from address $nfile = $file; @@ -2435,26 +2535,26 @@ sub forward { close $comment; } if ($autodelete =~ /^(DELAY|NO|\d+)$/i) { - symlink($autodelete,"$nfile/autodelete"); - } - symlink($keep||$keep_default, "$nfile/keep"); - copy("$file/id", "$nfile/id"); - copy("$file/ip", "$nfile/ip"); - copy("$file/speed", "$nfile/speed"); - copy("$file/replyto", "$nfile/replyto"); - $filename = copy("$file/filename", "$nfile/filename"); - link "$file/data", "$nfile/data" + symlink $autodelete,"$nfile/autodelete"; + } + symlink $keep, "$nfile/keep"; + copy("$file/id", "$nfile/id"); + copy("$file/ip", "$nfile/ip"); + copy("$file/speed", "$nfile/speed"); + copy("$file/replyto", "$nfile/replyto"); + $filename = copy("$file/filename", "$nfile/filename"); + link "$file/data", "$nfile/data" or die http_die("cannot create $nfile/data - $!"); unless ($dkey = readlink("$nfile/dkey") and -l "$dkeydir/$dkey") { $dkey = randstring(8); unlink "$dkeydir/$dkey"; - symlink "../$nfile","$dkeydir/$dkey" + symlink "../$nfile","$dkeydir/$dkey" or http_die("cannot symlink $dkeydir/$dkey"); unlink "$nfile/dkey"; - symlink $dkey,"$nfile/dkey" + symlink $dkey,"$nfile/dkey" or http_die("cannot create $nfile/dkey - $!"); } - + if ($nomail or $nomail{$to}) { if ($filename) { my $url = "$durl/$dkey/".normalize_filename($filename); @@ -2549,7 +2649,7 @@ sub calcsize { sub setparam { my ($v,$vv) = @_; my ($idf,$to); - + $v = uc(despace($v)); # if ($vv =~ /([<>])/) { @@ -2571,32 +2671,39 @@ sub setparam { 'Content-Length: 0', "" ); - &reexec; + } else { + nvt_print( + "HTTP/1.1 302 Found", + "Location: $ENV{PROTO}://$ENV{HTTP_HOST}/fup", + 'Content-Length: 0', + "" + ); } + &reexec; } elsif ($v eq 'LOCALE' and $vv =~ /^(\w+)$/) { $locale = $1; } elsif ($v eq 'REDIRECT' and $vv =~ /^([\w?=]+)$/) { $redirect = $1; - } elsif (($v eq 'KEY' or $v eq 'SKEY') and $vv =~ /^([\w:]+)$/) { + } elsif ($v eq 'SKEY' and $vv =~ /^([\w:]+)/) { $skey = $1; $restricted = $v; - } elsif ($v eq 'GKEY' and $vv =~ /^([\w:]+)$/) { + } elsif ($v eq 'GKEY' and $vv =~ /^([\w:]+)/) { $gkey = $1 unless $nomail; $restricted = $v; - } elsif ($v eq 'DKEY' and $vv =~ /^(\w+)$/) { + } elsif ($v eq 'DKEY' and $vv =~ /^(\w+)/) { $dkey = $1; - } elsif ($v eq 'AKEY' and $vv =~ /^(\w+)$/) { + } elsif ($v eq 'AKEY' and $vv =~ /^(\w+)/) { $akey = $1; - } elsif ($v eq 'FROM' or $v eq 'USER') { + } elsif ($v eq 'FROM' or $v eq 'USER') { $from = normalize_email($vv); $from = untaint(expand($from)); checkchars('from address',$from); # maybe FROM=SUBUSER ! # checkaddress($from) or http_die("FROM $from is no legal e-mail address"); - } elsif ($v eq 'REPLYTO') { + } elsif ($v eq 'REPLYTO') { $replyto = normalize_email($vv); checkchars('replyto address',$replyto); - checkaddress($replyto) or + checkaddress($replyto) or http_die("REPLYTO $replyto is no legal e-mail address"); } elsif ($v eq 'ADDTO') { $vv =~ s/\s.*//; @@ -2606,6 +2713,7 @@ sub setparam { } elsif ($v eq 'FEXYOURSELF') { $submit = $vv; @to = ($from); + $specific{'autodelete'} = $autodelete = 'no'; } elsif ($v eq 'TO') { # extract AUTODELETE and KEEP options if ($vv =~ s/[\s,]+AUTODELETE=(\w+)//i) { @@ -2621,9 +2729,15 @@ sub setparam { if ($from) { if ($to eq '.') { $to = $from; + unless ($specific{'autodelete'}) { + $specific{'autodelete'} = $autodelete = 'no'; + } } if ($to eq '//') { $to = $from; + unless ($specific{'autodelete'}) { + $specific{'autodelete'} = $autodelete = 'no'; + } $comment = '//'; } } @@ -2668,7 +2782,7 @@ sub setparam { } elsif ($v eq 'SEEK' and $vv =~ /^(\d+)$/) { $seek = $1; } elsif ($v eq 'FILESIZE' and $vv =~ /^(\d+)$/) { - $filesize = $1; # complete filesize! + $filesize = $1; # complete filesize! &check_space($filesize-$seek); } elsif ($v eq 'AUTODELETE' and $vv =~ /^(\w+)$/) { $specific{'autodelete'} = $autodelete = uc($1); @@ -2677,19 +2791,19 @@ sub setparam { $keep = $keep_max if $keep_max and $keep > $keep_max; $specific{'keep'} = $keep; } elsif ($v eq 'TIMEOUT' and $vv =~ /^(\d+)$/) { - $specific{'timeout'} = $timeout = $1; + $specific{'timeout'} = $timeout = $1; } } sub id_forgotten { my ($id,$to,$subuser,$gm,$skey,$gkey,$url,$fup); - + return if $nomail; - + $fup = $durl; $fup =~ s:/fop:/fup:; - + # full user if (open $from,'<',"$from/\@") { $id = getline($from); @@ -2706,7 +2820,7 @@ sub id_forgotten { ))); exit; } - + # sub user foreach my $skey (glob("$skeydir/*")) { if (-f $skey and open $skey,'<',$skey) { @@ -2729,7 +2843,7 @@ sub id_forgotten { exit; } } - + # group user foreach my $gkey (glob("$gkeydir/*")) { if (-f $gkey and open $gkey,'<',$gkey) { @@ -2783,6 +2897,11 @@ sub mail_forgotten { # lookup akey, skey and gkey (full and sub user and group) sub check_keys { + if (@to and "@to" ne '_') { + http_die("you cannot mix TO and SKEY URL parameters") if $skey; + http_die("you cannot mix TO and GKEY URL parameters") if $gkey; + } + # only one key can be valid $akey = $gkey = '' if $skey; $akey = $skey = '' if $gkey; @@ -2851,7 +2970,7 @@ sub check_keys { # sid is not set with web browser # akey with sid is set with schwuppdiwupp & co $idf = "$akeydir/$akey/@"; - + if (open $idf,'<',$idf and $id = getline($idf)) { close $idf; $from = readlink "$akeydir/$akey" @@ -2874,7 +2993,7 @@ sub check_space { my $req = shift; my ($df,$free,$uprq); local *P; - + if (open $df,"df -k $spooldir|") { while (<$df>) { if (/^.+?\s+\d+\s+\d+\s+(\d+)/ and $req/1024 > $1) { @@ -2903,10 +3022,10 @@ sub check_space { # global substitution as a function like in gawk -sub gsub { +sub gsub { local $_ = shift; - my ($p,$r) = @_; - s/$p/$r/g; + my ($p,$r) = @_; + s/$p/$r/g; return $_; } @@ -2914,7 +3033,7 @@ sub gsub { # standard log sub fuplog { my $msg = "@_"; - + $msg =~ s/\n/ /g; $msg =~ s/\s+$//; $msg = sprintf "%s [%s_%s] %s (%s) %s\n", @@ -2949,9 +3068,9 @@ sub sigexit { encode_Q($file||'-'), $msg, $RB?"(after $RB bytes)":""; - + writelog($log,$msg); - + if ($sig eq 'DIE') { shift; die "$msg\n"; @@ -2965,14 +3084,14 @@ sub present_locales { my $url = shift; my @locales = @::locales; # from fex.ph my ($locale,$lang); - - if ($url =~ /\?/) { + + if ($url =~ /\?/) { $url .= "&"; $url =~ s/locale=\w+&//g; - } else { + } else { $url .= "?"; } - + if (@locales) { map { $_ = "$FEXHOME/locale/$_" } @locales; } else { @@ -3001,7 +3120,7 @@ sub present_locales { sub check_camel { my ($logo,$camel); local $/; - + if (open $logo,"$docdir/logo.jpg") { $camel = md5_hex(<$logo>) eq 'ad8a95bba8dd1a61d70bd38611bc2059'; }