89 lines
3.9 KiB
Scheme
89 lines
3.9 KiB
Scheme
;;; 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".
|
|
|
|
;;; 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 <name> and <val> 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 <search> 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
|
|
;;; ?<search> part of the URI. (Hence the CGI script will split the individual
|
|
;;; fields into argv[].)
|
|
|
|
|
|
;;; CGI interface:
|
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
;;; - The URL's <search> 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. (URL above)
|
|
|
|
|
|
;;; (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.
|