Perlfect Solutions

Pre-processing Url-Encoded CGI Input

So, you're writing your first CGI, and you're stuck right at the very beginning... Don't worry, that's very common. As soon as you set out to write your first script that will process data from a form you get to some of the most commonly asked newbie questions. This article will help you sort them out once and for all. As you'll soon see, it's all quite simple.

Where do I get my input from?

So, you wrote your simple form, say something like this: <FORM METHOD="GET" ACTION="/cgi-perlfect/test.pl"> Your name: <INPUT TYPE="text" NAME="name"> You e-mail: <INPUT TYPE="text" NAME="email"> <INPUT TYPE="submit"> </FORM> Now, you expect your CGI (test.pl) to get the values for name and email somehow... but how? There are two answers to that question. That is because there are two methods to submit a form, POST and GET. In fact, the only difference between the two methods lies in the way that the input is given to the script. Here's what happens in each case:

  1. GET: The input of a GET request is stored in a special environmental variable (if you don't know what that is, don't worry) called QUERY_STRING To access an environmental variable from your script, you have to use the %ENV hash that perl nicely provides. All you need to say is: $my_input = $ENV{QUERY_STRING}; and the form's data will be put to $my_input.
  2. POST: The POST method does not put your input in some variable. Instead, the web server, upon executing your script will pass the CGI input to the script from STDIN. (the standard input) So, all you have to do is to read from the STDIN filehandle to get your input. The only tricky thing is that, an EOF (end-of-file) is not guaranteed at the end of the string. So how do you figure out how much you need to read? Not coincidentally, the server puts the length of the input string into an environmental variable, CONTENT_LENGTH. So you have to read CONTENT_LENGTH bytes from STDIN. The line that does this is: read(STDIN, $my_input, $ENV{CONTENT_LENGTH}); Isn't perl lovely? A whole paragraph of jargon can be written in one simple line!

Now try the followin one-liner, that prints out to the browser the input string it got from the form: print "Content/type: text/plain\n\n$ENV{QUERY_STRING}";

Hell, but this comes all scrambled! How do I decode it?

For various reasons that we will not discuss at the moment, CGI input comes in a, somewhat messy, form, that has the fancy name Url-Encoded. The general form is the following: field1=value1&field2=value2&...&fieldn=valuen where, field1...fieldn are the names (as in the name attribute of the input tag in the HTML form) of the input fileds and value1...valuen are the corresponding values. (what the user typed in or selected) In addition, the resulting string is encoded, by replacing all spaces with pluses (+) and replacing certain other characters (like / and ~ and :) with hexadecimal ascii codes representing them. Now this looks messy, but don't be very scared (just a little), because with perl it only takes a couple of lines to decode. So, let's see how it's done:

First of all you'll have to separate each field-value pair from the rest. We use the split function to do that. @fv_pairs = split /\&/ , $my_input; The line above simple tells perl to split up the input string on the & symbol (which is the separator of two pair in url-encoded form) and put the list of resulting field-value pairs in the array @fv_pairs.

Then, we will have to take each of those pairs, separate the fieldname from the value, decode them, and store them in a hash (associative array) so that each fieldname is the key to its value. Here's how we do it: foreach $pair (@fv_pairs) { if($pair=~m/([^=]+)=(.*)/) { $field = $1; $value = $2; $value =~ s/\+/ /g; $value =~ s/%([\dA-Fa-f]{2})/pack("C", hex($1))/eg; $INPUT{$field}=$value; } } Now, what this does is pretty straightforward. We try each pair in turn, and if it is of the form field=value we store the fieldsnam and value in two separate variables. Then we replace all +es with spaces and decode hexadecimal sequences. (well, if you don't really follow the regular expressions, don't worry... you don't need to understand how they work, so long as you know how to use them - you will learn more with time) Finally, we put the value we get in an associative array with the relevant fieldname as a key.

