Important alert: (current site time 7/15/2013 8:37:14 PM EDT)
 

VB icon

CGI File Upload (with filename acquisition)

Email
Submitted on: 8/1/2002 3:18:44 AM
By: Nate Cox  
Level: Beginner
User Rating: By 21 Users
Compatibility: 5.0 (all versions), Active Perl specific, 4.0 (all versions), 3.0 (all versions), Pre 3.0
Views: 34356
author picture
(About the author)
 
     To upload a file of any type to your website. I offer you the unique ability to call the original filename, and save the file as it was intended, not under a temporary, or alternate, filename. (though... if you want to force the name for some reason, it's easy enough to modify my code to do so...)
 
code:
Can't Copy and Paste this?
Click here for a copy-and-paste friendly version of this code!
 
Terms of Agreement:   
By using this code, you agree to the following terms...   
  1. You may use this code in your own programs (and may compile it into a program and distribute it in compiled format for languages that allow it) freely and with no charge.
  2. You MAY NOT redistribute this code (for example to a web site) without written permission from the original author. Failure to do so is a violation of copyright laws.   
  3. You may link to this code from another website, but ONLY if it is not wrapped in a frame. 
  4. You will abide by any additional copyright restrictions which the author may have placed in the code or code's description.
				
=**************************************
= Name: CGI File Upload (with filename acquisition)
= Description:To upload a file of any type to your website. I offer you the unique ability to call the original filename, and save the file as it was intended, not under a temporary, or alternate, filename. (though... if you want to force the name for some reason, it's easy enough to modify my code to do so...)
= By: Nate Cox
=
= Inputs:The code comes with the nessicary HTML form required to use this script. nothing complex, and you can add it to ANY html webpage!
=
= Returns:Well, it uploads the file! i guess that counts as a return!
=
= Assumes:My code is VERY well commented and you should not have a problem with anything, however if you DO then feel free to e-mail me, or comment! I'm happy to answer any questions that you may have.
=
= Side Effects:Nothing. This script is completly safe.
=
=This code is copyrighted and has= limited warranties.Please see http://www.Planet-Source-Code.com/vb/scripts/ShowCode.asp?txtCodeId=348&lngWId=6=for details.=**************************************

#!c:/perl/bin/perl.exe
###############################################################################
# before you start, you are going to need an HTML form to use this#
# script. Basically a way to call the script to be used. #
# i'll enclose the form you need below: #
# <form enctype="multipart/form-data" method=post action="/cgi-bin/file1.pl"> #
# <input type=file name=filex>#
# <input type=submit value="Submit">#
# </form> #
# just replace the "/cgi-bin/file1.pl" in the top with whatever you decide to #
# name the file.#
###############################################################################
########################
# enable CGI interface #
########################
use CGI;
###########################
# Set maximum upload size #
###########################
$CGI::POST_MAX = 2048;
#####################
# post content type #
#####################
print "content-type: text/html\n\n";
###################################################################
# Now we really begin. binmode() sets the argument passed into it #
# to a binary file. This means that it can be ANY type of file #
# because EVERYTHING is base binary. Without this line you will #
# only be allowed to successfully upload text files. The next #
# line sets the arguments passed from our form (which perl calls #
# STDIN) to a binary mode. #
###################################################################
binmode(STDIN);
###################################################################
# The next two lines are simple. We are passing the array "STDIN" #
# into two differant arrays. @inx will be used for opening and #
# saving the file, while @filetest will be used to pull the files #
# name out. We must seperate STDIN into both of these arrays #
# because @inx is going to be taken apart later, and we can't #
# risk losing anything!#
###################################################################
@inx = <STDIN>;
@filetest = <STDIN>;
###################################################################
# Finally we arive at one of the most frustrating parts of #
# Writing this script! Obviously we want to know the name of the #
# original file because we need to know what to save it as. #
# Perl does NOT make this easy for us. one of the elements of the #
# STDIN's arguments is a string that tells us EVERYTHING about #
# the file. the problem is that it gives too much information #
# with no way to easily get one aspect. To show you what i mean #
# i'll give you the argument below:#
# Content-Disposition: form-data; name="filex"; filename="C:\Docu #
# ments and Settings\Owner\Desktop\Dracula.txt" #
# As you can see, it tells us everything we would want to know, #
# however pulling that information out is very tricky. I came up #
# with a way. I start by reversing the entire string. This makes #
# the filename start from the beginning of the string. backwards. #
# Then I search through the string looking for a "\" (the#
# backwards equivilent of "/") because we know the filename will #
# start at the end of the directory settings. As i look for the #
# "\" I store each character in a string, and by the time i find #
# the "\" i have the filename (backwards). Then it's a simple #
# matter of re-reversing the string and we have our filename! #
# you will see below!#
###################################################################
$str = @inx[1];
$str1 = reverse $str;
$filename1 = "";
$currchar = "";
$offset = 3;
while ($currchar !~ /\\/) {
 $currchar = substr($str1, $offset, 1);
 if ($currchar !~ /\\/) {
$filename1 = "$filename1$currchar";
$offset++;
 }
}
$filename2 = reverse $filename1;
####################################################################
# We now have the filename stored in "$filename2". Lets move on. #
# Now, as i said before, everything is stored in STDIN, so we know #
# that the actual file is there too. Finding it is fairly simple. #
# First of all we cut up (or "splice") the array containing STDIN #
# I must Thank Dax Ahweng for this part of my code. He took the #
# time to figure out where the actual file was stored. Without #
# the code from him i never would have known where to start! #
# Anyways, we now splice @inx, removing the unnessisary elements #
# from STDIN. Then, in the following lines we further remove #
# the unnessisary characters, and strip @inx down to EXACTLY the #
# file data we need, storing that data in "$in" #
####################################################################
splice(@inx,0,4);
splice(@inx,$#inx,1);
$in = join("",@inx);
$in = substr($in,0,length($in) - 2);;
####################################################################
# from here on out everything is VERY simple. First, we open the #
# file that we wish to save. ">" means we want to create a new #
# file and overwrite anything that is named the same. The#
# directory you will have to change. I wrote this on a windows #
# computer, running an Apache server. MAKE SURE YOU KEEP THE #
# "$filename2" AT THE END!!!!!!!!!! This is our filename! without #
# this line we are not saving the file as anything!!!#
# We then set the file to a binary file (to read our binary STDIN) #
# and print the data to the file (note: after print it says ff #
# which is our filehandle. it means we are printing to that file, #
# not the screen. Finally, we close the file. #
####################################################################
open(ff,">../htdocs/pics/$filename2");
binmode(ff);
print ff $in;
close(ff);
####################################################################
# below this you may do whatever you wish. I personally just have #
# it display the file size, and a link where you can access the #
# file. but if you wish this is where you could redirect the page #
# or do whatever you need to do for your website #
####################################################################
print "DONE, Uploaded Size: ".length($in)." bytes\n";
print "<br>View file at: <a href=\"http://akujindomains.com/pics/$filename2\">$filename2</a>";
####################################################################
# I hope i didn't go too overboard on the commenting for you guys #
# (and girls, or corse)! I HATE finding scripts that are so #
# under-commented that you don't know what they are doing!! #
# i tried to keep the comments clean and precice, however if you #
# have any trouble with them... or you just don't like them... #
# feel free to let me know, and suggest how i might change them! #
# Also, if you like the code (and i spent a lot of time and effort #
# writing this for you guys so that you could have the original #
# filename) i would REALLY appreciate a vote! Thanks a lot! #
# Any questions or comments can be directed to akujin11@yahoo.com #
####################################################################


Report Bad Submission
Use this form to tell us if this entry should be deleted (i.e contains no code, is a virus, etc.).
This submission should be removed because:

Your Vote

What do you think of this code (in the Beginner category)?
(The code with your highest vote will win this month's coding contest!)
Excellent  Good  Average  Below Average  Poor (See voting log ...)
 

Other User Comments

9/20/2002 3:19:28 PMDax Ahweng

cool!

good to see you took the time to extract the filename :)

contact me dax@konqueror.net... and we'll talk about some stuff!
(If this comment was disrespectful, please report it.)

 
9/20/2002 3:28:44 PMDax Ahweng

one more thing, i havent read the whole thing, but at a point you say it doesnt matter if you set a text file to binmode(), i disagree, as in many situations, text files will not be recognised if they are stored in binary files, and many other situations such as newline character will require a return character associated with it, so all 'new lines' will be removed...

you should check if the file is binary or text before storing it...

just a thought.
(If this comment was disrespectful, please report it.)

 
12/1/2002 10:06:27 AM-Oz

$tmp_filename = $ENV{'SCRIPT_FILENAME'};

# Reverse the path
$tmp_filename = reverse($tmp_filename);

# Replace the first instance of / with :
$tmp_filename =~ s/\//:/;

# Split the string into an array via :
@script = split(/:/, $tmp_filename);

# Take the first value of the array and reverse it again
$script_filename = reverse(shift @script);
$script_path = reverse(shift @script).
(If this comment was disrespectful, please report it.)

 
2/5/2003 8:48:20 AMMichael Bacoz

Uh.. No... lol.
(If this comment was disrespectful, please report it.)

 
8/13/2003 11:33:10 PMHackMan Curda

Como le hago para instalarlo??
what i make for install???
that is the litle situacion that you dont say ;¬ )
(If this comment was disrespectful, please report it.)

 
12/3/2003 1:41:30 PM

When I upload an image it's beautiful. When I upload a .html or .txt file it adds

-----------------------------7d3394c1201ba Content-Disposition: form-data; name=
(If this comment was disrespectful, please report it.)

 
1/4/2004 4:29:39 PM

You ... Rock :). Actually all I needed to know was the binmode stuff but, nicely commented anyway !

Good job !

(If this comment was disrespectful, please report it.)

 
7/6/2004 6:57:47 AM

Another neat way to extract the filename is to use Perl's excellent regexp library

$str = @inx[1];
my ($filename) = $str =~ /.*\\(.*?)\
(If this comment was disrespectful, please report it.)

 
7/6/2004 6:59:58 AM

And an html formatted version of the above code is ...

$str = @inx[1];
($filename) = $str =~ /.*\\(.*?)\"/;
(If this comment was disrespectful, please report it.)

 
8/25/2004 5:44:49 AM

Hi, code looks perfect for what I need to do, but im a complete programming newbie so was just wondering if you could help me with the script im working on. Please email, thanks
(If this comment was disrespectful, please report it.)

 
8/25/2004 5:46:14 AM

Sorry, heres my email
(If this comment was disrespectful, please report it.)

 
9/18/2004 9:11:50 PM

this thing doesnt work
(If this comment was disrespectful, please report it.)

 
9/18/2004 9:39:58 PM

$str =
@inx[1];
($filename) = $str =~
/.*\\(.*?)\"/;

Who ever wrote that.. thank you sooo veryyy much
that little thing alone got the filename for me
(If this comment was disrespectful, please report it.)

 
11/22/2004 1:44:32 PM

You say this is completely safe, what about using it to run arbitrary code on a server?
(If this comment was disrespectful, please report it.)

 
11/23/2004 3:14:25 PMNate Cox

You'll have to give me a situation, and a method of replying to you.
(If this comment was disrespectful, please report it.)

 

Add Your Feedback
Your feedback will be posted below and an email sent to the author. Please remember that the author was kind enough to share this with you, so any criticisms must be stated politely, or they will be deleted. (For feedback not related to this particular code, please click here instead.)
 

To post feedback, first please login.