Getting a CGI script to work locally on my Mac

simX

Unofficial Mac Genius

I've been trying to make a perl CGI script for my website, but I don't have any UNIX server to test it on, so I decided I might as well just test in on my iBook since it has perl installed.

The problem is that when I set it up (I'm following the www.htmlgoodies.com CGI primers tutorial), it doesn't work correctly. In OmniWeb and Mozilla, when the HTML page accesses the cgi script, it just displays the CGI script contents on the page instead of running the script.

I can't figure out what the problem is: I made sure that the path to perl was correct, and that the cgi script was executable, but I still cannot make it work. Is there any way to get this to run locally?

<!-- Here's the HTML page (basically directly from the HTMLgoodies.com tutorial):

<HTML>
<HEAD>
<TITLE>
Guestbook Script
</TITLE>
</HEAD>
<BODY BGCOLOR="#FFFFFF">
<FORM METHOD="post" ACTION="cgi-bin/guestbook.pl">
<INPUT NAME="name" SIZE=50 TYPE="text">
<B>Your Name</B><BR>
<INPUT NAME="email" SIZE=50 TYPE="text">
<B>Your E-Mail Address</B><BR>
<INPUT TYPE="hidden" NAME="submitaddress" VALUE="simX@mac.com">
<B>Write to me below:</B>
<P>
<TEXTAREA NAME="feedback" ROWS=10 COLS=50>
</TEXTAREA>
<P>
<CENTER>
<INPUT TYPE=submit VALUE="SEND">
<INPUT TYPE=reset VALUE="CLEAR">
</CENTER>
</FORM>
</BODY>
</HTML>

And here's the CGI script:

#!/usr/bin/perl

# That is the path to PERL just above It MUST be first in the script

# The following accepts the data from the form


if ($ENV{'REQUEST_METHOD'} eq 'POST') {


read(STDIN, $buffer, $ENV{'CONTENT_LENGTH'});


@pairs = split(/&/, $buffer);

foreach $pair (@pairs) {
($name, $value) = split(/=/, $pair);
$value =~ tr/+/ /;
$value =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/eg;

$FORM{$name} = $value;
}



# The following sends the email

open (MESSAGE,"| /usr/sbin/sendmail -t");
# the default for the above is /usr/lib/sendmail

print MESSAGE "To: $FORM{submitaddress}\n";
print MESSAGE "From: $FORM{name}\n";
print MESSAGE "Reply-To: $FORM{email}\n";

print MESSAGE "Subject: Feedback from $FORM{name} at $ENV{'REMOTE_HOST'}\n\n";
print MESSAGE "The user wrote:\n\n";
print MESSAGE "$FORM{feedback}\n";
close (MESSAGE);

&thank_you;
}




#The following creates the Thank You page display

sub thank_you {

print "Content-type: text/html\n\n";
print "<HTML>\n";
print "<HEAD>\n";
print "<TITLE>Thank You!</TITLE>\n";
print "</HEAD>\n";
print "<BODY BGCOLOR=#FFFFCC TEXT=#000000>\n";
print "<H1>Thank You!</H1>\n";
print "\n";
print "<P>\n";
print "<H3>Your feedback is greatly appreciated.<BR>\n";
print "<P>\n";
print "</BODY>\n";
print "</HTML>\n";
exit(0);
} -->

You can download the HTML code and CGI script here:

http://homepage.mac.com/simx/.Public/guestbook.html

http://homepage.mac.com/simx/.Public/guestbook.pl


I would post it, but Apple's HomePage iTools feature doesn't seem to be running on UNIX (or it blocks CGI scripts from running), so it won't work there. Can anybody see if they can get this to work or show me what's wrong? (And, can anybody tell me if you CAN run cgi scripts on HomePage? That would be awesome.)

By the way.. how do I stop the forum from automatically interpreting the HTML. I wanted to post the text, not have MacOSX.com interpret it.
 

azosx

Banned
Maybe this URL will help you configure Apache for use with CGI.

http://httpd.apache.org/docs/howto/cgi.html

It sounds like you need to install the CGI module to interpret your scripts.

I'm not familiar with Apache on OS X so perhaps that tutorial will not help.

If you need further help, I can configure Apache in Linux and see what the problem is exactly.

Let me know.
 

vertigo

Swollen Member
double check that you have cgi enabled in your httpd.conf file (/etc/httpd/httpd.conf)

you'll need to add ExecCGI to your Options directive in the appropriate &#60Directory&#62 block. it should look something like this:

&#60Directory "/Library/WebServer/Documents"&#62
Options Indexes FollowSymLinks MultiViews ExecCGI
...
&#60/Directory&#62

you'll also need to make sure the AddHandler line for .cgi is uncommented, it should look like this:

AddHandler cgi-script .cgi

then of course restart httpd

p.s. to get the html brackets, escape them. left is 60, right is 62. check out http://www.bbsinc.com/symbol.html
 

simX

Unofficial Mac Genius
Isn't it the command-line utility "perl" that interprets the CGI scripts, though? What does Apache have to do with this – I thought that was just a web server, which I don't need since all the files are locally on my hard drive.

:confused:
 

vertigo

Swollen Member
apache isn't interpreting your perl script, perl is (thus the #! line at the top pointing to perl). but apache does have to know when to treat the requested file as a CGI, which is why you need the AddHandler. the ExecCGI option is more of a security thing, since you may not want to allow CGI execution from everywhere. apache also has to pass in environment stuff, and redirect output back to the client, etc. why do you think you can read from STDIN and print to STDOUT and have it all transparently routed to/from the client's browser? :) gg apache.
 