So, now, all we need to do, is use the associative array %INPUT to access our form's data. For example, the following lines: print "Content-type: text/plain\n\n"; print "Your name is $INPUT{name} and your email is $INPUT{email} will print to the browser, something like Your name is Nick and your email is nick@perlfect.com for the example form we saw earlier.

That's basically all you need to know to get started. Trying things out and experimenting is your best bet at learning, so go on and try for yourself...

Happy CGI writing!

Comments

Your name:
Your comments:

Security check *

 

sreenivasulu   

Posted at 3:34am on Friday, April 20th, 2007

It helped me a lot.....

Raj   

Posted at 2:46pm on Wednesday, May 30th, 2007

Very well explained!

Vanessa   

Posted at 3:31am on Friday, June 15th, 2007

it helped me, thnx

john   

Posted at 12:12pm on Sunday, July 15th, 2007

Something is just not quite right. here is the code that I have tried and it does not work. I noticed that their should be a "; after {email} but, I still cannot get the code to work. Here is the form I am using:

Your name:
You e-mail:



here is the perl script I am using:

@fv_pairs = split /&/ , $my_input;
foreach $pair (@fv_pairs) {
if($pair=~m/([^=]+)=(.*)/) {
$field = $1;
$value = $2;
$value =~ s/+/ /g;
$value =~ s/%([dA-Fa-f]{2})/pack("C", hex($1))/eg;
$INPUT{$field}=$value;
}
}
print "Content-type: text/plainnn";
print "Your name is $INPUT{name} and your email is $INPUT{email}";

john   

Posted at 12:13pm on Sunday, July 15th, 2007

sorry htm form did not come through:

Your name:
You e-mail:

john   

Posted at 12:14pm on Sunday, July 15th, 2007

well, that did not work either it is identical to the one posted on this page.

john   

Posted at 12:19pm on Sunday, July 15th, 2007

Well, sorry I figured it out here is the the script for perl

$my_input = $ENV{QUERY_STRING};
@fv_pairs = split /&/ , $my_input;
foreach $pair (@fv_pairs) {
if($pair=~m/([^=]+)=(.*)/) {
$field = $1;
$value = $2;
$value =~ s/+/ /g;
$value =~ s/%([dA-Fa-f]{2})/pack("C", hex($1))/eg;
$INPUT{$field}=$value;
}
}
print "Content-type: text/plainnn";
print "Your name is $INPUT{name} and your email is $INPUT{email}";

Robert   

Posted at 1:18pm on Wednesday, October 10th, 2007

Excellent Note.

benila   

Posted at 5:56am on Sunday, March 30th, 2008

easy to syudy

Marco-Paul   

Posted at 5:07am on Wednesday, April 2nd, 2008

Why not use:

use CGI qw(:standard Vars);
my %form = Vars();

greetings,
Perllover

teen porn   

Posted at 9:51am on Tuesday, May 20th, 2008

Excellent job! Look forward to seeing more in the near future - teen porn. It's a pleasant surprise to find a sanctury from all that modern inane garbage(sex teen, anal teen sex, anal teen sex) they call music.

biju   

Posted at 2:08am on Wednesday, November 24th, 2010

you can param insted to get the values...no need to do these editings.....tat would be more simple

robby   

Posted at 4:00am on Tuesday, April 19th, 2011

I can see that you can write the content of a form to a file but how do your get it back into the form? I want to be able for a user to enter some details but because they may not know all the data required at the time they need to come back at a later date to complete the form so the form needs to fill in the fields they've alrady completed!

robby   

Posted at 4:01am on Tuesday, April 19th, 2011

I can see that you can write the content of a form to a file but how do your get it back into the form? I want to be able for a user to enter some details but because they may not know all the data required at the time they need to come back at a later date to complete the form so the form needs to fill in the fields they've alrady completed!

Bobby   

Posted at 9:04am on Wednesday, May 11th, 2011

Cool! That's a clever way of looikng at it!

qzleohpt   

Posted at 7:01pm on Wednesday, May 11th, 2011

