in reply to File Upload To Selected Directory
Please see perlsec for some details about security. One general rule is that you do not allow anyone to name files on your system. Generate a unique filename and use that. NEVER TRUST USER INPUT!!!#!/usr/bin/perl -wT use strict;
Also, you should check your open statement for success.
I'll post more later after I've cleaned up your code a bit.
Cheers,
Ovid
Update:Here's a somewhat cleaner version of your script. It has the following features (but is untested!!!):
The Perl resembles the following:<SELECT name="path"> <OPTION value="personal">Personal Images</OPTION> <OPTION value="impersonal">Impersonal Images</OPTION> </SELECT>
You should also check your directory size, to make sure someone doesn't upload 1000 1 meg files.#!/usr/bin/perl -wT use strict; use CGI; use Fcntl; use constant BUFFER_SIZE => 16_384; # Amount of upload file to + read at one time use constant MAX_FILE_SIZE => 1_048_576; # This is the filesize upl +oad limit use constant UPLOAD_DIR => "/home/sites/web/directory/"; $CGI::DISABLE_UPLOADS = 0; # Temporarily reenable upl +oads $CGI::POST_MAX = MAX_FILE_SIZE; # This will stop someone f +rom uploading # a fifty meg file to your + system my $req = CGI->new; my $theext = "gif"; my $donepage = "up2.html"; my %upload_path = {personal => 'personal/', impersonal => 'anotherpath/'}; my $path = $req->param('path'); if (! exists $upload_path{$path}) { # Oops! It's not in our hash. Someone was being naughty! print $req->redirect("some_error_page.html"); exit; } $path = $upload_path{$path}; UPLOAD_FILE: { for my $onnum (1..10) { my $file = $req->param("FILE$onnum") or next UPLOAD_FILE; if ($file) { my $buffer; my $file_handle = $req->upload( $file ); my $format = $req->uploadInfo($file)->{'Content-Type'}; # In the following regex, we're getting the image type of +the MIME type. # This is better than checking the extension because if th +ey upload from # a system that doesn't use extensions - or if the user's +redefined their # extensions, we'd have problems. $format =~ s!^image/([a-zA-Z]+)$!$1!; if ($format !~ /$theext/o) { next UPLOAD_FILE; } my $fileName = ""; # Create a random filename. Keep running the loop if the +filename exists, # or if $fileName is false. while (! $fileName or -e UPLOAD_DIR.$path.$fileName) { $fileName = ""; my @myarray=('a'..'z','A'..'Z','1'..'9'); for (1..8) { $fileName .= $myarray[rand(@myarray)]; } $fileName .= ".$theext"; } # This will create the new file sysopen OUTFILE, UPLOAD_DIR . $path . $fileName, O_CREAT o +r die "Can't open UPLOAD_DIR$path$fileName: $!"; while ( read( $file_handle, $buffer, BUFFER_SIZE ) ) { print OUTFILE $buffer; } close (OUTFILE); } } } # Send them to the confirmation page. print $req->redirect($donepage);
You'll also need CGI.pm version 2.47 or above to use the upload method.
I've also added a quick hack to allow users to choose subdirectories from a pre-approved list. It's untested and not great, but again, no user data gets to the shell. Using this method, you'll need to create those download directories in advance and make sure that they are writeable by the same user your script is running under (probably user "nobody").
Join the Perlmonks Setiathome Group or just go the the link and check out our stats.
|
---|