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

Hi there. I'm trying to do an upload - and have a couple of questions.

I'm building a file sharing application, so a few folks who are on a password-protected extranet can share files via the web. The following code is part of this script (there is a link at the bottom of each directory listing for uploading files. The link looks like: "/cgi-bin/xi_fileshare.cgi?upload=get&fileshare_directory=path_of_current_directory"

Here's the code snippet:

if ($query_string =~ /upload/) { (my $upload, my $fileshare_directory) = split ('&',$query_string); (my $stuff, $fileshare_directory) = split ('=',$fileshare_director +y); if ($upload eq "upload=get") { #################################### # # This is the situation if the script is called from the file +list # #################################### print start_multipart_form(-action=>'/cgi-bin/xi_fileshare.cgi +'), hidden (-name=>'upload', -value=>'upload'), hidden (-name=>'fileshare_directory', -value=>'$fileshare_ +directory'), filefield(-name=>'file_upload', size=>60), br, submit(-label=>'Upload File'), end_form; } else { #################################### # # This is when it's called with a file upload # #################################### my $length; print "Query:$query_string<br>\n"; my $file = param('file_upload'); if (!$file) {print "Ain't no file!<br>\n"; exit;} print h2 ('File Name:'),$file; print h3('File MIME TYPE:'), uploadInfo($file)->['Content-Type']; while (<$file>) { $length += length ($_); } print h3('File Length:'),$length; } exit; }
(At this point, I'm just trying to get info on the file, I'll deal with saving the file later). Two problems - first - I can't seem to pass any parameters. When I run this and enter in a file, all of the parameters are empty. However, when I print the query string, all of the data about the form, and the hidden fields, are all there. So what's up?

Second problem, and I've encountered this many times before using CGI - if I call a script using a specific parameter, like "upload=get", then set up another (or the same) form, but change the value of this parameter via a hidden field (like I do above, to set the value of the upload parameter to "upload"), the old value sticks. In this case, when I look at the data when the query string prints out, a line of that data is:
'Content-Disposition: form-data; name="upload" get'

So clearly the old value is sticking, even though I tried to change it. Is this a bug, or am I doing something wrong?

Thanks for any help here!

Replies are listed 'Best First'.
Re: Uploading using CGI, plus a bug in CGI?
by Zaxo (Archbishop) on Oct 09, 2001 at 05:28 UTC

    You are neglecting one of the best reasons to use CGI.pm, the CGI::param method. Both problems will go away when you use that correctly. See 'perldoc CGI'.

    After Compline,
    Zaxo

Re: Uploading using CGI, plus a bug in CGI?
by pjf (Curate) on Oct 09, 2001 at 06:49 UTC
    G'day michellem,

    The "stickiness" is actually intentional. This allows you to display a form, have the user fill in some values, and then spit the form back at them with their previous values already filled in. This saves a lot of effort should you be re-printing the form due to bad or insufficient input, or carrying the values to a different form where you want the user's choices to stay.

    As such, any "value" that you provide to a form field (including hidden fields) is merely a "default" which gets used if we have no previous paramater value of that name. If you want your new value to override any pervious values, you need to pass in an "override" option, like this:

    hidden(-name=>"Upload",-value=>"foo",-override=>1);
    Also, the advice about not decoding your own query string is incredibly wise. The CGI module already does this for you with its param() function.

    If you're using CGI version 2.47 or above, then you won't want to use param() to grab files like you're doing in your code above, as the upload() function does a much better job. param() can return something which is not a filehandle if your users are being mischievious with their parameters, whereas upload() guarantees that what you get back is a valid filehandle or undef.

    If you have to use param() to get uploaded files, there's a discussion on checking if something is a filehandle here.

    Cheers,
    Paul