tvBoSa stxmwutnswwz

vybuzfya   

Posted at 9:57pm on Friday, May 13th, 2011

NIZVIn rwcuhpgkehcj

Anonymous   

Posted at 3:40am on Monday, June 20th, 2011

http://www.haoivietnamtravels.com

foooaler   

Posted at 1:07am on Saturday, March 17th, 2012

Ordinarily I advise people to upgrade their gadgets every second generation.
So why am I not taking my own advice with the third-generation iPad?
Maybe it was carelessness. Then again, maybe my Samsung Galaxy Tab 10.1 was jealous that the iPad 2 was getting all the attention.

I had set the iPad 2 on top of the Galaxy Tab, which in turn was resting on a couple external hard drives in the power-strip section of my office where most of my electronica goes when it needs a current fix.
(Don't ask me about my office, and really don't ask my wife.) .
One of the hard disks was propped up a bit for better airflow, so the Galaxy Tab was sloped just a smidgen

promotional products   

Posted at 5:32am on Tuesday, May 15th, 2012

Nice experience shared. Its not less than an interview. Great way of posting such good http://www.sense2.com.au/ and informative stuff. promotional products

USB pens   

Posted at 12:03am on Tuesday, May 22nd, 2012

Cool post! How much stuff did you have to look up in order to write this one? I can tell you put some work in.
USB pens

branded products   

Posted at 4:17am on Saturday, August 18th, 2012

Excellent article you have here. I just love to tinker with images. I am very thankful that I stumbled upon this site. Keep posting more articles like this.

branded products

Sugriv   

Posted at 5:30am on Tuesday, August 21st, 2012

getElementsByTagName( a') will return an array of all anohcr elements in the page. Compare the href attributes of those items to the requested url until you find a match or fail.function get(eid) {var d = document;var r = d.getElementById(eid);return r;}function update() {var isInPage = false;var link = get('link').value;var d = document;var links =d.getElementsByTagName('a');var last = links.length;for (var i = 0; i < last; i++) {isInPage = link == links[i].href;if (isInPage) break;}if (isInPage) {// do submitalert('link is in page');}else {// do error processalert('link is NOT in page');}}Enter link to update:

jlygupfeo   

Posted at 9:30pm on Tuesday, August 21st, 2012

TuMAYe spkasmltnbrq

wyqsve   

Posted at 4:02am on Friday, August 24th, 2012

gz1tcQ hyewsxeavbvp

Anonymous   

Posted at 11:23am on Tuesday, February 19th, 2013

6543

Comments to date: 26.

Like it? Share it!

Suggested Reading

Official CGI.pm Programming Guide The Official CGI.pm Programming Guide is the definitive manual and guidebook for writing CGI programs with perl and the CGI library. While the manual distributed with the library as part of perl's documentation is well written and covers almost anything you'd need to know about using CGI.pm, this book is a useful companion for anyone making CGI scripts with perl.
CGI Programming CGI Programming is an introductry book for CGI programming, perhaps not the best book I've read. It covers most topics about the CGI protocol and how to write server side programs to work with it. Nevertheless, most if not all of the information in this book (as with most books that discuss CGI programming) can be found in tutorials and references on the web, but if you feel like buying a book anyway, you may want to consider this one.
Webmaster In A Nutshell Webmaster in a nutshell is a catch-all reference book for webmaster and programmers. It does not have anuything that you can't find online, but if you're liek me you might want to have all the stuff you refer to frequently nicely laid out in a well-organized book lying on your desk. If you're looking for something like that then you'll be happy with this book.
Perl Cookbook The Perl Cookbook is full of quick solutions to everyday programming problems in perl with explanations and tips easy to understand even for beginners, but also frequently useful even to more experienced programmers. The code is clear and straightforward and the topics covered as well-thought and correspond to real world examples, so frequently you can literally copy code snippets from the book and fit them in your program. It is a nice complement for the Camel Book on your bookshelf.