in reply to Re: CGI::Upload problem with MSWin32 browser
in thread CGI::Upload problem with MSWin32 browser

I include the code of uploadfile.pl #! /usr/bin/perl

use CGI qw/:standard/;
use CGI::Carp 'fatalsToBrowser';
use CGI::Upload;
my $q = CGI->new;
my $upload = CGI::Upload->new($q);
print header(),start_html('Upload d\'un fichier'),
    h1('Upload d\'un fichier');

print $q->dump;

my $filename = $upload->file_name( 'fichier' );
my $type = $upload->file_type( 'fichier' );
my $file_handle = $upload->file_handle( 'fichier' );
 

print "Fichier: $filename",p();
print "Type: $type",p();
print hr();
my $name = $q->param('name');
print $name,p;
while (<$file_handle>) {
    print $_;
}

print hr();

Thank's

Carl Provencher

Université Laval

  • Comment on Re: Re: CGI::Upload problem with MSWin32 browser

Replies are listed 'Best First'.
Bug in CGI::Upload, not with your code
by Ovid (Cardinal) on May 06, 2002 at 20:14 UTC

    Your code is fine. The module has a bug in it. Here's the relevant section of your code:

    my $filename = $upload->file_name( 'fichier' ); my $type = $upload->file_type( 'fichier' ); my $file_handle = $upload->file_handle( 'fichier' );

    In the above three lines, you are calling methods that all have the following general form:

    sub file_XXXX { my $self = shift; my ($param) = @_; my $cgi = $self->{'_CGI'}; return undef unless defined $cgi->param($param); $self->{'_PARAMS'}->{$param} = $self->_handle_file( $cgi, $param) unless exists $self->{'_PARAMS'}->{$param}; return $self->{'_PARAMS'}->{$param}->{'file_XXXX'}; }

    In the above example, replace the XXXX with whatever the second part of the method name is and you have the correct method. The author of the module you are using is calling a private method, &CGI::Upload::_handle_file, which creates a hash reference, $object, and returns it and it gets assigned to $param. The relevant code is this:

    my $object = { 'file_handle' => $fh, 'file_name' => $file[0] . $file[2], 'file_type' => substr(lc $file[2], 1), 'mime_type' => $magic->checktype_filehandle($fh) }; $fh->seek(0, 0); $fh->binmode if $CGI::needs_binmode; return $object;

    Now, that looks all fine and dandy. The author is creating a hash reference and later accessing one of the members of the hash. However, a little while earlier in the same method, we see the following little tidbit:

    sub _handle_file { # ... more code fileparse_set_fstype( do { my $browser = HTTP::BrowserDetect->new; return 'MSWin32' if $browser->windows; return 'MacOS' if $browser->mac; $^O; } ); # ... more code }

    The problem lies in that do block. If $browser->windows evaluates as true, then 'MSWin32' will be returned from this subroutine, rather than returned as the argument to &fileparse_set_fstype, which is what the author was intending. What this means is that 'MSWin32' gets returned instead of a hash reference. I'll shoot an email to the author. In the meantime, try hacking the module with the following (untested) code:

    my $browser = HTTP::BrowserDetect->new; fileparse_set_fstype( $browser->windows ? 'MSWin32' : $browser->mac ? 'MacOS' : $^0 );

    And here's a little 'proof of concept' program demonstrating the bug:

    #!/usr/bin/perl -w use strict; sub test { my $arg = shift; my $x = foo ( do { # In theory, this will pass 7 to foo() if $arg is 3 # In reality, it will return from test() return 7 if $arg == 3; } ); $x = 5; return $x; } print test( 3 ),$/; print test( 5 ),$/; sub foo {};

    Cheers,
    Ovid

    Join the Perlmonks Setiathome Group or just click on the the link and check out our stats.

      Ovid,

      You are a true scholar and a gentleman - Many thanks, I will incorporate a fix based upon your code into a new release of CGI::Upload later today.

      Regards,
      Rob