Perl Upload a File to a Website
Uploading Files Using CGI and Perl
Would yous like to give your visitors the ability to upload files to your site? Letting them upload content with their Web browsers can be very useful, and fun too! Yous can permit them contribute pictures, sounds and other binary files to your site. And you can use a file upload facility on your own Website to update your site�s content easily via your own Web browser.
If you�ve ever used a Spider web-based e-mail service such as Gmail or Hotmail, y'all�ve probably sent email with attachments. To add attachments to your emails, you but click the �Browse�� push on the Web page to select the file from your hard drive, and then your browser sends the file to the server. This is file upload in activity!
Merely how does it piece of work? In this article, which has been updated from an earlier version I wrote a few years ago, I�m going to talk you through the process of file upload, and show you how to build a simple file upload example using CGI and Perl � that�s right, Perl! Despite the hype over other scripting languages, Perl is still a powerful and pop selection to power a web site. The example we�ll go through will let people to upload photos of themselves to your Web server.
What You Need
To build your own file upload script, you�ll need the following:
Access to a Web server that supports CGI (nearly all exercise)
A copy of Perl running on the Web server
The Perl CGI library, CGI.pm, installed on your Web server. This is probably pre-installed.
How Does It Work?
File upload works by using a special type of form field called �file�, and a special type of form encoding called �multipart/course-data�. The file form field displays a text box for the filename of the file to upload, and a �Browse�� button:
At the Web server cease, the software (in our case, a CGI script) interprets the form data that�southward sent from the browser, and extracts the file name and contents, forth with the other form fields. Usually, the file is then saved to a directory on the server. Now, allow�s create a file upload form that allows your users to upload files to your Web server.
The grade chemical element
The first part of a file upload form is the �form� element:
<class action="/cgi-bin/upload.cgi" method="post" enctype="multipart/class-information">
Note the special multipart/form-data encoding type, which is what we utilise for file upload. Note as well that the class will post the data to our upload script, called upload.cgi, which we�ll create in the next section.
The file upload field
The second part of the file upload form is the upload field itself. In this example, we�re creating a form so that our users can upload their photos, then nosotros need an upload field called �photograph�:
Photo to Upload: <input type="file" name="photo" />
The Submit Button
As with a regular form, nosotros need a submit push button so that the user can send the course to the Web server:
<input blazon="submit" name="Submit" value="Submit Form" />
Here is the consummate form:
<grade action="/cgi-bin/upload.cgi" method="post" enctype="multipart/grade-data"> <input type="file" name="photo" /> <input type="submit" name="Submit" value="Submit Form" /> </grade>Next we will programme the upload.cgi script.
Creating the file upload script
Handling the data that the browser sends when it uploads a file is quite a circuitous process. Fortunately, the Perl CGI library, CGI.pm, does most of the dirty work for us! Using ii methods of the CGI query object, param and upload, we tin retrieve the uploaded file�s filename and file handle, respectively. Using the file handle, we can read the contents of the file, and relieve it to a new file in our file upload area on the server.
At the top of our script, nosotros need to create the shebang line. We then put the Perl interpreter into strict way to make our script equally safe every bit possible, and include the Perl CGI and File::Basename modules for use in the script. We�ll besides utilise the CGI::Carp module to display errors in the spider web page, rather than displaying a generic �500 Server Error� message (information technology�due south a skilful idea to comment out this line in a production environment):
#!/usr/bin/perl -wT utilise strict; use CGI; use CGI::Carp qw ( fatalsToBrowser ); use File::Basename;Annotation the use of the -due west switch to make Perl warn united states of america of any potential dangers in our code. It�s nearly always a good idea to put the -w in! In addition, the -T switch turns on taint checking. This ensures that whatever untrusted input to the script, such as the uploaded file�s filename, is marked every bit tainted; we so need to explicitly �make clean� this data before using information technology. (If you try to use tainted data, Perl throws an error.) More on this in a moment.
In lodge to preclude the server being overloaded by huge file uploads, we�ll limit the allowable size of an uploaded file to 5MB; this should be big plenty to handle nearly digital photos:
$CGI::POST_MAX = 1024 * 5000;
We�ll also create a list of �condom� characters for filenames. Some characters, such every bit slashes (/), are unsafe in filenames, as they might allow attackers to upload files to whatsoever directory they wanted. Mostly speaking, messages, digits, underscores, periods, and hyphens are safe bets:
my $safe_filename_characters = "a-zA-Z0-9_.-";
Upload directory
We need to create a location on our server where we tin shop the uploaded files. We desire these files (the photos) to be visible on our spider web site, and then we should store them in a directory under our document root, for case:
my $upload_dir = "/domicile/mywebsite/htdocs/upload";
You�ll need to create a directory chosen �upload� on your spider web site�s document root, and then set $upload_dir to the absolute path to that directory, as I�ve done above. Make sure your directory can be read and written to past your script; on a shared UNIX server, this usually ways setting the manner to 777 (for example, by issuing the chmod 777 upload control at the command line). Check with your web hosting provider if yous�re not sure what you need to do.
Reading the Form Variables
The next pace is to create a CGI object (nosotros assign it to $query below); this allows united states to access methods in the CGI.pm library. We can then read in the filename of our uploaded file, and the electronic mail accost that the user entered into the form:
my $query = new CGI; my $filename = $query->param("photograph"); my $email_address = $query->param("email_address"); If there was a trouble uploading the file � for example, the file was bigger than the $CGI::POST_MAX setting � $filename will exist empty. We can examination for this and report the problem to the user as follows:
if ( !$filename ) { print $query->header ( ); print "In that location was a problem uploading your photo (effort a smaller file)."; exit; } Making the Filename Condom
We can�t necessarily trust the filename that�due south been sent past the browser; an attacker could manipulate this filename to do nasty things such as upload the file to any directory on the Spider web server, or attempt to run programs on the server.
The first affair we�ll do is employ the fileparse routine in the File::Basename module to dissever the filename into its leading path (if any), the filename itself, and the file extension. We can and so safely ignore the leading path. Not just does this help thwart attempts to save the file anywhere on the spider web server, but some browsers ship the whole path to the file on the user�s difficult drive, which is obviously no use to us:
my ( $proper noun, $path, $extension ) = fileparse ( $filename, '\..*' ); $filename = $name . $extension;
The above code splits the full filename, as passed by the browser, into the name portion ($name), the leading path to the file ($path), and the filename�s extension ($extension). To locate the extension, we laissez passer in the regular expression '\..*' � in other words, a literal period (.) followed by zero or more characters. We then join the extension dorsum onto the name to reconstruct the filename without any leading path.
The next stage in our quest to clean upwardly the filename is to remove any characters that aren�t in our safety graphic symbol listing ($safe_filename_characters). We�ll use Perl�s substitution operator (s///) to practise this. While we�re at it, nosotros�ll catechumen any spaces in the filename to underscores, equally underscores are easier to bargain within URLs:
$filename =~ tr/ /_/; $filename =~ due south/[^$safe_filename_characters]//one thousand;
Finally, to make doubly sure that our filename is now condom, we�ll match information technology against our $safe_filename_characters regular expression, and excerpt the characters that match (which should exist all of them). We as well demand to practise this to untaint the $filename variable. This variable is tainted because information technology contains potentially unsafe data passed by the browser. The merely way to untaint a tainted variable is to apply regular expression matching to extract the safe characters:
if ( $filename =~ /^([$safe_filename_characters]+)$/ ) { $filename = $i; } else { dice "Filename contains invalid characters"; } (Note that the to a higher place die function should never be executed, because we�ve already removed our dodgy characters using the before commutation. Nonetheless, information technology doesn�t injure to be cautious!)
Getting the File Handle
Equally I mentioned to a higher place, we can utilise the upload method to grab the file handle of the uploaded file (which actually points to a temporary file created by CGI.pm). Nosotros do this like so:
my $upload_filehandle = $query->upload("photo"); Saving the File
At present that we accept a handle to our uploaded file, we can read its contents and save it out to a new file in our file upload area. We�ll use the uploaded file�due south filename � now fully sanitised � as the name of our new file:
open ( UPLOADFILE, ">$upload_dir/$filename" ) or die "$!"; binmode UPLOADFILE; while ( <$upload_filehandle> ) { print UPLOADFILE; } close UPLOADFILE; Notice the die function at the terminate of the showtime line to a higher place; if at that place�south an fault writing the file, this function stops the script running and reports the error message (stored in the special variable $!). Meanwhile, the binmode office tells Perl to write the file in binary mode, rather than in text mode. This prevents the uploaded file from being corrupted on not-UNIX servers (such as Windows machines). Thanking the User
We�ve now uploaded our file! The final step is to display a quick thank-you annotation to the users, and to show them their uploaded photograph and e-mail address:
print $query->header ( ); print <<END_HTML; <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "DTD/xhtml1-strict.dtd"> <html xmlns="http://world wide web.w3.org/1999/xhtml" xml:lang="en" lang="en"> <caput> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <title>Cheers!</title> <way blazon="text/css"> img {border: none;} </style> </caput> <trunk> <p>Thanks for uploading your photo!</p> <p>Your email accost: $email_address</p> <p>Your photograph:</p> <p><img src="/upload/$filename" alt="Photograph" /></p> </trunk> </html> END_HTML The finished script
Our finished CGI script should await something similar this:
#!/usr/bin/perl -wT use strict; employ CGI; employ CGI::Carp qw ( fatalsToBrowser ); use File::Basename; $CGI::POST_MAX = 1024 * 5000; my $safe_filename_characters = "a-zA-Z0-9_.-"; my $upload_dir = "/home/mywebsite/htdocs/upload"; my $query = new CGI; my $filename = $query->param("photo"); my $email_address = $query->param("email_address"); if ( !$filename ) { print $query->header ( ); print "There was a problem uploading your photograph (endeavour a smaller file)."; get out; } my ( $proper noun, $path, $extension ) = fileparse ( $filename, '\..*' ); $filename = $proper noun . $extension; $filename =~ tr/ /_/; $filename =~ s/[^$safe_filename_characters]//g; if ( $filename =~ /^([$safe_filename_characters]+)$/ ) { $filename = $ane; } else { die "Filename contains invalid characters"; } my $upload_filehandle = $query->upload("photo"); open up ( UPLOADFILE, ">$upload_dir/$filename" ) or die "$!"; binmode UPLOADFILE; while ( <$upload_filehandle> ) { print UPLOADFILE; } close UPLOADFILE; impress $query->header ( ); print <<END_HTML; <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML ane.0 Strict//EN" "DTD/xhtml1-strict.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-viii" /> <title>Thanks!</championship> <way blazon="text/css"> img {edge: none;} </fashion> </head> <body> <p>Thank you for uploading your photo!</p> <p>Your email address: $email_address</p> <p>Your photo:</p> <p><img src="/upload/$filename" alt="Photo" /></p> </body> </html> END_HTML Salvage this file on your difficult drive, and call it upload.cgi. Now we�ve created our server-side script, we can place both the script and the form on our server and exam the file upload.
Savor!
Source: https://www.ihypress.net/programming/perl/upload.html
Post a Comment for "Perl Upload a File to a Website"