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

in a nutshell, i am using CGI.pm to handle uploading files to a webserver. Everything seems to work fine, except for one (not so) edge case when the enduser path of the file to be uploaded contains a special character such as comma, ampersand, or others. CGI.pm acts like it is uploading the file, but nothing is ever read in to the in-memory var that is later flushed to a file. the completely embarrassing, but-in-other-circumstances-usable code for handling the file upload is below.
my $file = $cgi->param('file'); select((select($file), $|=1)[0]); my $tempFile; while(<$file>) { $tempFile .= $_; } close($file); mkdir("/var/www/html/pmuze/upload/$username"); open(LOCAL, ">/var/www/html/pmuze/upload/$username/$fileName") or warn + $!; select((select(LOCAL), $|=1)[0]); binmode(LOCAL); print LOCAL $tempFile; close(LOCAL);
what kind of crack am i smoking here? (i also have data::dumper's of the offending cgi objects if that would help)

Replies are listed 'Best First'.
Re: CGI File Upload Problems
by chromatic (Archbishop) on Apr 04, 2007 at 02:48 UTC

    Setting autoflush on a filehandle from which you want to read is awfully curious, at best:

    my $file = $cgi->param('file'); select((select($file), $|=1)[0]);

    Setting it for output here is curious too. If you're printing the file all in one chunk and closing it immediately, and if you're on a Unix platform, it's fairly meaningless code.

    That's probably not the immediate problem. I seem to recall that my $fh = $cgi->upload( 'file' ) returns a more useful filehandle; does that solve the problem for you?

      i'll give that func a try.

      as for the flushing, well let's just say i was thrashing in agony trying everything that came to mind.
Re: CGI File Upload Problems
by Ovid (Cardinal) on Apr 04, 2007 at 08:31 UTC

    Where are $username and $fileName coming from? If those are from user-supplied data, you have a very serious security hole here, one which could leave your system wide open to attackers.

    Cheers,
    Ovid

    New address of my CGI Course.

      well, it turns out that I Win Teh Intarweb today, cause the problem was being caused by some of my security related checks on input. thanks for all your help!
      $username is generated from user supplied info following very strict data sanitation (no special chars and a bunch of other checks for sql injection and other attacks). $filename is a basically int(rand(1000000))
Re: CGI File Upload Problems
by randyk (Parson) on Apr 04, 2007 at 04:44 UTC
    The following:
    use strict; use warnings; use CGI; use CGI::Carp qw/fatalsToBrowser/; my $q = CGI->new(); print $q->header(), $q->start_html("File Upload Example"); # Start a multipart form. print $q->start_multipart_form(), "Enter the file to process: ", $q->filefield('filename','',25), $q->br, $q->reset, $q->submit('submit','Process File'), $q->endform; # Process the form if there is a file name entered if (my $file = $q->upload('filename')) { my $tmpfile=$q->tmpFileName($file); my $txt; while (<$file>) { $txt .= $_; } close($file); print $q->hr(), $q->h2($file), $q->h3($tmpfile), $q->p, $txt; } print $q->hr(), $q->end_html;
    works for me, even for files that have a comma or & in their names. Does this also exhibit a problem for you? Perhaps there's something going wrong at the stage of writing to the local file?
      well, your code works just fine, and mine doesn't. at least that's something (nothing is completely broken)--thanks for your help, i think i will be able to get it fixed!
Re: CGI File Upload Problems
by varian (Chaplain) on Apr 04, 2007 at 07:16 UTC
    If the filename contains metacharacters this may lead to undesired behavior:
    open(LOCAL, ">/var/www/html/pmuze/upload/$username/$fileName")
    I would highly recommend to use a three argument call to open as to avoid the open function from performing any magic.

    Excerpt from open function Perl documenattion:

    The filename passed to 2-argument (or 1-argument) form of open() will have leading and trailing whitespace deleted, and the normal redirection characters honored. This property, known as "magic open", can often be used to good effect. A user could specify a filename of "rsh cat file |", or you could change certain filenames as needed.
    Use 3-argument form to open a file with arbitrary weird characters in it.
    In particular for filenames received via webforms you want to be careful.
Re: CGI File Upload Problems
by jupe (Beadle) on Apr 04, 2007 at 03:20 UTC
    unfortunately the $cgi->upload() method was not the silver bullet. other thoughts?