Andre_br has asked for the wisdom of the Perl Monks concerning the following question:

Hello Folks I have this code, wich always worked just fine:
use CGI; my $q = new CGI; my $fh = $q->upload( "file" ); my $filesize = -s $fh; # die $filesize; # returns undef!
But today, after upgrading Perl, it suddenly stopped working. I'm going mad as I've spent the whole day with this, and there's no way it comes back to work. (!)

I even have set up the entire development environment in another machine (with perl 5.8.9 too) and the same occurs!

Both machines are win32. One of them is win2k and the other one is vista.

Besides the -s not working, nothing else on the file upload works too. I mean, I can't get the file as well, not only the size.

Any hints? I'm going crazy here. Please help.

Thanks

André

PS: I'm running Apache 1.3.4 on one of them, and now Apache 2.2 on the other one. So I think Apache is not guilt.

This is perl, v5.8.9 built for MSWin32-x86-multi-thread (with 12 registered patches, see perl -V for more detail) Copyright 1987-2008, Larry Wall Binary build 827 [291969] provided by ActiveState http://www.ActiveSta +te.com Built Jan 26 2010 21:15:51

Replies are listed 'Best First'.
Re: File upload became deaf after upgrading from 5.8.7 to 5.8.9
by Khen1950fx (Canon) on Nov 05, 2010 at 08:43 UTC
    I would use a CGI wrapper for security reasons instead of CGI to upload a file. I used CGI::Upload, and to make the numbers more readable, I used Number::Bytes::Human.
    #!/usr/bin/perl use strict; use warnings; use CGI::Upload; use Number::Bytes::Human qw(format_bytes); my $file = shift @ARGV; my $upload = CGI::Upload->new; $upload->file_name( "$file" ); my $h = Number::Bytes::Human->new(); my $h_size = format_bytes(-s $file); print $h_size, "\n";
      Hey Khen, thanks for the reply!

      Tell me, wich security reasons? You mean it does some security checks? (I didn't find it in the docs)

      Also, folks, I think the reason I interpreted from the issue was the opposite: the my $q = new CGI; inside the sub probably emptied the POSTed data that was captured by the my $q = new CGI; in the beginning of the main script.

      Curious thing is that it only bothers the upload() method, and not the param(). That shall make a lot of people go crazy.

      Thanks

      André

        Which security reasons?

        You'll find the reasons in the PRAGMAS subsection. Look for -private_tempfiles. Here, quoting the documentation:

        -private_tempfiles

        "CGI.pm can process uploaded file. Ordinarily it spools the uploaded file to a temporary directory, then deletes the file when done. However, this opens the risk of eavesdropping as described in the file upload section. Another CGI script author could peek at this data during the upload, even if it is confidential information. On Unix systems, the -private_tempfiles pragma will cause the temporary file to be unlinked as soon as it is opened and before any data is written into it, reducing, but not eliminating the risk of eavesdropping (there is still a potential race condition). To make life harder for the attacker, the program chooses tempfile names by calculating a 32 bit checksum of the incoming HTTP headers".

        "To ensure that the temporary file cannot be read by other CGI scripts, use suEXEC or a CGI wrapper program to run your script. The temporary file is created with mode 0600 (neither world nor group readable)".

Re: File upload became deaf after upgrading from 5.8.7 to 5.8.9
by bart (Canon) on Nov 04, 2010 at 21:27 UTC
    Can you tell us something more about the versions of CGI.pm on both servers? I've heard bad things about the latest upgrades of that module, though nothing related to file uploads, but I wouldn't rule it out.
      along a similar vein of thinking...have you turned on some debugging output for CGI.pm and or checked your webserver logs? run the CGI from command line?..i think you can even provide the file upload parameter on command line. is the file upload form parameter being passed into the CGI for sure? sniff the network with wireshark? check webserver config is not pointing to older (incompatible) .dll/.exe for perl. also check the upgraded perl doesn't point to older modules somehow/somewhere.
      i'm sure you know all these things to check..probably just stressed out too much. just remembered another useful thing: run Filemon utility and check the log, possibility of a file permission issue.
      good luck.
      the hardest line to type correctly is: stty erase ^H
      Hey bart, hey aquarium

      Thanks for the replies!

      I've just found the cure.

      Before that part of the code, I had a sub that initiated the CGI object within itself. For example:

      #!/usr/bin/perl -wT use CGI; my $q = new CGI; #... my ( $user_id, $name ) = identify ( $auth_token ); # ... my $fh = $q->upload( "file" ); my $filesize = -s $fh; die $filesize; # undef at debugging! # ... file read routines, that resulted blank after the upgrade
      Then, on my personal lib, mylib1.pm, I had this subroutine:
      sub identify { my $token = shift; # my $q = new CGI; # it started working when I removed this line! # identification routines # some calls to CGI.pm methods, where I used $q }
      After hours of mystery, I decided to remove this inner initialization. And it worked! I'm now passing $q as a parameter to the sub.

      sub identify { my $token = shift; my $q = shift; # and including this element on the sub call, of cou +rse my $q = new CGI; # it started working when I removed this line! # identification routines # some calls to CGI.pm methods, where I used $q }
      Tell me, guys, what's the explanation? Is this a bug on CGI.pm garbage collection or is it the case that I was doing ugly things.

      Funny is that it worked with 5.8.7.

      Thanks

      Andre

        Uh, creating a CGI object effectively reads the data from the input. After that, it is gone, when the data is POSTed (as is necessary for file upload) — you may repeat reading parameters from GET.

        It's not a matter of garbage collecting, it's a matter of a physical action performed when creating the object. An action that cannot stand being repeated.