cgitool - functions useful for CGI programming

version 2.1

Shiro Kawai (

Table of Contents

Copyright (C) 1998-2000 by Square USA Inc.

1. Overview

Cgitool is a collection of procedures useful to write cgi scripts in Scheme. It supports:

Changes from 1.0: The dependency on html-classes module is removed. Now cgitool doesn't require STklos. The document is rewritten in texinfo format, reflecting the change.

2. License

SQUARE USA Inc. hereby grants permission to use, copy, modify, and distribute this software and its documentation for any purpose, provided that existing copyright notices are retained verbatim in all copies.

In no event shall the authors or distributors be liable to any party for direct, indirect, special, incidental, or consequential damages arising out of the use of this software, its documentation, or any derivatives thereof, even if the authors have been advised of the possibility of such damage.

The authors and distributors specifically disclaim any warranties, including, but not limited to, the implied warranties of merchantability, fitness for a particular purpose, and non-infringement. this software is provided on an "as is" basis, and the authors and distributors have no obligation to provide maintenance, support, updates, enhancements, or modifications.

3. Install

The on-line version of this document is at

The current verision of cgitool is 2.1. It is available at

  1. ungzip+unter the package.
  2. stk Makefile.stk
  3. make install

4. API

4.1 Error page

Function: cgi:error format &rest args

Print out an error page in HTML (with HTTP header) and exit. The arguments format and args are passed to format to generate a message.

Function: cgi:report-error head msg obj

Print out an error page in HTML (with HTTP header) and exit. This function is set to the variable report-error, as a hook function to be called when an error is raised.

Note: simply loading cgitool sets a hook to report-error, and Scheme exits whenever an error is signalled. This action is convenient for CGI scripts, but not for interactive programming. If you load cgitool to your interactive Scheme session, reset report-error to #f (in snow) or tk:report-error (in stk).

4.2 Decoding query parameters

Function: cgi:parse-query-string &optional string

Parses url-encoded query string and returns a list of decomposed key and value lists. If string is provided, the function takes input from the string. Otherwise, it examines the environment variable REQUEST_METHOD. If it is "POST", it reads encoded string from stdin. Otherwise, it uses the value of the environment variable QUERY_STRING. This behavior is useful for most CGI scripts.


(cgi:parse-query-string "name=Shiro+Kawai&")
=> ((email "") (name "Shiro Kawai"))

(cgi:parse-query-string "name=a&name=b&name=c")
=> ((name "a" "b" "c"))

Function: cgi:parse-cookie &optional string

Parses encoded cookie string and returns a list of decomposed key and value lists. If string is provided, the function takes input from it. Otherwise, it use the environment variable HTTP_COOKIE.

The "new" format as of RFC2109 can be handled, although all additional attributes (attributes starts with "$") will be ignored in the current version.

Function: cgi:get-parameter-value name plist &key :default :error :multivalue :convert

Retrieve Scheme value(s) from the decoded query parameters or cookies.

name is a name of the parameter you want to retrieve, and plist is a list of parameters that cgi:parse-query-string or cgi:parse-cookie returns.

If a parameter associated with name is in plist, the function returns the value. The value is always a string unless you specify the :convert keyword argument, which must be a procedure taking one argument, in that case the function passes the retrieved value to the procedure and returns the converted value.

(cgi:get-parameter-value 'num (cgi:parse-query-string "num=453")
                         :convert string->number)
=> 453

If name is not found in plist, the function takes the following actions.

  1. If a keyword argument :default is specified, it is returned
  2. Otherwise, if a keyword argument :error is specified, call it as a procedure with one argument name.
  3. Otherwise, generates an html error page and exits.

If keyword argument :multivalue is true, the procedure returns list of values. Otherwise, the procedure returns a string, concatenating all the values with whitespace inbetween. When multivalue is true and :convert is specified, the conversion function is applied on each values.

(cgi:get-parameter-value 'name (cgi:parse-query-string "name=a"))
=> "a"

(cgi:get-parameter-value 'name (cgi:parse-query-string "name=a")
                         :multivalue #t)
=> ("a")

(cgi:get-parameter-value 'name (cgi:parse-query-string "name=a&name=b"))
=> "a b"

(cgi:get-parameter-value 'name (cgi:parse-query-string "name=a&name=b")
                         :multivaue #t)
=> ("a" "b")

(cgi:get-parameter-value 'name (cgi:parse-query-string "name=a&name=b")
                         :multivaue #t :convert string->symbol)
=> (a b)

4.3 Escaping special characters

Function: cgi:safe-html-string string

Copies string with replacing `unsafe' html characters to the escaped representation.

(cgi:safe-html-string "<a&b>")
=> "&lt;a&amp;b&gt;"

Function: cgi:safe-url-string string

Copies string with replacing `unsafe' URL characters to the escaped representation, as specified in RFC2068.

(cgi:safe-url-string "1 + 2 = 3")
=> "1%20%2b%202%20%3d%203"

4.4 HTTP header

Function: cgi:write-header &key :content-type :cookies :location

Generates a CGI header string and writes it out to stdout.

Keyword argument :content-type specifies Content-Type header. Its default is "text/html".

Keyword argument :location specifies location header of http, to redirect user's request to new location. This option supercedes content-type option.

Keyword argument :cookies specifies "cookies" to be sent to the client by Set-Cookies header. It is a list of the following form:

   ((NAME VALUE [keyword attribute ...])
    ... )

Keyword-value pairs are for per-cookie attribute values as defined in RFC2109 (new specification). It also supports "old" cookie format in original Netscape proposal ( To make two standard coexist, VALUExs are not quoted.

Following attribute specifications (keyword-value pair) are recognized. If the attribute is only available either new spec or old spec, it is marked as "(new)" or "(old)" in the table. If you mix new-spec-only attribute and old-spec-only attribute, the result will be unknown. Note that if you want to use new specification, you must specify "Version" attribute explicitly (it should be 1).

   :comment STRING    Comment attribute.  (new)
   :domain STRING     Domain attribute.
   :max-age INTEGER   Max-Age attribute.  (new)
   :path STRING       Path attribute.
   :secure BOOLEAN    Secure attribute.
   :version INTEGER   Version attribute.  (new)
   :expires DATE      Expires attribute.  (old)
      If DATE is integer, it must be a seconds from
      Jan 1, 1970 0:0:0 GMT.  If DATE is a string, it must be
      a formatted date string ("Wdy, DD-Mon-YY HH:MM:SS GMT").

4.5 High level macro

Macro: cgi:let (argument-spec ...) body ...

This macro provides a convenient way to write a CGI script. It retrieves a query-string parameter and cookie values from environment variable QUERY_STRING and HTTP_COOKIE, respectively, and bound it to local variables according to argument-specs, then executes body.

argument-spec must be in one of the following formats:

cgi:let looks for the parameter from query parametres whose name is the same as the symbol, and binds its value to the symbol. If named parameter is not found, cgi:error is called. The special cases are the symbol &queries and &cookies. The symbol &queries is bound to a list which cgi:parse-query-string returns, and &cookies is bound to a list which cgi:parse-cookie returns.
(symbol option ...)
cgi:let retrieves a parameter value according to options, and binds it to symbol. Possible options are:
:name name
Specifies parameter name. Default is the same as symbol.
:source source
source might be either :query or :cookie. If it is :cookie, the value is retrieved from cookie instead of query string. The default is ::query.
:convert proc
:default default-value
:error error-proc
:multivalue boolean
Given to cgi:get-parameter-value.

5. Examples

This CGI script just gets parameter "name" and prints out a greeting.

#! /usr/local/bin/snow 
(require "cgitool")

(cgi:let (name)
  (format #t "<html><head><title>Test</title></head>\n")
  (format #t "<body>Hello, ~a</body></html>" name))
(exit 0)

This CGI script accepts parameter "year" and "month", and returns calender using unix "cal" command.

#! /usr/local/bin/snow 
(require "posix")
(require "cgitool")

;; Default month and year
(define *this-year-and-month*
  (let* ((tmvec (posix-tm->vector
                  (posix-localtime (posix-time))))
         (yy    (+ (vector-ref tmvec 5) 1900))
         (mm    (+ (vector-ref tmvec 4) 1)))
    (if (< yy 1970)          ;; year 2000 problem...
        (cons (+ yy 100) mm)
        (cons yy mm))))

;; Make sure parameter gives correct string
(define (convert-year str)
  (or (string->number str) (car *this-year-and-month*)))
(define (convert-month str)
  (or (string->number str) (cdr *this-year-and-month*)))

;; Process request
(cgi:let ((year  :default (car *this-year-and-month*) :convert convert-year)
          (month :default (cdr *this-year-and-month*) :convert convert-month))
  (let ((cal (call-with-input-file
                 (format #f "| cal ~a ~a" month year)
               (lambda (port) (port->list read-line port)))))
    (format #t "<html><head><title>Calendar ~a/~a</title></head>\n" year month)
    (format #t "<body><pre>")
    (for-each (lambda (line) (display line) (newline)) cal)
    (format #t "</body></html>\n"))

;; All done.
(exit 0)


Jump to: c


  • cgi:error
  • cgi:get-parameter-value
  • cgi:let
  • cgi:parse-cookie
  • cgi:parse-query-string
  • cgi:report-error
  • cgi:safe-html-string
  • cgi:safe-url-string
  • cgi:write-header

  • This document was generated on 30 June 2000 using texi2html 1.56k.