simX

Unofficial Mac Genius
Hrm.

I put this at the bottom of the file:

<Directory /Users/simmy/Sites/smbxas/cgi-bin>
Options +ExecCGI
</Directory>

And I uncommented the AddHandler script so it looks like this:

AddHandler cgi-script .cgi

I restarted my Mac (or is there some command I need to do for it to reload the new file?), and it still doesn't work.

Any more suggestions?

I still don't understand what Apache has to do with it. Doesn't the browser I use look at the HTML, see that it wants a CGI script, calls the perl command and tells it to execute the specified CGI script, and then perl gives the browser what to display. Where exactly does Apache come in on this?
 

azosx

Banned
Maybe I missunderstood but you're trying to serve a webpage from your home computer running OS X right?

If so, you are serving web pages with the Apache web server built into OS X.

Apache needs to know how to handle the perl scripts you are trying to incorporate into your website.

Without the CGI module, that will pass it's function along to Perl, it's just going to serve your perl script as raw data or text.

It doesn't know how to work with Perl on your computer without the module telling it what to do.

I don't think what the other user described above will work without the CGI module installed.
 

vertigo

Swollen Member
azosx - the CGI module is installed by default in apache. you can look in httpd.conf and see that mod_cgi is added.

simx - the ExecCGI should go _inside_ the Directory block, not simply at the end of the file. if you're using pico, hit control-w and search for ExecCGI. the first match should be right below the Directory tag and right above the Options directive. just add ExecCGI to that list. mine looks like this:

Options Indexes FollowSymLinks MultiViews ExecCGI

make sure you save the file (you'll need sudo), and just go into the Sharing control panel, turn off web sharing, and turn it back on.

also, make sure your filename ends with .cgi, not .pl. or add .pl to the AddHandler line if you want. i find .cgi a bit more intuitive.
 

dsnyder

Registered
There's no reason to muck about with the Apache config files at all. The default setup has everything SimX needs. All you need to do is activate web sharing, put your scripts in /Library/WebServer/CGI-Executables and chmod to make them executable. Now point your browser to http://localhost/cgi-bin/guestbook.pl or whatever the name of the actual script is.

To answer your question as to why you need Apache: web browsers can't execute files on their own. This is a GOOD thing, for security reasons. Think about it, someone could put a link on a page like this:

file:///bin/rm -rf /

and wipe out your disk. OK, maybe that's not a good example because the arguments would probably make it a misformed URL, but you get the idea. It's to keep malicious web site operators from duping people into unknowingly running potentially damaging stuff on their computers.
 

simX

Unofficial Mac Genius
Hrm. I did what dsnyder said and now I'm just getting a 500 error -- internal server error.

Am I missing something?

Update: Neeeeevermind. The perl script had an error. :p

Q: Where's the perl error log?
 

dsnyder

Registered
HTTP 500 errors usually indicate that the script died before it even got the chance to send an HTTP header.

perl doesn't keep it's own error log as far as I know, but Apache will keep track of errors generated by Perl scripts run under CGI. Look in:
/var/log/httpd/error_log

I don't think this is visible from the finder, so you'll need to look at it from the terminal (let me know if you need help with this).

When developing debugging cgi scripts, I find it useful to keep a terminal windows open with:
tail -f /var/log/httpd/error_log
running. This way I can see the errors come up as they happen.

You can also try running the script from the command line to see if it outputs what you expect.

Another uesful tidbit for debugging, put the following line near the top of your perl script:
use CGI::Carp 'fatalsToBrowser';
And error messages from Perl will be displayed directly in your browser.

Report any errors you find in the log here and I'm sure someone can help you straighten them out.
 

dsnyder

Registered
actually, I just downloaded the script and took a look at it. I noticed a couple of things:

The script won't do anythingn without POST data. So, if you try to access http://localhost/cgi-bin/guestbook.pl it won't do anything on it's own. You will have to access it from the form instead.

Also, the script uses 'sendmail'. As far as I know, sendmail doesn't work right in the default install of OS X, so you may have to jump through some hoops to get that working (I have no idea how to do this). Since the script doesn't do any sort of error handling if sendmail isn't working, and the HTTP header doesn't get sent until after the email, it could be that the script is failing at the sendmail part, which could explain the 500 error.

A big problem with the script is that it gets the "To" address from a hidden field in the form. This leaves it wide open for use a Spam relay. Anyone could post any value for submitaddress and use your script to send email to anyone they like. It would be much better to hard-code the "To" address right in the script, so no one can misuse the form. Some kind of check on the length of the body would probably be nice as well, also to limit misuse.
 
Top