Figuring out Where you are
The next thing I do is to try to get my little script to talk to library
files since most likely, I will be using cgi-lib.pl to interpret incoming
form data. So one way or another, we will need our CGI script to be able
to talk to other files. To do that, I will need to grab cgi-lib.pl from
the web and place it in a sub-directory called Library. The subdirectory
should be readable and executable by the web server and cgi-lib.pl should
be readable by the web server.
So now I have something like this (open your browser window wide so this
does not wrap)
cgi-bin Directory (readable and executable by the web server)
..|___hello_world.cgi (readable and executable by the web server)
..|___Library Directory (readable and executable by the web server)
........|___cgi-lib.pl (readable by the web server)
Now, let's use the "require" command to pull cgi-lib.pl into our
"hello_world.cgi" program.
#!/usr/local/bin/perl
print "Content-type: text/html\n\n";
print "Hello World";
require ("./Library/cgi-lib.pl");
Getting pretty complex here pretty quickly eh? That is okay because we
know for sure that cgi-lib.pl does not have any bugs in it since it is
being used everywhere and has been for years now. So that means all we
really did was:
- Add a subdirectory called Library
- Transfer cgi-lib.pl from somewhere to the Library subdirectory
- Add one line of code to hello_world.cgi.
So what could go wrong with that?
- Permissions, permissions, permissions! Check Library and cgi-lib.pl!
- If you got an "EOF error at line xxx of cgi-lib.pl" error,
it is a good bet that you did not transfer cgi-lib.pl to your server
correctly. Specifically, you must make sure that you do not
introduce bad characters into the text of the program as it is sent
over the internet from my web server to yours.
Typically, you must make sure that you set your ftp client to
transfer in ASCII mode when you transfer scripts from one server to
another.
Also, you must make sure that you do not edit any scripts using a
text editor which will introduce bad characters (especially line
breaks and newline characters). I use PICO or EMACS for UNIX, Simple
Text for Mac and Notepad for Windows.
- It may also be that your hello_world.cgi program was unable to find
cgi-lib.pl. Note that when you said "./Library/cgi-lib.pl", you were
telling your script to grab cgi-lib.pl in the Library
directory which is a sub-directory of the directory hello_world.cgi
is in (./).
Well, the problem with this is that on some ISP's the system admins
have decided that all accounts are based on virtual servers. This
means that every account sees itself as the root server, when in
actuality, there is one root server which has aliases to each
account.
Virtual Servers are more secure for the ISPs, so they prefer them.
The use of Virtual Servers also allows you to have your own domain
name instead of the domain name of the ISP so they are also nice for
you. However, they can cause lots of problems when trying to install
scripts which need to talk to other files on the file system (like
hello_world.cgi needs to talk to cgi-lib.pl). Specifically, virtual
servers get kinda screwy when it comes to what path is the "real"
path.
Typically, the path that you see from the command line may be totally
different from what the web server sees when it runs. Thus, what
you may see as:
domainname/cgi-bin/hello_world.cgi
the web server sees as
/usr/local/etc/httpd/cgi-bin/hello_world.cgi
and when you tell it to require somethig like "./Library/cgi-lib.pl", the
web server may look for
/usr/local/etc/httpd/cgi-bin/Library/cgi-lib.pl
instead of
domainname/cgi-bin/Library/cgi-lib.pl
Of course, it won't find anything in this case. The solution is to ask
your sys admin what path you should use when loading files into your cgi
script. Another way to find out what path the web server is seeing
if you are using a UNIX server is to use the "pwd" command. You can
try adding these lines to your script.
#!/usr/local/bin/perl
print "Content-type: text/html\n\n";
print "Hello World";
$pwd = `pwd`;
print $pwd;
This should echo back the present working directory as seen by your web
server. This path will help you determine what you need to type in order
to get your script to access a supporting file like cgi-lib.pl. But
remember that you can always just work this out with your sys admin, that
is what she is there for! That is what you pay her to do!
What the Script Sees
Once I have successfully loaded cgi-lib.pl, I use it to make sure that my
CGI script is actually getting the information from the browser that it is
supposed to get from the browser.
Since the usage of cgi-lib.pl is covered in depth in the
chapter in Instant Web
Scripts with CGI/PERL and is one of the free chapters available from
the Scripts Archive, I am not going to explain its usage. If you are not
sure what &ReadParse is, just do some reading. It is a quick chapter and
pretty straight forward.
So I will add the usual lines to my little CGI script.
#!/usr/local/bin/perl
print "Content-type: text/html\n\n";
print "Hello World";
require ("./Library/cgi-lib.pl");
&ReadParse(*form_data);
foreach $incoming_form_variable (keys(%form_data))
{
print "$incoming_form_variable =
$form_data{$incoming_form_variable}\n";
}
So what did I add to my script. I simply added a small foreach loop
which goes through each of the incoming form variables stored in the
%form_data associative array created in the ReadParse subroutine of
cgi-lib.pl and printed out the name of the form variable and the value of
the form variable.
The usage of foreach, associative arrays, and the keys
function is covered in great detail in my Perl
Faq
However, there is one piece missing. I need to actually send some form
data to my script. Of course, I don't actually have a form frontend to
my script, so I will pass the script form data via a URL encoded string
like:
http://www.yourdomain.com/cgi-bin/test.cgi?fname=selena&lname=sol
When I do so, the result should look something like the following:
This little foreach loop is an invaluable tool when you want to check to
see what the script thinks its variables are. While debugging, you can
always dump in this foreach loop to zip through the current variables and
check to see what they are. It may be that you have 1) accidentally
overwritten a variable, 2) the script has lost some values for variables
you thought it had, or 3) the script never received variables that it
needs.
Often I forget to pass state information from page to
page via hidden variables. If you forget to add state info to every HTML
page, it is easy to lose it along the way. Most of the time, that state
info is crucial. So anytime you have a CGI which utilizes several screens
of info, you need to print out your variables when debugging to make sure
they are all getting passed back to the script.
Oh, and one more thing, you can also get a listing of the current
ENVIRONMENT variables by adding the following foreach loop:
foreach $environment_variable (%ENV)
{
print "$environment_variable = $ENV{$environment_variable}";
}
Advanced Error Hunting
Newtonian Methodology and the Nitty Gritty of Debugging
Sherlock Holmes and the Case of the Broken CGI Script
Advanced Error Hunting
|