X-Git-Url: http://git.alex.org.uk diff --git a/download.pl b/download.pl index 859d5d8..feadfa6 100755 --- a/download.pl +++ b/download.pl @@ -1,5 +1,6 @@ #!/usr/bin/perl +use File::stat; use strict; use warnings; @@ -11,6 +12,7 @@ use File::stat; use Digest::SHA qw(sha256_hex sha1); use MIME::Base64; use File::Spec; +use File::Spec::Functions qw(rel2abs); use CGI; use HTML::Entities; use IO::Handle; @@ -20,18 +22,21 @@ my $log; my $transaction="unknown"; my $logfile = "/var/log/download.log"; -my $datadir = "/var/www/server.example.com/public_html/download/"; +my $datadir = dirname(rel2abs($0))."/"; my $secretfile="/etc/apache2/download.secret"; my $secret; my $sentheader = 0; my $maxdrift = 60; +my $remoteip; +my $t0 = [gettimeofday]; +my $filesize; sub lprintf { if (defined($log)) { my $now = strftime "%a, %d %b %Y %T %z", localtime; - print $log "$now: [$$][$transaction]: "; + printf $log "$now: [$$:%s][$transaction]: ", defined($remoteip)?$remoteip:"unknown"; printf $log @_; } } @@ -52,7 +57,8 @@ sub openlog sub qdie { my $err = shift @_; - lprintf "ERROR: $err\n"; + my $elapsed = tv_interval ( $t0, [gettimeofday]); + lprintf "ERROR: $err after %.3f secs\n", $elapsed; if (!$sentheader) { my $error = encode_entities( $err ); @@ -81,12 +87,13 @@ sub sendfile { $sentheader = 1; print CGI::header( -type => 'application/octet-stream', + -Content_length=> $filesize, -attachment => $name, ); binmode STDOUT, ':raw'; - unless (copy $fh => \*STDOUT, 8192) + unless (copy $fh => \*STDOUT, 65536) { qdie "Cannot write to STDOUT"; } @@ -102,6 +109,14 @@ sub gethash return sha256_hex(shift @_); } +sub getfile +{ + my $fn = $datadir.(shift @_); + $fn = File::Spec->rel2abs( readlink($fn) ) if (-l $fn); + qdie ("File not found") unless ( -f $fn); + return $fn; +} + sub decodeparams { my $query = CGI::url(-absolute=>1); @@ -111,22 +126,49 @@ sub decodeparams my $clientfile = CGI::url_param('file'); $clientfile = "default" unless(defined($clientfile)); qdie ("Bad parameters") unless (defined($clienttime) && defined($clientid) && defined($clienthash) && ($clienttime=~/^[0-9]+$/)); - my $drift = time()-$clienttime; - qdie ("Client time has drifted - we have ".time()) if (($drift < -$maxdrift) || ($drift > $maxdrift)); + my $now = time(); + my $drift = $now-$clienttime; + qdie ("Client time has drifted - $now - $clienttime = $drift") if (($drift < -$maxdrift) || ($drift > $maxdrift)); qdie ("Bad ID") unless ($clientid=~/^[-+._\@a-zA-Z0-9]+$/); qdie ("Bad filename") unless ($clientfile=~/^[-+._a-zA-Z0-9]+$/); qdie ("Bad filename") if ($clientfile=~/^\./); my $hash = gethash($clienttime.":".$clientid.":".$clientfile.":".$secret); qdie ("Bad hash") unless ($hash eq $clienthash); - my $fn = $datadir.$clientfile; - $fn = File::Spec->rel2abs( readlink($fn) ) if (-l $fn); - qdie ("File not found") unless ( -f $fn); + my $fn = getfile($clientfile); $clientfile = basename ($fn); $transaction=$hash." ".$clientfile." ".$clientid; return $fn; } +sub doinfo +{ + my $clientfile = shift @_; + my $fn = getfile($clientfile); + $clientfile = basename ($fn); + my $size = "unknown"; + my $sb = stat($fn); + $size = $sb->size if (defined($sb) && defined($sb->size)); + my $md5sum = "unknown"; + my $md5fn = $fn.".md5sum"; + if ( -r $md5fn ) + { + my $md5; + open $md5, "<", $md5fn || qdie ("Can't read md5sum"); + while (<$md5>) + { + chomp; + $md5sum = $1 if (/^([a-f0-9]+)\b/); + } + close $md5; + } + $sentheader = 1; + print CGI::header( + -type => 'text/plain' ); + + print "$clientfile $size $md5sum\n"; +} + open (my $sfh, "<", $secretfile) || qdie("Can't open secret file $secretfile: $!"); chomp($secret=join("",<$sfh>)); close ($sfh); @@ -140,11 +182,18 @@ if (!defined($ENV{DOCUMENT_ROOT}) && !defined($ENV{SERVER_NAME})) } else { + my $info = CGI::url_param('info'); + if (defined($info)) + { + doinfo($info); + exit 0; + } + $remoteip = CGI::remote_addr(); + openlog; my $file = decodeparams; my $sb = stat($file); - my $size = $sb->size; - my $t0 = [gettimeofday]; + $filesize = $sb->size; lprintf("STARTING\n"); $SIG{INT} = \&caughtsignal; $SIG{QUIT} = \&caughtsignal; @@ -154,7 +203,8 @@ else $SIG{TERM} = \&caughtsignal; sendfile($file); my $elapsed = tv_interval ( $t0, [gettimeofday]); - lprintf("SUCCESS %d bytes %.3f MB/s\n", $size, $size/(1000000.0*(($elapsed<0.001)?0.001:$elapsed))); + my $rate = $filesize/(1000000.0*(($elapsed<0.001)?0.001:$elapsed)); + lprintf("SUCCESS %d bytes %.3f MB/s %.3f secs\n", $filesize, $rate, $elapsed); closelog; exit(0);