X-Git-Url: http://git.treefish.org/fex.git/blobdiff_plain/7fa382617fbaccc0ce522b2b3adbbee9db5ad227..20150729:/lib/fex.pp diff --git a/lib/fex.pp b/lib/fex.pp index bb72a4e..bd7ed98 100644 --- a/lib/fex.pp +++ b/lib/fex.pp @@ -13,7 +13,7 @@ use Symbol qw'gensym'; # set and untaint ENV if not in CLI (fexsrv provides clean ENV) unless (-t) { foreach my $v (keys %ENV) { - ($ENV{$v}) = ($ENV{$v} =~ /(.*)/s); + ($ENV{$v}) = ($ENV{$v} =~ /(.*)/s) if defined $ENV{$v}; } $ENV{PATH} = '/usr/local/bin:/bin:/usr/bin'; $ENV{IFS} = " \t\n"; @@ -43,11 +43,14 @@ $logdir = $spooldir; $autodelete = 'YES'; $overwrite = 'YES'; $limited_download = 'YES'; # multiple downloads only from same client +$fex_yourself = 'YES'; # allow SENDER = RECIPIENT $keep = 5; # days $recipient_quota = 0; # MB $sender_quota = 0; # MB $timeout = 30; # seconds $bs = 2**16; # I/O blocksize +$DS = 60*60*24; # seconds in a day +$MB = 1024*1024; # binary Mega $use_cookies = 1; $sendmail = '/usr/lib/sendmail'; $sendmail = '/usr/sbin/sendmail' unless -x $sendmail; @@ -72,9 +75,6 @@ if ($FHS) { # allowed download managers (HTTP User-Agent) $adlm = '^(Axel|fex)'; -# allowed multi download recipients -$amdl = '^(anonymous|_fexmail_)'; - # local config require "$FEXLIB/fex.ph" or die "$0: cannot load $FEXLIB/fex.ph - $!"; @@ -82,10 +82,22 @@ $fop_auth = 0 if $fop_auth =~ /no/i; $mail_authid = 0 if $mail_authid =~ /no/i; $force_https = 0 if $force_https =~ /no/i; $debug = 0 if $debug =~ /no/i; - + +@logdir = ($logdir) unless @logdir; +$logdir = $logdir[0]; + +# allowed multi download recipients: from any ip, any times +if (@mailing_lists) { + $amdl = '^('.join('|',map { quotewild($_) } @mailing_lists).')$'; +} else { + $amdl = '^-$'; +} + # check for name based virtual host $vhost = vhost($ENV{'HTTP_HOST'}); +$RB = 0; # read POST bytes + push @doc_dirs,$docdir; foreach my $ld (glob "$FEXHOME/locale/*/htdocs") { push @doc_dirs,$ld; @@ -94,7 +106,7 @@ foreach my $ld (glob "$FEXHOME/locale/*/htdocs") { $nomail = ($mailmode =~ /^MANUAL|nomail$/i); if (not $nomail and not -x $sendmail) { - http_die("found no sendmail\n"); + http_die("found no sendmail"); } http_die("cannot determine the server hostname") unless $hostname; @@ -143,16 +155,41 @@ if (@locales) { $default_locale ||= 'english'; +# $durl is first default fop download URL +# @durl is optional mandatory fop download URL list (from fex.ph) unless ($durl) { my $host = ''; - my $port = 0; - - ($host,$port) = split(':',$ENV{HTTP_HOST}||''); - $host = $hostname; + my $port = 80; + my $xinetd = '/etc/xinetd.d/fex'; + + if (@durl) { + $durl = $durl[0]; + } elsif ($ENV{HTTP_HOST} and $ENV{PROTO}) { + + ($host,$port) = split(':',$ENV{HTTP_HOST}||''); + $host = $hostname; + + unless ($port) { + $port = 80; + if (open $xinetd,$xinetd) { + while (<$xinetd>) { + if (/^\s*port\s*=\s*(\d+)/) { + $port = $1; + last; + } + } + close $xinetd; + } + } - unless ($port) { - $port = 80; - if (open my $xinetd,'<',"/etc/xinetd.d/fex") { + # use same protocal as uploader for download + if ($ENV{PROTO} eq 'https' and $port == 443 or $port == 80) { + $durl = "$ENV{PROTO}://$host/fop"; + } else { + $durl = "$ENV{PROTO}://$host:$port/fop"; + } + } else { + if (open $xinetd,$xinetd) { while (<$xinetd>) { if (/^\s*port\s*=\s*(\d+)/) { $port = $1; @@ -161,16 +198,13 @@ unless ($durl) { } close $xinetd; } - } - - # use same protocal as uploader for download - if ($ENV{PROTO} eq 'https' and $port == 443 or $port == 80) { - $durl = "$ENV{PROTO}://$host/fop"; - } else { - $durl = "$ENV{PROTO}://$host:$port/fop"; + if ($port == 80) { + $durl = "http://$hostname/fop"; + } else { + $durl = "http://$hostname:$port/fop"; + } } } - @durl = ($durl) unless @durl; @@ -344,7 +378,10 @@ sub html_error { sub http_die { # not in CGI mode - die "$0: @_\n" unless $ENV{GATEWAY_INTERFACE}; + unless ($ENV{GATEWAY_INTERFACE}) { + warn "$0: @_\n"; # must not die, because of fex_cleanup! + return; + } debuglog(@_); @@ -584,6 +621,23 @@ sub normalize_email { } +sub normalize_user { + my $user = shift; + + $user = lc(urldecode(despace($user))); + $user .= '@'.$mdomain if $mdomain and $user !~ /@/; + checkaddress($user) or http_die("$user is not a valid e-mail address"); + return untaint($user); +} + + +sub urldecode { + local $_ = shift; + s/%([a-f0-9]{2})/chr(hex($1))/gie; + return $_; +} + + sub untaint { local $_ = shift; /(.*)/s; @@ -621,8 +675,10 @@ sub checkaddress { $a =~ s/:\w+=.*//; # remove options from address return $a if $a eq 'anonymous'; - - $re = '^[.@]|@.*@|local(host|domain)$|["\'\`\|\s()<>/;,]'; + + $a .= '@'.$mdomain if $mdomain and $a !~ /@/; + + $re = '^[.@-]|@.*@|local(host|domain)$|["\'\`\|\s()<>/;,]'; if ($a =~ /$re/i) { debuglog("$a has illegal syntax ($re)"); return ''; @@ -663,8 +719,7 @@ sub checkforbidden { return $a if -d "$spooldir/$a"; # ok, if user already exists if (@forbidden_recipients) { foreach (@forbidden_recipients) { - $fr = quotemeta; - $fr =~ s/\\\*/.*/g; # allow wildcard * + $fr = quotewild($_); # skip public recipients if (@public_recipients) { foreach $pr (@public_recipients) { @@ -696,13 +751,13 @@ sub mkdirp { return if -d $dir; $dir =~ s:/+$::; - http_die("cannot mkdir /\n") unless $dir; + http_die("cannot mkdir /") unless $dir; $pdir = $dir; if ($pdir =~ s:/[^/]+$::) { mkdirp($pdir) unless -d $pdir; } unless (-d $dir) { - mkdir $dir,0770 or http_die("mkdir $dir - $!\n"); + mkdir $dir,0770 or http_die("mkdir $dir - $!"); } } @@ -789,20 +844,16 @@ sub urlencode { # file and document log sub fdlog { my ($log,$file,$s,$size) = @_; - my $ra; - - if (open $log,'>>',$log) { - flock $log,LOCK_EX; - seek $log,0,SEEK_END; - $ra = $ENV{REMOTE_ADDR}||'-'; - $ra .= '/'.$ENV{HTTP_X_FORWARDED_FOR} if $ENV{HTTP_X_FORWARDED_FOR}; - $ra =~ s/\s//g; - $file =~ s:/data$::; - printf {$log} - "%s [%s_%s] %s %s %s/%s\n", - isodate(time),$$,$ENV{REQUESTCOUNT},$ra,encode_Q($file),$s,$size; - close $log; - } + my $ra = $ENV{REMOTE_ADDR}||'-'; + my $msg; + + $ra .= '/'.$ENV{HTTP_X_FORWARDED_FOR} if $ENV{HTTP_X_FORWARDED_FOR}; + $ra =~ s/\s//g; + $file =~ s:/data$::; + $msg = sprintf "%s [%s_%s] %s %s %s/%s\n", + isodate(time),$$,$ENV{REQUESTCOUNT},$ra,encode_Q($file),$s,$size; + + writelog($log,$msg); } @@ -813,11 +864,12 @@ sub debuglog { return unless $debug and @_; unless ($debuglog and fileno $debuglog) { - mkdir "$logdir/.debug",0770 unless -d "$logdir/.debug"; + my $ddir = "$spooldir/.debug"; + mkdir $ddir,0770 unless -d $ddir; $prg =~ s:.*/::; $prg = untaint($prg); - $debuglog = sprintf("%s/.debug/%s_%s_%s.%s", - $logdir,time,$$,$ENV{REQUESTCOUNT}||0,$prg); + $debuglog = sprintf("%s/%s_%s_%s.%s", + $ddir,time,$$,$ENV{REQUESTCOUNT}||0,$prg); $debuglog =~ s/\s/_/g; # open $debuglog,'>>:encoding(UTF-8)',$debuglog or return; open $debuglog,'>>',$debuglog or return; @@ -836,22 +888,32 @@ sub debuglog { # extra debug log sub errorlog { my $prg = $0; - my $log = "$logdir/error.log"; my $msg = "@_"; + my $ra = $ENV{REMOTE_ADDR}||'-'; + $ra .= '/'.$ENV{HTTP_X_FORWARDED_FOR} if $ENV{HTTP_X_FORWARDED_FOR}; + $ra =~ s/\s//g; $prg =~ s:.*/::; $msg =~ s/[\r\n]+$//; $msg =~ s/[\r\n]+/ /; $msg =~ s/\s*
.*//;
+ $msg = sprintf "%s %s %s %s\n",isodate(time),$prg,$ra,$msg;
- if (open $log,'>>',$log) {
- flock $log,LOCK_EX;
- seek $log,0,SEEK_END;
- $ra = $ENV{REMOTE_ADDR}||'-';
- $ra .= '/'.$ENV{HTTP_X_FORWARDED_FOR} if $ENV{HTTP_X_FORWARDED_FOR};
- $ra =~ s/\s//g;
- printf {$log} "%s %s %s %s\n",isodate(time),$prg,$ra,$msg;
- close $log;
+ writelog('error.log',$msg);
+}
+
+
+sub writelog {
+ my $log = shift;
+ my $msg = shift;
+
+ foreach my $logdir (@logdir) {
+ if (open $log,'>>',"$logdir/$log") {
+ flock $log,LOCK_EX;
+ seek $log,0,SEEK_END;
+ print {$log} $msg;
+ close $log;
+ }
}
}
@@ -931,7 +993,7 @@ sub check_sender_quota {
my $sender = shift;
my $squota = $sender_quota||0;
my $du = 0;
- my ($file,$size,%file,$data);
+ my ($file,$size,%file,$data,$upload);
local $_;
if (open $qf,'<',"$sender/\@QUOTA") {
@@ -944,6 +1006,7 @@ sub check_sender_quota {
foreach $file (glob "*/$sender/*") {
$data = "$file/data";
+ $upload = "$file/upload";
if (not -l $data and $size = -s $data) {
# count hard links only once (= same inode)
my $i = (stat($data))[1]||0;
@@ -951,8 +1014,13 @@ sub check_sender_quota {
$du += $size;
$file{$i} = $i;
}
- } elsif (-f "$file/upload" and $size = readlink "$file/size") {
- $du += $size;
+ } elsif (-f $upload) {
+ # count hard links only once (= same inode)
+ my $i = (stat($upload))[1]||0;
+ unless ($file{$i}) {
+ $size = readlink "$file/size" and $du += $size;
+ $file{$i} = $i;
+ }
}
}
@@ -1094,6 +1162,89 @@ sub slurp {
}
+# read one line from STDIN (net socket) and assign it to $_
+# return number of read bytes
+# also set global variable $RB (read bytes)
+sub nvt_read {
+ my $len = 0;
+
+ if (defined ($_ =