6 use POSIX qw(strftime);
8 use File::Copy qw( copy );
10 use Digest::SHA qw(sha256_hex sha1);
18 my $transaction="unknown";
20 my $logfile = "/var/log/download.log";
21 my $datadir = "/var/www/server.example.com/public_html/download/";
22 my $secretfile="/etc/apache2/download.secret";
31 my $now = strftime "%a, %d %b %Y %T %z", localtime;
32 print $log "$now: [$$][$transaction]: ";
39 close $log if defined($log);
46 open ($log, '>>', $logfile) || die ("Cannot open logfile $logfile: $!");
53 lprintf "ERROR: $err\n";
56 my $error = encode_entities( $err );
57 print "Status: 404 Not Found\n";
58 print "Content-type: text/html\n\n";
59 print "<html><head><title>404 Not Found</title></head><body><h1>Not Found</h1><p>$error</p><hr><address>Download Server</address>";
60 print "</body></html>\n";
69 qdie ("Received SIG$signame");
74 my $name = basename($file);
76 open my $fh, '<:raw', $file
77 or qdie "Cannot open '$file': $!";
81 -type => 'application/octet-stream',
85 binmode STDOUT, ':raw';
87 unless (copy $fh => \*STDOUT, 8192)
89 qdie "Cannot write to STDOUT";
93 or qdie "Cannot close '$file': $!";
100 return sha256_hex(shift @_);
105 my $query = CGI::url(-absolute=>1);
106 my $clienttime = CGI::url_param('time');
107 my $clientid = CGI::url_param('id');
108 my $clienthash = CGI::url_param('hash');
109 my $clientfile = CGI::url_param('file');
110 $clientfile = "default" unless(defined($clientfile));
111 qdie ("Bad parameters") unless (defined($clienttime) && defined($clientid) && defined($clienthash) && ($clienttime=~/^[0-9]+$/));
112 my $drift = time()-$clienttime;
113 qdie ("Client time has drifted - we have ".time()) if (($drift < -$maxdrift) || ($drift > $maxdrift));
114 qdie ("Bad ID") unless ($clientid=~/^[-+._\@a-zA-Z0-9]+$/);
115 qdie ("Bad filename") unless ($clientfile=~/^[-+._a-zA-Z0-9]+$/);
116 qdie ("Bad filename") if ($clientfile=~/^\./);
118 my $hash = gethash($clienttime.":".$clientid.":".$clientfile.":".$secret);
119 qdie ("Bad hash") unless ($hash eq $clienthash);
120 my $fn = $datadir.$clientfile;
121 $fn = File::Spec->rel2abs( readlink($fn) ) if (-l $fn);
122 qdie ("File not found") unless ( -f $fn);
123 $clientfile = basename ($fn);
124 $transaction=$hash." ".$clientfile." ".$clientid;
128 open (my $sfh, "<", $secretfile) || qdie("Can't open secret file $secretfile: $!");
129 chomp($secret=join("",<$sfh>));
132 if (!defined($ENV{DOCUMENT_ROOT}) && !defined($ENV{SERVER_NAME}))
134 die ("Bad parameters") unless ($#ARGV == 1);
136 printf "id=%s&file=%s&time=%s&hash=%s",uri_escape($ARGV[0]),uri_escape($ARGV[1]),$t,gethash($t.":".$ARGV[0].":".$ARGV[1].":".$secret)."\n";
142 my $file = decodeparams;
143 lprintf("STARTING\n");
144 $SIG{INT} = \&caughtsignal;
145 $SIG{QUIT} = \&caughtsignal;
146 $SIG{PIPE} = \&caughtsignal;
147 $SIG{HUP} = \&caughtsignal;
148 $SIG{KILL} = \&caughtsignal;
149 $SIG{TERM} = \&caughtsignal;
151 lprintf("SUCCESS\n");