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

Hi all, This is probably a stupid question, but I will ask any way..... I have a form to upload a file to a specific dir on the server. When I use POST for the method, instead of the file name, I get the contents of the file as the file name. If I use GET, I get the file name. Why? I don't really want to use GET since it shows the info in the URL. (security thing) By way of example, the file I am using as a test is called test1.txt. The file contains only one line "This is the test file" With my code, the file name becomes "This is the test file" This is driving me nuts..... Can anyone shed some light on this please? Thanks! Jim The code I am using for the form:
print "<FORM METHOD=\"post\" ENCTYPE=\"multipart/form-data\">\n"; print "<INPUT TYPE=\"FILE\" SIZE=\"25\" NAME=\"UPLOAD\">\n"; print "<input type=\"hidden\" name=\"login\" value=\"$login\">\n"; print "<input type=\"hidden\" name=\"password\" value=\"$password\">\n +"; print "<input type=\"submit\" value=\" Send File \">\n"; print "</FORM>\n";
The code I am using for the script:
$dir = '/Full/path/to/ul/dir'; $filename = $input{'UPLOAD'}; $filename =~ s/.*[\/\\](.*)/$1/; $fileUp = $dir.$filename; my $upload_filehandle = "$filename"; open UPLOADFILE, ">$dir/$filename"; binmode UPLOADFILE; while ( <$upload_filehandle> ) { print UPLOADFILE; } close UPLOADFILE;

Replies are listed 'Best First'.
Re: Upload form
by zentara (Cardinal) on Feb 18, 2007 at 17:43 UTC
    It looks to me its the way you are parsing your cgi. Try this upload script:
    #!/usr/bin/perl use warnings; use strict; use CGI; use CGI::Carp 'fatalsToBrowser'; #my $maxsize = 1024 * 100; #max 100K my $maxsize = 1024 * 20000; #max 20M #$CGI::POST_MAX= $maxsize; # max 100K posts !not working right? #$CGI::DISABLE_UPLOADS = 1; # no uploads my $query = new CGI; my $upload_dir = "uploads"; #permissions for dir are set print $query->header(); if($ENV{CONTENT_LENGTH} > $maxsize){ print "file too large - must be less than $maxsize bytes"; exit; } my $file = $query->param("file"); my $filename = $file; $filename =~s/.*[\/\\](.*)/$1/; open (UPLOADFILE, ">$upload_dir/$filename"); $/= \8192; # sets 8192 byte buffer chunks, perldoc perlvar while ( <$file> ){ print UPLOADFILE $_; #select(undef,undef,undef,.05); #for testing } close UPLOADFILE; print <<END_HTML; <HTML> <HEAD> <TITLE>Thanks!</TITLE> </HEAD> <BODY bgcolor="#ffffff"><br> <P>Thanks for uploading file : $filename!</P> </BODY> </HTML> END_HTML
    and a form
    <html> <form enctype="multipart/form-data" method=post action=http://z.net/cg +i-bin/up1.cgi> <input type=file name=file > <INPUT TYPE="submit" VALUE="Send!"> + </form> </html>

    I'm not really a human, but I play one on earth. Cogito ergo sum a bum
      Thank you, that worked.

      I do appreciate the time, but I am curious about why the contents of the file are returned when I use $input{UPLOAD} and select the file on the form when that field name is UPLOAD.

      That is going to drive me nuts until I figure it out.

      But again, thank you for taking the time to answer.
      Jim

        That is going to drive me nuts until I figure it out.

        My advice is to let it go for now, and just accept CGI.pm's way of doing it. A few years ago, after Perl5 came out, and CGI.pm, there was many posts here concerning the old manual-cgi-parsing, and the general wisdom is always use CGI.pm instead of the old Perl4 style manual input parsing. The question was asked so many times, that when anyone asked a cgi question that used manual parsing, they were answered simply with " use CGI.pm".

        So let it go. There are many tiny details, see manual parsing for an idea of the complexities. So just accept for now, as a definition, "always use CGI.pm". The common complaint about CGI.pm is that it is big and cumbersome, but you can just import the input parsing portion of it.... use CGI qw(:cgi), or check out CPAN for CGI::Simple and CGI::Lite.

        You will run into so many problems with manual parsing that it is a waste of time to learn it. For instance what happens when you have multiple files to upload, or you want to give a different name to the uploaded file on the receive end? Look at this nice example:

        #!/usr/bin/perl use warnings; use strict; use CGI::Simple; my $upload_dir='uploads'; my $q = new CGI::Simple; print $q->header(); my $files = $q->upload(); # number of files uploaded +; my @files = $q->upload(); # names of all uploaded fil +es my $filename = $q->param('upload_file'); # filename of uploaded fil +e my $mime = $q->upload_info($filename,'mime'); # MIME type of uploa +ded file my $size = $q->upload_info($filename,'size'); # size of uploaded f +ile # short and sweet upload my $ok = $q->upload( $q->param('upload_file'),"$upload_dir/$filename") +; print "Uploaded ".$q->param('upload_file')." and wrote it OK!\n" if $o +k; print "total files = $files<br> filenames = @files<br> filename = $filename<br> mimetype= $mime<br> size=$size<br>";

        I'm not really a human, but I play one on earth. Cogito ergo sum a bum
Re: Upload form
by Joost (Canon) on Feb 18, 2007 at 17:42 UTC
(security thing) was Re: Upload form
by chromatic (Archbishop) on Feb 18, 2007 at 21:44 UTC
    I don't really want to use GET since it shows the info in the URL. (security thing)

    What leads you to believe that a client could not also show the contents of a POST request?

    All you know about the client is that it speaks HTTP. It could do anything it wants with what you send to it, and it could send anything back.

    Assuming you have a finite amount of time to write a secure application, spend your time doing things that will provide actual security, not superficial security.

    Of course, if you're doing internal development and you know that no one will ever use anything other than the company-mandated web browser, even by accident, you can make other assumptions. Do be cautious though.

Re: Upload form
by shmem (Chancellor) on Feb 18, 2007 at 21:28 UTC
    You've got some answers so I'll just focus on something that makes me go Eek! :-)
    print "<FORM METHOD=\"post\" ENCTYPE=\"multipart/form-data\">\n"; print "<INPUT TYPE=\"FILE\" SIZE=\"25\" NAME=\"UPLOAD\">\n"; print "<input type=\"hidden\" name=\"login\" value=\"$login\">\n"; print "<input type=\"hidden\" name=\"password\" value=\"$password\">\n +"; print "<input type=\"submit\" value=\" Send File \">\n"; print "</FORM>\n";

    If you don't use a module to construct your form, at least use here-docs:

    print <<"END_OF_FORM"; <FORM METHOD="post" ENCTYPE="multipart/form-data"> <INPUT TYPE="FILE" SIZE="25" NAME="UPLOAD"> <input type="hidden" name="login" value="$login"> <input type="hidden" name="password" value="$password"> <input type="submit" value=" Send File "> END_OF_FORM

    Keep your code readable. Ah, and don't pass around hidden fields with username/password, use e.g. a cookie to store a session key. See Basic cookie management.

    --shmem

    _($_=" "x(1<<5)."?\n".q·/)Oo.  G°\        /
                                  /\_¯/(q    /
    ----------------------------  \__(m.====·.(_("always off the crowd"))."·
    ");sub _{s./.($e="'Itrs `mnsgdq Gdbj O`qkdq")=~y/"-y/#-z/;$e.e && print}