;;; NCSA's WWW Common Gateway Interface -- script-side code -*- Scheme -*- ;;; Copyright (c) 1995 by Olin Shivers. ;;; See http://hoohoo.ncsa.uiuc.edu/cgi/interface.html for a sort of "spec". ;;; Imports and non-R4RS'isms ;;; switch (control structure) ;;; getenv read-string (scsh) ;;; error ;;; parse-html-form-query (parse-html-forms package) ;;; This file provides routines to help you write programs in Scheme ;;; that can interface to HTTP servers using the CGI program interface ;;; to carry out HTTP transactions. ;;; Other files/packages that will be of help: ;;; rfc822 For reading headers from entities. ;;; uri url For parsing and unparsing these things. Also for generally ;;; URI-decoding strings. ;;; htmlout For generating HTML output. ;;; About HTML forms ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; This info is in fact independent of CGI, but important to know about, ;;; as many CGI scripts are written for responding to forms-entry in ;;; HTML browsers. ;;; ;;; The form's field data are turned into a single string, of the form ;;; name=val&name=val ;;; where the and parts are URI encoded to hide their ;;; &, =, and + chars, among other things. After URI encoding, the ;;; space chars are converted to + chars, just for fun. It is important ;;; to encode the spaces this way, because the perfectly general %xx escape ;;; mechanism might be insufficiently confusing. This variant encoding is ;;; called "form-url encoding." ;;; ;;; If the form's method is POST, ;;; Browser sends the form's field data in the entity block, e.g., ;;; "button=on&ans=yes". The request's Content-type: is application/ ;;; x-www-form-urlencoded, and the request's Content-length: is the ;;; number of bytes in the form data. ;;; ;;; If the form's method is GET, ;;; Browser sends the form's field data in the URL's part. ;;; (So the server will pass to the CGI script as $QUERY_STRING, ;;; and perhaps also on in argv[]). ;;; ;;; In either case, the data is "form-url encoded" (as described above). ;;; ISINDEX queries: ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; (Likewise for ISINDEX URL queries from browsers.) ;;; Browser url-form encodes the query (see above), which then becomes the ;;; ? part of the URI. (Hence the CGI script will split the individual ;;; fields into argv[].) ;;; CGI interface: ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; - The URL's part is assigned to env var $QUERY_STRING, undecoded. ;;; - If it contains no raw "=" chars, it is split at "+" chars. The ;;; substrings are URI decoded, and become the elts of argv[]. You aren't ;;; supposed to rely on this unless you are replying to ISINDEX queries. ;;; - The CGI script is run with stdin hooked up to the socket. If it's going ;;; to read the entity, it should read $CONTENT_LENGTH bytes worth. ;;; - A bunch of env vars are set with useful values. ;;; - Entity block is passed to script on stdin; ;;; script writes reply to stdout. ;;; - If the script begins with "nph-" its output is the entire reply. ;;; Otherwise, when it replies to the server, it sends back a special ;;; little header that tells the server how to construct the real header ;;; for the reply. ;;; See the "spec" for further details. ;;; (cgi-form-query) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; Return the form data as an alist of decoded strings. ;;; So a query string like "button=on&reply=Oh,%20yes" becomes alist ;;; (("button" . "on") ("reply" . "Oh, yes")) ;;; This only works for GET and POST methods. (define (cgi-form-query) (let ((request-method (getenv "REQUEST_METHOD"))) (cond ((string=? request-method "GET") (parse-html-form-query (getenv "QUERY_STRING"))) ((string=? request-method "POST") (let ((nchars (string->number (getenv "CONTENT_LENGTH")))) (parse-html-form-query (read-string nchars)))) (else (error "Method not handled."))))) ; Don't be calling me.