I have a situation where a file upload program that has been running without any problems for months now suddenly uploads completely empty files. When I turn on warnings (perl -w), I get a message like the following:
FATAL WARNING: read() on closed filehandle fh00001license.txt at CDownloadEditor.pm line 293.
Here is my main problem. I had this happen on a different server about a month ago. After a full day of scratching my head, delving back into the apache config, making slight modifications, looking at up2date logs, etc, I gave up for the day. When I tried using the program the next morning, it worked. So, I had made many different changes and rewritten the code many times with no change, it still did not work when I left, and it worked when I came back (no one else had access BTW). To further complicate things, my up2date logs showed that nothing changed overnight.
I thought of it as a weird fluke and shrugged it off, now it is happening on a different server. Both of these two servers are fairly small and the problem only affected one client. Now I'm concerned that this problem might occur on one of our critical servers that hosts many clients.
Another piece of important information is that while both the program that failed and then worked and this current program are programs to upload files, they are completely different versions of code that work differently. They don't even share any custom libraries in common.
The subroutine I call is as follows:
sub uploadFile
{
my $self = shift;
my %FORM = %{$self->{FORM}};
my %sysvars = %{$self->{GVARS}};
my ($variableName, $variableID);
if(@_)
{
$variableName = shift;
$variableID = shift;
}
return if($FORM{$variableName} eq '');
my $extension = $1 if($FORM{$variableName} =~ /\.([^\.]+)$/);
my $fileHandle = $FORM{$variableName};
my $filename = $variableID . $variableName . '.' . lc($extension);
my $path = "$sysvars{MODFILEPATH}/$sysvars{FILE}";
if($filename =~ /([^\/\\]+)$/)
{
$filename = $1;
}
else
{
return "error";
}
if (!(-d "$path/"))
{
mkdir("$path/", 0777);
}
if(-f "$path/$filename")
{
unlink("$path/$filename");
}
if(!(open(IMAGEFILE, ">$path/$filename")))
{
if($FORM{'SCRIPTERROR-FILEUPLOAD'} eq '')
{
$self->{FORM}->{'SCRIPTERROR-FILEUPLOAD'} = 1;
$self->setErrorMessage("File did not upload correctly. The system administrator has been notified of this issue.<br>Please try editing the record later to upload the file.");
$self->sendTechnicalInformation("File permissions issue.");
}
return;
}
my $bytesRead;
my $buffer;
while(my $bytes = read($fileHandle, $buffer, 2096))
{
$bytesRead += $bytes;
binmode IMAGEFILE;
print IMAGEFILE $buffer;
}
close($fileHandle);
close(IMAGEFILE);
chmod (0777, "$path/$filename");
$self->{FORM}->{$variableName} = "$sysvars{MODFILEURL}/$sysvars{FILE}/$filename";
$self->doSQLUpdate('', "ID='$variableID'");
$self->setSuccessMessage("Upload Successful: $bytesRead bytes read.");
}
No other code before this call attempts to open or close any file handles.
This subroutine is called by a line such as:
$self->uploadFile('file', $id) if($FORM{'file'});
Note that the %FORM hash contains variables passed in from the CGI module. The code that handles that is as follows:
my $query = new CGI;
my $sql = do_sql->new;
$sql->connect;
foreach my $key (sort {$a <=> $b} $query->param())
{
my $value = $query->param($key);
$self->{FORM}->{$key} = $value;
}
If you have any advice to offer, please share it. This has baffled me long enough. Thank you.