Copyright © 2003-2005 Gene Michael Stover. All rights reserved. Permission to copy, store, & view this document unmodified & in its entirety is granted.
The examples I have here worked fine when I had clisp on both my development systems & on lisp-p.org, but not that there are different Lisps on the development systems & no Lisp on lisp-p.org, they aren't reliable. It's really tough to use Lisp with CGI portably! So the examples might not work.
gms.freeshell.org doesn't have a Lisp installed. At least, it doesn't have clisp. These Lisp/CGI programs will fail on that system. So I have hard-coded my CyberTiggyr.COM web site into the URL to the CGI programs. So if you are viewing this page on gms.freeshell.org or on lisp-p.org, the links to the CGI programs will take you to my CyberTiggyr.COM site. I apologize for any shock this may cause (if you even notice it). My main web site is http://CyberTiggyr.COM/gene, so everything is on the up-&-up (unless CyberTiggyr.COM happens to be down).
test0000.cgi is about the most basic Lisp/CGI program possible. It assumes clisp is present. It prints some hard-coded strings to *standard-output* to make a basic, hard-coded HTML document.
test0000.cgi uses format to print each line to *standard-output*. It does nothing else.
The source is test0000.cgi.sh.
test0002.cgi prints the standard (or at least, the common) CGI environment variables & their values. It relies on clisp's probably non-standard function system::getenv.
It's also useful to see the QUERY_STRING when one is present, such as in test0002.cgi?a=1;b=2;c=3.
The source is test0002.cgi.sh.
test0004.cgi assumes you've invoked it with POSTed data. To send it POSTed data, use the HTML page with a form in it at form0004.html.
That small experiment shows that the default encoding is application/x-www-form-urlencoded & that said encoding, just like a regular URL with parameters, divides the (argument, value) pairs with ampersands (&). The POSTed form data is one long line.
I do not see a CGI environment variable that explicitly tells the CGI program the encoding form of the POSTed data. Presumably, the CGI program & the form which tells the browser how to encode the data must be written with the same assumption about data encoding.
It also looks like semicolons (;) are encoded, so they could be used as parameter separators, except that I don't see how to force the browser to use them that way when it posts data.
The source for the form is form0004.html, & the source for the CGI program is test0004.cgi.sh.
Let's write a Lisp library for CGI. The first test program for it should just try to load the library. That's test0010.cgi. It should print a message that the library file exists & another message that the test program could load the library.
The source is test0010.cgi.sh.
The first thing the library needs is a list of the CGI environment variables. Our new library has a non-exported variable, cybertiggyr-cgi::*envvars*, that holds the names of the environment variables in a list, & test0011.cgi prints that list.
cybertiggyr-cgi::*envvars* isn't exported because client programs probably won't need it, but it's nice that test programs can still access it.
The source is test0011.cgi.sh.
The CGI library needs a function to obtain the query string from the appropriate location, whether it's the URL or the input stream.
When the Web client sends data, it has two choices according to the HTTP protocol: GET & POST. The GET technique attaches the data to the URL. The POST technique sends the data in the HTTP stream, which the HTTP server connects to the CGI program's input stream.
The CGI library will provide one function to retrieve the data. That function is cybertiggyr-cgi::get-query-string & is not exported. It will cache the query string in a variable, *query-string*, which also is not exported.
test0012.cgi demonstrates the get-query-string function. You can give it parameters in the URL or as POSTed data. It does not parse the query string into arguments & their values. An URL that has a query string for test0012.cgi is test0012.cgi?a=1. A form which sends data to test0012.cgi by POSTing it is form0012.html.
The source for the form is form0012.html, & the source for the CGI program is test0012.cgi.sh.
Now we need a function to parse the query string into (parameter, value) pairs & returning a list of the pairs. While we're at it, we should make a function that eats a list of pairs & encodes them into a query string.
Encoded parameters are most commonly separated by ampersands (&), but it is also possible & recommended (in my opinion) to separate them with semicolons (;). So the CGI library will have a string that contains the possible parameter separator characters. The decoder function will allow parameters to be separated by any of those characters. The encoder function will separate parameters with the first character in that string. The string is in the non-exported symbol *separators*. Test programs might need to access it, & some client libraries might want to alter it. It will default to ``;&'' (semicolon, ampersand).
The decoding & encoding functions are decode-url & encode-url, respectively. They are not exported, but test programs might need to access them.
If I have a list alst of (attribute, value) pairs, then (equal (decode (encode alst))) should always be true, but the reverse opteration, (equal (encode (decode some-string))), might not be true because there are more than one ways to encode a query string.
test0015.cgi URL-encodes a hard-coded list of parameters. test0016.cgi does the same demonstration but with a more complex list of parameters.
Now we need a non-exported function to decode an URL, & it will probably be built from a non-exported function to decode an URL-encoded string. test0018.cgi tests the function to decode some hard-coded, URL-encoded strings.
The source is test0015.cgi.sh.
The CGI library is unfinished at this time1. It's even untested. Nevertheless, the source is here.
Gene Michael Stover 2008-04-20