joec_
asked on
Bad file descriptor with file download script
Hi,
I have got a file download script from the internet which is attached below. The script gives a bad file descriptor error message on line 11 when trying to assign the file parameter to the $file variable. What exactly does a bad file descriptor mean? All it should be doing is downloading a csv file.
Thanks
Joe
I have got a file download script from the internet which is attached below. The script gives a bad file descriptor error message on line 11 when trying to assign the file parameter to the $file variable. What exactly does a bad file descriptor mean? All it should be doing is downloading a csv file.
Thanks
Joe
#!/usr/bin/perl -T
use strict;
use warnings;
use CGI;
# Uncomment the next line only for debugging the script.
use CGI::Carp qw/fatalsToBrowser/;
# the path to where the downloadable files are.
# prefereably this should be above the web root folder.
my $path_to_files = '/apps/actweb/cgi-bin';
my $q = CGI->new;
my $file = $q->param('file') or error('Error: No file selected.');
# here we untaint the filename and make sure there are no characters like /
# in the name that could be used to download files from any folder on the website.
# personally I don't even recommend you pass filenames to the script, but that
# gets too complicated for a simple example of a download script.
if ($file =~ /^(\w+[\w.-]+\.\w+)$/) {
$file = $1;
}
else {
error('Error: Unexpected characters in filename.');
}
if ($file) {
download($file) or error('Error: an unknown error has occured. Try again.');
}
sub download {
# Uncomment the next line only for debugging the script
#open(DLFILE, '<', "$path_to_files/$file") or die "Can't open file '$path_to_files/$file' : $!";
# Comment the next line if you uncomment the above line
open(DLFILE, '<', "$path_to_files/$file") or return(0);
# this prints the download headers with the file size included
# so you get a progress bar in the dialog box that displays during file downlaods.
print $q->header(-type => 'application/x-download',
-attachment => $file,
'Content-length' => -s "$path_to_files/$file",
);
binmode DLFILE;
print while <DLFILE>;
close (DLFILE);
return(1);
}
# This is a very generic error page. You should make a better one.
sub error {
print $q->header(),
$q->start_html(-title=>'Error'),
$q->h1($_),
$q->end_html;
exit(0);
}
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
I just noticed a problem in the error() subroutine.
change:
$q->h1($_),
to:
$q->h1($_[0]),
or:
$q->h1(shift),
change:
$q->h1($_),
to:
$q->h1($_[0]),
or:
$q->h1(shift),
ASKER
thanks for the suggestions and new code - ive been working on a different project last couple of days but will try your suggestions on Monday.
Joe.
Joe.
The use of $_ where $_[0] should have been used in the error() function is a good catch. The other possible problem though is not a problem:
'Content-length' => -s "$path_to_files/$file",
The CGI module will correctly interpret the above line although changing it as suggested also works:
-Content_length => -s "$path_to_files/$file",
Hi Fish (now you (should) know my secret identity. PS: I also wrote the code the OP posted)
'Content-length' => -s "$path_to_files/$file",
The CGI module will correctly interpret the above line although changing it as suggested also works:
-Content_length => -s "$path_to_files/$file",
Hi Fish (now you (should) know my secret identity. PS: I also wrote the code the OP posted)
I'm not 100% sure, but yes I think I do know your "secret identity". Does it start with the letter K?
Have you checked $file to verify that it holds the value you expect?
Don't put the csv files in the cgi-bin directory...instead, put them in something like
my $path_to_files = '/apps/actweb/downloads';
It would be better to either hard code or build a hash of the filenames that are available to download and verify that the requested file is a key in the hash.