HTTP (HyperText Transfer Protocol) is the protocol that Web browsers use to talk to Web servers. The official specification for the HTTP standard is available on the W3 Consortium web server at:
http://www.w3.org/pub/WWW/Protocols/
Some more readable introductions can be found on the Yahoo HTTP page at:
http://www.yahoo.com/Computers_and_Internet/Internet/World_Wide_Web/HTTP/
CGI (Common Gateway Interface) is a protocol used by Web servers to run server programs. Scripts that support the CGI protocol are sometimes called "CGI scripts"; this leads to the unfortunate misperception that CGI is a language of its own.
The classic information on CGI is available on the NCSA server at:
http://hoohoo.ncsa.uiuc.edu/cgi/
If you haven't read this, read it now. If it doesn't click for you, you can check the Yahoo CGI page at:
http://www.yahoo.com/Computers_and_Internet/Internet/World_Wide_Web/
CGI___Common_Gateway_Interface/
(All one URL, leave out the line feed).
Try also the following URL for CGI programming in Perl:
http://www.perl.com/perl/faq/perl-cgi-faq.html
If you still don't get it, try one of the "get-rich-quick-by-writing-CGI-scripts" books at your local bookstores.
One of the big differences between UNIX and Win32 platforms is that on Win32 there's a difference between text or ASCII files and binary file. To return a graphics file, you need to specify that the file is a binary file, and that the standard output stream should accept binary data. Try something like this:
$MY_FILE_NAME = 'Penelope.jpg'; $CHUNK_SIZE = 4096; open( MY_FILE, "<$MY_FILE_NAME" ) or die( "Can't open $MY_FILE_NAME: $!\n" ); print "Content-type: image/jpeg\r\n"; print "\r\n"; binmode( MY_FILE ); # These are crucial! binmode( STDOUT ); while ( $cb = read( MY_FILE, $data, $CHUNK_SIZE ) ) { print $data; } close( MY_FILE );
PerlIS scripts need to add some extra header information, as noted below.
Scripts running under PerlIS are a lot like "nph" scripts, as defined in the CGI/1.1 specification (see question 7.2). You have to specify the HTTP response status line as well as all headers for the response.
Here's a sample that works under PerlIS:
print <<"END"; HTTP/1.0 200 OK Content-Type: text/html <HTML> <HEAD> <TITLE>PerlIS Response</TITLE> </HEAD> <BODY> This is a PerlIS response. </BODY> </HTML> END
If you don't add the HTTP status line, as above, the browser will assume that it is talking to an HTTP/0.9 server (the HTTP spec says that the difference between a 1.0 and an 0.9 server is the presence of the status line, and that good browsers should accept 0.9 responses). It will then try and treat your response headers as part of the HTML you are returning, so your headers will show up in the browser window, which you probably don't want.
There's a misperception that if you don't add the HTTP status line, PerlIS will add one for you, plus a Content-Type header. This is false, and can be checked with a little sockets coding.
You should probably review the HTTP spec (see question 7.1) if you're going to do any complicated PerlIS programming.
Philip Nelson has written a good exposition on the differences between PerlIS and CGI (http://www.dct.com/~nelsonp/IISHeader.html).
PerlIS sets an environment variable, PERLXS, for scripts that are executed under PerlIS. The following script will run as a perl.exe CGI script or as a PerlIS script. It checks the environment variable to see if it needs to print out a status line.
print "HTTP/1.0 200 OK\r\n" if $ENV{PERLXS} eq "PerlIS"; print <<"END"; Content-Type: text/html <HTML> <HEAD> <TITLE>Both</TITLE> </HEAD> <BODY> This script will work with perl.exe and PerlIS. </BODY> </HTML> END
The CGI.pm module works with Perl for Win32. It's available at
http://www-genome.wi.mit.edu/ftp/pub/software/WWW/cgi_docs.html
Note that you need to change the $OS variable in CGI.pm before it will work correctly with Windows NT or Windows 95.
[Any other CGI modules work with Perl for Win32? -ESP]
You can use redirection to point the client browser to another file or script, usually in a way that's invisible to the user. It requires using the Location header as well as a special HTTP code, if you're using PerlIS. The following code redirects the browser to a simple text file.
print "HTTP/1.0 303 See Other\r\n" if $ENV{PERLXS} eq "PerlIS"; print <<"END"; Content-Type: text/plain Location: /text/mytextfile.txt END
Note that, if CGI (perl.exe) is used, the _server_ will retrieve the location and send it to the browser, so the browser thinks that the content is from the URL of your script. If PerlIS is used, the _browser_ has to retrieve the content itself, and the URL of the resource you redirected to will be displayed to the user.
If you're using PerlIS, you should check out HTTP status codes 301 (Moved Permanently), 302 (Moved Temporarily), and 303 (See Other) to see which is most appropriate to your application. See question 7.1.
Cookies are packets of data that a server can give to a client to identify the client in future interactions. They were first defined by NetScape, and the definition of cookies can be found at:
http://home.netscape.com/newsref/std/cookie_spec.html
You can set the cookie as one of the CGI (for PerlIS, HTTP response) headers in your file. You can get the cookie, if one is passed, throught the HTTP_COOKIE environment variable. Here's a simple script that counts how many times a user has accessed a page:
$cookie = $ENV{HTTP_COOKIE}; $count = ( $cookie ) ? (split( "=", $cookie ))[1] : 0; $count++; # counting this visit. if ( $count > 1 ) { $welcome = "Welcome back for visit #$count to this page!"; } else { $welcome = "Welcome to my page for the first time!"; } $cookie = "COUNT=$count"; print "HTTP/1.0 200 OK\r\n" if $ENV{PERLXS} eq "PerlIS"; print <<"END"; Content-Type: text/html Set-Cookie: $cookie <HTML> <HEAD> <TITLE>Cookie Sample</TITLE> </HEAD> <BODY> $welcome </BODY> </HTML> END
To set persistent cookies, define domains, specify expiration dates, etc., refer to the specification above.
It's not, in general, possible to get the e-mail address of a user without asking them for it. If you need an e-mail address, provide the user with a form to fill in an address.
The HTTP specification (see question 6.2) defines an HTTP request header , "From", that can contain the e-mail address of the user making the connection. Your script can retrieve it using the environment variable HTTP_FROM. However, it's rarely provided and can't really be counted on.
There are all kinds of sneaky ways to determine where requests come from -- like checking the IP address that was used to connect -- but you can't figure out the e-mail address of the user this way.
Generally, it's considered a violation of the user's privacy to get their e-mail address without their knowledge. Perhaps that's why it's so difficult.
There are several CGI script archives on the Web. You may not be able to find exactly the script you want, but you will probably find something that can be adapted to your needs.
Two of the most famous script pages are:
[Others? -ESP]
Note that most script archives have UNIX-targeted scripts, and you may have to make some adaptations to them to make them run (see question 5.7).
This is one of the most common questions on the Perl-Win32-Users list. Occasionally it's phrased more like "I have a program to write. Here are the specs. Please e-mail it to me by Friday." Hopefully the reader can understand why these messages are usually answered with flames or ignored.
The hard way to test your CGI programs from the command line is to set up environment variables and a standard input stream just like a Web server would (see the CGI 1.1 specification for more details on this -- question 7.2).
The easy way is to use CGI.pm, the Perl module for CGI programming. It provides an easy mechanism to run CGI programs, with arguments, from the command line.
You are using PerlIS as your Perl interpreter on an IIS Web server (this is set up by default by the install.bat program), but you're not outputting an HTTP status line. See question 7.4 for details on how to fix your problem.
Your Web server has been misconfigured. It doesn't know that it should execute your Perl program, so it's just returning it to the browser. See section 6 of this document for details on how to configure your particular Web server to know that Perl scripts should be executed.