Link to home
Start Free TrialLog in
Avatar of joec_
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
#!/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); 
}

Open in new window

Avatar of FishMonger
FishMonger
Flag of United States of America image

Are you sure the error is coming from line 11?  I'd suspect line 29.

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.
ASKER CERTIFIED SOLUTION
Avatar of FishMonger
FishMonger
Flag of United States of America image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
I just noticed a problem in the error() subroutine.

change:
$q->h1($_),

to:
$q->h1($_[0]),

or:
$q->h1(shift),
Avatar of joec_
joec_

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.
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)
I'm not 100% sure, but yes I think I do know your "secret identity".  Does it start with the letter K?