LispCMS Guide

Table of Contents


Next: , Previous: (dir), Up: (dir)

LispCMS Guide

This guide is for LispCMS revision 42 which is a Common Lisp web development framework.

Copyright © 2006 Bram Geron.

Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.2 or any later version published by the Free Software Foundation; with no Invariant Sections, with the Front-Cover Texts being “LispCMS Guide,” and with the Back-Cover Texts as in (a) below. A copy of the license is included in the section entitled “GNU Free Documentation License.”

(a) The FSF's Back-Cover Text is: “You have freedom to copy and modify this GNU Manual, like GNU software. Copies published by the Free Software Foundation raise funds for GNU development.”

--- The Detailed Node Listing ---

Quick Start

Reference

Server Layer

Copying This Manual


Next: , Previous: Top, Up: Top

1 Invoking LispCMS

LispCMS isn't invoked in the way a standard program is. Instead, you make it listen on a special port and Apache will send requests via mod_lisp to LispCMS.

Although I like starting LispCMS through SLIME better, this is how you can invoke LispCMS when you have installed CMU Common Lisp:

     lisp -load (path to LispCMS)/src/loader.lisp

You must also set up mod_lisp to connect to LispCMS's port 3000 at requests...

     LispServer 127.0.0.1 3000 "local"
...

and you must set up Apache to use mod_lisp at some paths:

     <Location /cms>
         SetHandler lisp-handler
     </Location>
     
     <Location /rc>
         SetHandler lisp-handler
     </Location>

You can make LispCMS listen on a different port by changing +apache-port+ in src/base/server.lisp.

That should get you working. If you still have problems installing/using mod_lisp or LispCMS, contact me.

More details of the interaction between Apache and Lisp can be found on the mod_lisp web site.


Next: , Previous: Invoking LispCMS, Up: Top

2 About

2.1 About LispCMS

LispCMS is a web development framework in and for Common Lisp: with LispCMS you should be able to make web applications easily and quickly.

LispCMS a set of files loadable via ASDF. After loading LispCMS there is a package org.brgr.lispcms with which you can build your application.

LispCMS is a server for mod_lisp: LispCMS uses Apache and mod_lisp to serve web pages.

HTTP requests come in via Apache, Apache and mod_lisp parse them and mod_lisp passes the parsed request to (usually) port 3000; LispCMS listened on that port, handles the request and via mod_lisp and Apache sends it back to the browser.

See Quick Start, if you quickly want to be introduced to LispCMS. See Reference, for well-documented LispCMS functionality that can make the life of developers easier.

Most of the source code of LispCMS is under the GNU General Public License.

2.1.1 History

LispCMS started off as a hobby project, purely to learn Common Lisp better. Because the original developer liked PHP in that you can quickly make a small application with a UI (User Interface) in HTML and it would be portable and usable from any computer, he wanted to continue coding that way, and LispCMS was born.

After adding files and directories, mimicing boundp.net, the development quickly went in the direction of web application framework. Now it is quite usable to create nice-looking complex applications with little code. With less code, you have less room to make bugs. Still, LispCMS tries not to constrain the developer in any way, for example by limiting user permissions to a small number of predefined values.

2.1.2 Target audience

LispCMS was written with application developers in mind. Alhough it was originally intended to be a CMS (Content Management System) in Lisp, much like the PHP PHP-Nuke and Joomla, now the main target is letting developers develop code quickly, using Lisp's macro's wherever it would be handy.

2.1.3 Way of development

Like most Open Source software, LispCMS is developed bottom-up. You can use low-layered functionality just fine without having to use more advanced functionality.

For an overview of the features, See Reference.

2.2 About the docs

This chapter is a reference for most of LispCMS's documented functionality. It documents the most important things of LispCMS. If you want to know about really all of LispCMS, you should look at the source code.

The things inside each section have been sorted in order of revelance, in my opinion.

This Guide assumes knowledge of Common Lisp and HTML, and knowledge of how HTTP works in general.

Note that where optional parameters can be specified in a function/method, their defaults are not always shown. You can assume that they have sensible defaults, or look at the source to be positive.

2.3 About the code

Please note that all of LispCMS's symbols are in package org.brgr.lispcms, but none of them are exported currently. If you want to use them, use `(in-package :org.brgr.lispcms)' once and let all your symbols be in org.brgr.lispcms, or put `org.brgr.lispcms::' before all LispCMS symbols.

Also note that sometimes there is documentation of some part of LispCMS in the source code file, and that often there are docstrings.

You can find what source code files implement the functionality of a section at the bottom of that section.

Feel free to adapt the source code to your wishes, that's what LispCMS was made for.


Next: , Previous: About, Up: Top

3 Quick Start

This chapter provides some examples to get you coding as fast as possible. I advice you just try to install it, and run each example to see the results.

Please note that all of LispCMS's symbols are in package org.brgr.lispcms, but none of them are exported currently. If you want to use them, use `(in-package :org.brgr.lispcms)' once and let all your symbols be in org.brgr.lispcms, or put `org.brgr.lispcms::' before all LispCMS symbols.


Next: , Previous: Quick Start, Up: Quick Start

3.1 Setting up LispCMS

Before you can use LispCMS, you must of course set it up.

You can check if all is right by visiting http://localhost/cms, you should see a directory listing with a few virtual files in it.


Previous: Setting up LispCMS, Up: Quick Start

3.2 Introduction to LispCMS

3.2.1 Trivial things in LispCMS

LispCMS works with a virtual file system, in which you add and modify files with Lisp commands. You use this virtual file system to create your application in.

First, we must make sure that we're in the LispCMS package:

     (in-package :org.brgr.lispcms)
Adding a file

You can add files with with-cms-address. Those files will then show up in the http://localhost/cms directory listing.

     (with-cms-address ("/hello-world")
       (princ "Hello, world!"))

If you would now visit http://localhost/cms/hello-world, you would see "Hello, world!" in your browser.

Having nice HTML output

LispCMS uses cl-who to let you easily output HTML. You can use style-page for that, and it will also automatically enter the right <html>, <head>, etc. tags to make your page valid (X)HTML. And, you get a shiny new LispCMS banner on top :o)

     (with-cms-address ("/hello-world")
       (style-page
         (:p (:b "Hello")
             ", world!")))

Just try it out to see what it looks like.

See Styles, if you want to know the exact HTML outputting syntax.

Adding nice icons

With LispCMS you don't need to remember your image file paths: LispCMS does that for you, you just remember a handy tag. By default, LispCMS loads a bunch of icons at startup. Icons can often clarify a page.

You can get an icon path with (get-rc :image (tags)), you can set an icon for the directory listing with :icon in with-cms-address. You can print the HTML for an icon with (print-rc-image (tags)).

     (with-cms-address ("/hello-world" :icon (get-rc :image :smiley))
       (style-page
         (:p "Hello, "
             (print-rc-image :world)
             "!")))

Check http://localhost/cms to see the file icon in action. Note that icons printed with print-rc-image often have clarifying tooltips.

A simple form, the PHP way

You can get request values from LispCMS with request-var.

This will output a simple form:

     (with-cms-address ("/friendly-form" :icon (get-rc :image :script))
       (if (not (request-var :name))
           (style-page (:form :action (get-nav) :method :post
                         (:p "What is your name?")
                         (:input :name :name)
                         (:input :type :submit :value "Greet me!")))
           (style-page (:p "Hello "
                           (princ (request-var :name))
                           "!"))))

get-nav with no arguments returns the script url.

request-var will search the equivalents of PHP $_GET, $_POST, $_COOKIE, and $_SERVER, in that order.

3.2.2 Advanced examples

A simple session script

LispCMS allows you to easily write scripts that use sessions. For example, this script can remember your name in a session:

     (with-cms-address ("/remember-name")
       (with-session-vars (name)
         ;; We told the script to remember our name
         (if (request-var :name)
             (setf name (request-var :name)))
         ;; We told the script to forget our name
         (if (request-var :forget)
             (setf name nil))
         ;; Construct the page
         (style-page
           (if name
               (htm (:p "I thought your name was " (princ name) "."))
               (htm (:p "I really don't know your name.")))
           (:form :action (get-nav)
             (:p "What is your name?")
             (:input :name "name")
             (:input :type :submit :value "Remember me!")
             (:input :name :forget :type :submit :value "Forget me!")))))

with-session-vars makes that variables an 'alias' for those session variables. To get the same in PHP, you'd use $_SESSION['name']. Or, when register_globals is on, just $name, but using register_globals is unsafe.

The LispCMS equivalent of $_SESSION['name'] is (sess-var 'name).

A simple personal notebook

LispCMS implements users. To make users, you must first become root. In the default setup, visiting /cms/make-root does that. You can then (in the default setup) make new users at /cms/admin.

An example of a script that uses users, a personal notebook:

     (with-cms-address ("/notebook")
       (with-user-vars (notes)
         (if (request-var :note)
             ;; We entered a note, store it.
             (push (request-var :note) notes))
         (if (request-var :throw-away)
             ;; We want to throw away our notes.
             (setf notes nil))
         ;; Construct the page
         (style-page
           (:h3 "Notebook for "
               ;; Get your name (see previous example)
               (princ (or (sess-var 'name)
                          "you")))
           (:p "Previously entered notes:")
           (:ul (dolist (note notes)
                  (htm (:li (princ note)))))
           (:form :action (get-nav) :method :post
             (:textarea :name :note "Enter your note here.")
             (:input :type :submit :value "Store!")
             (:input :name :throw-away :type :submit
                     :value "Throw them away!")))))

Like with-session-vars, with-user-vars makes some variables an alias for those user variables. I don't think there is anything like this in PHP.

user-var is the user equivalent of sess-var, see above.

This example uses the name from the previous example, to show how sess-var works.

A simple temperature-keeping application

LispCMS implements a layer to create HTML forms and their handlers with little code. See Easy form handling, for how to use it.

An example of a simple application in which an integer can be stored, if a non-integer is entered it errors:

     (defvar *temp* -43)
     
     (with-cms-address ("/change-foo")
       (with-form-env
         ;; When something invalid was entered, start again from
         ;; within the with-form-env.
         (style-page
           (:h3 "You can change the temperature indicator here.")
           (:p "Please enter an whole number, in degrees Celcius.")
           (with-form-out ; <form> and </form>
             ;; Output an error message when needed
             (status-line)
             ;; Output an HTML input field that can change *temp*, but it
             ;; must be an integer.
             (change-field *temp* nil
                           :validator #'parse-integer
                           :parser #'parse-integer)
             (submit-button "Change!"))))) ; submit button

When a number is filled in correctly, a standard success page is shown. See Easy form handling, for an example on how to redisplay the form then.

*temp* will contain the integer here, not the string, after the form has been filled in for the first time. Would parser not be specified, *temp* would contain a string, but the outputted HTML would be the same.

Note that parse-integer signals an error, it is catched by with-form-env, and counted as an error.


Next: , Previous: Quick Start, Up: Top

4 Reference

Please note that all of LispCMS's symbols are in package org.brgr.lispcms, but none of them are exported currently. If you want to use them, use `(in-package :org.brgr.lispcms)' once and let all your symbols be in org.brgr.lispcms, or put `org.brgr.lispcms::' before all LispCMS symbols.


Next: , Previous: Reference, Up: Reference

4.1 Files

Brief

In LispCMS there are several ways to store a virtual file. The best one is with-cms-address.

— Macro: with-cms-address (relative-address &key icon ...) &rest body

Store a file in relative-address, so that body is executed when (cms-root)relative-address is accessed. The body source is also stored as property :source of the containing file-wrapper (see Properties). Remember to start relative-address with a /.

See with-apache-address, for the icon parameter.

For example, the below code will print `Hello, world!' when you access /cms/foo:

          (with-cms-address ("/foo")
            (princ "Hello, world!"))
     

See The cms-root, for why you should put everything in the cms-root.

Detailed

with-cms-address first makes a file out of its body, then stores that file in the cms-root.

— Function: fn->file function

Create a function-file out of function. function is called without any arguments when output.

Note that each component of a path in LispCMS goes up to but excluding the slash, so /cms/admin/log-view has components /cms, /admin, and /log-view.

— Method: store-file-in container file rest-url &optional old-url

Store file in container, under path rest-url. If rest-url is a nested path, nest that file accordingly in the directory tree, creating new directorys as necessary. old-url will probably be removed in a next version.

Remember to start rest-url with a / !

For outputting files, the output-file method is used.

— Method: output-file file &optional rest-url old-url

Output file, with the unprocessed path being rest-url. rest-url should be used e.g. in directories, to output either the correct child, or a directory listing.

old-url is deprecated.

— Class: simple-directory-file

A simple-directory-file can store files in a directory-like structure. When output-file is called on one, it output-files the correct child, or prints a directory listing if none was found. store-file can be used to store a child.

— Macro: with-apache-address (relative-address &key icon (root-file *root-file*) ...) &rest body

Store a file in relative-address, relative to root-file, so that body is executed when relative-address is accessed. The body source is stored as property :source of the containing file-wrapper (see Properties). Remember to start relative-address with a /.

When you pass an icon path in icon, that icon will be shown in the parent's directory listing. See Icons, for a mechanism to look up icons.

For example, the below code will print `Hello, world!' when you access /foo. It also will have a nice icon in the parent's directory listing.

          (with-apache-address ("/foo" :icon (get-rc :image :smiley))
            (princ "Hello, world!"))
     
— Variable: *root-file*

The file that corresponds to the document root. When a request is done, we output this file with the url as rest-url.

— Function: get-file path parent

Look up a file that has that is some descendant of parent, under path.

4.1.1 File wrapping

Wrapping files can be useful for storing some data next to a file.

— Function: wrap-file file &key icon permissions props

Wrap file in a file-wrapper, setting the icon path (see Icons) to icon, the properties of the file-wrapper to the alist in props (see Properties), and requiring that a user have permissions when outputting the wrapped file.

— Class: file-wrapper

A file-wrapper passes output-file, get-file, and store-file-in method calls to it's wrapped file, except that it can require some permissions, set by wrap-file. See wrap-file. file-wrappers can have properties (see Properties).

Source files

See src/base/files.lisp for the source code.


Next: , Previous: Files, Up: Reference

4.2 Styles

Brief

In LispCMS you can output a page in a unified style using style-page.

— Macro: style-page &body body

Do body, catch its output, and output a styled page with what body has output.

The body of style-page is parsed by cl-who (see below). style-page will take care of <html>, <head>, <body>, etc. and site-specific headers, so this will output valid (X)HTML:

          (style-page
            (princ "Hello world!"))
     

With the standard style, there will even be a nice LispCMS banner on top :o)

The intention of style-page is to let you output content in its body, and style-page will take care of the rest.

The current style is stored in *style*. See the source for how to make a style.

4.2.1 HTML/XML output

LispCMS uses cl-who for HTML output (who stands for with-html-output), so inside style-page, 'keyword functions' are transformed into HTML:

     (style-page
       (:p :class "foo" :style nil
         (:b "Hi")
         (princ " there."))
       (:br))
         -| (some style-page output)
         -| <p class="foo"><b>Hi</b> there.</p><br />
         -| (some style-page output)

Some cl-who rules:

Detailed

— Function: title title

Set the title of the style-page'd document to title. Only to be used inside style-page. title should be a string.

— Function: add-css &rest pieces

Put the style sheet fragments pieces in the right place in the HTML page.

— Function: add-css-path path

Specify path as a linked style sheet. path is from the browser's point of view.

— Macro: thinbox &attribute inside border margin-v margin-h padding-v padding-h inline style &body body

Execute body within a light thin box. This can be useful for e.g. grouping things/text, because it clearly explains the structure of the viewed page, without disturbing normal page view.

inside is the color of the inside, border of the border. The margin and padding parameters behave as specified in CSS. If inline is true, the thinbox is no block element but an inline element. style can add more CSS to the box.

Source files

See src/base/html.lisp and dep/cl-who/ for the source code.


Next: , Previous: Styles, Up: Reference

4.3 Paths and Linking

4.3.1 Linking

Brief

In LispCMS, the standard is to link with absolute paths (/cms/foo) instead of relative paths (e.g. foo) in HTML.

This has an advantage: if you have a script at /cms/foo, a browser can visit /cms/foo/one and /one can be an 'argument' to your script. Linking to /cms/bar will not require complex, ugly-looking things like counting slashes and inserting that many times ../ before bar. More problems can be ahead when you want to use a <base> HTML element, to shorten relative URLs.

This also has a drawback: you have to remember the path to your script, which makes it a real pain to move. Fortunately, LispCMS implements a macro that helps developers to get an absolute path: get-nav. Use it to keep your scripts movable.

— Function: get-nav &rest ways

Get a URL to the page you want: it starts in the current script, navigates as in ways (see below), and returns the URL to there.

Example: when we are /cms/foo, (get-nav :up "/boo") will return "/cms/boo".

4.3.1.1 Navigation ways

Some navigation way possibilities for use with get-nav are below. Note that the files you navigate to don't really have to exist, it's only specifying a path easily.

string, e.g. "/foo"
Navigate into /foo in the current directory.
:up
Navigate up once to the parent of the current path.
(count . ways), e.g. 2 :up
Do ways count times.
:root, :cms, etc.
Skip upwards to the root file, the nearest cms-var, etc. That is, :cms will get you the path to the innermost cms-var.

Doing :cms multiple times in a row won't change anything, you must use one :elem-up after e.g. :cms to jump past one. You can use :cms :up to get the path to the parent of the innermost cms-var.

See Detailed on how to extend these.

:elem-up
Skip one element up. This is not the same as :up, and you should only use one when you want to jump past one cms-var, for example.
:allow-empty-string
When the final outcome is the root file, "" will be returned by get-nav instead of "/". Doesn't navigate anywhere. :allow-empty-string must not be nested, and has no effect on get-nav-file.
(:seek symbol)
See :cms and :root, but works for all symbols, not just keyword symbols. Not very clean.
Detailed

When available, you can get the file at the get-nav path using get-nav-file.

— Macro: get-nav-file &rest ways

get-nav, but returns a file instead of a path. Returns nil when not available.

While building up the page (see parsing path pieces below), a list of passed-through path pieces (e.g. /foo) is bound using nav-through: each output-file on a simple-directory-file executes output-file on its child within a nav-through for the path piece for that child. This list is bound dynamically with nav-through.

— Macro: nav-through (path-piece &optional file) &body body

Do body, with path piece path-piece remembered. An optional file can be stored with it, for use in get-nav-file.

When path-piece is not a string, but a (keyword) symbol, it can directly be used as a navigation way, to jump to that path.

Example, script in /cms/foo:

          (nav-through (:foo *some-file*)
            (nav-through ("/bar")
              (list (get-nav)
                    (get-nav-file :up)
                    (get-nav :foo "/baz"))))
          =>
          ("/cms/foo/bar"
           (what is in *some-file*)
           "/cms/foo/baz")
     

4.3.2 Path pieces

While handling a request, the request path is parsed into pieces like /foo (leading slash, no trailing slash). At any time, the part that isn't parsed yet is available as a rest-url; the part that has already been parsed is available as an old-url. In function-files (like when you use with-cms-address and with-apache-address) these are in *rest-url* and *old-url*.

next-path-piece is used to parse path pieces, one at a time. Use it wherever appropriate to keep your code compatible.

— Function: next-path-piece path &optional old-path

Returns 2 values: the first path piece (the part before the second slash), and the rest (the slash plus the part after the second slash).

This is an example of what could happen when we would access some imaginary path /cms/foo/bar/baz:


Next: , Previous: Paths and Linking, Up: Reference

4.4 Icons

Brief

In LispCMS it is possible to store icons by tags, and then look up icons for outputting by tags.

— Function: print-rc-image &rest tags

Print the (X)HTML for an image matching every tag in tags. You can use :title title to set the title argument to <img>, this sets a 'tooltip' that may clarify the image.

— Function: rc-image &rest tags

The same as print-rc-image, except that it returns, not outputs the image HTML.

In a default LispCMS installation, the init script already loads some icons from disk from the Silk icon set from famfamfam.com. If you want to auto-load some icons you like, change the src/rc/loader.lisp file to load them.

See Resources, for the mechanism via which icons are stored and retrieved.

Source files

The icon system is implemented in the same file resources are implemented: src/cms/rc.lisp.


Next: , Previous: Icons, Up: Reference

4.5 Resources

Brief

The resource system in LispCMS implements a way of storing resources by tags, and then looking up a list of resources identified by that tags. The ordering of tags doesn't matter.

Resources are just a little more than the urls a browser can visit to get some image/sound/whatever.

— Function: store-rc type path &optional tags &rest keys

Store the resource of type type at path. tags is a list of tags that identify that resource, and keys is a list of attributes. Think of keys as a &key argument list. There is a number of currently-used keys below.

— Function: get-rc type &rest tags

Get the path of the first resource that is of type type and matches tags. Its definition is:

          (defun get-rc (type &rest tags)
            (second (apply #'get-resource type tags)))
     

Detailed

— Function: get-resource type &rest tags

Get all resources of type type that match tags. The resources will be returned as values.

Each value will be a list of the resource type, the resource path (=url), a list of the tags that match it, and the rest will be a list of attributes. All get-resource return values are in the format of store-rc.

Resource types

Currently, the only used resource type is :image, which matches images and icons. You can define your own resource types, please make them keyword symbols.

Resource keys

Each resource can store a little bit of information next to its type, url, and tags: its attributes. Currently, only :title is used; it specifies a default title (tooltip) to be used for an icon or image.

Resource serving

LispCMS implements a small resource server. This may be handy if you don't like changing your apache config only for displaying icons in LispCMS.

— Function: rc-server-store-mime file-name &optional mime-type

Return the path for a virtual file that outputs file-name on the real file system with mime type mime-type. mime-type defaults to plain-text, which you probably don't want.

The resource loader script uses this for loading resources from disk, have a look at src/rc/loader.lisp if you're curious.

Source files

See src/cms/rc.lisp for the source code.


Next: , Previous: Resources, Up: Reference

4.6 Sessions

Brief

LispCMS implements sessions: with sessions you just send out two session cookies with a unique session identifier and password, and you can store as many values as you want for that session identifier. Those session values can then only be changed via your script, so they can be considered 'safe', assuming you don't have any security holes.

The session identifier we send should be stored in the browser until the browser is closed. See Users, if you want more permanent storage for user data.

To use sessions, wrap all your session-using code in a with-session, then you can use sess-var to get/set session variables.

— Function: sess-var key

Get the value for key in the active session. sess-var is setf'able.

— Macro: with-session &body body

Do body with a session active: either resume the session found or give the user a new session.

When multiple with-sessions are nested, the resumed or created session is detected. However when multiple with-sessions are not nested and a new session is created, the two with-sessions each make a new session and output their session cookies! (This is not what you want.) To prevent this, just wrap all code that could possibly use sessions in one huge with-session.

OK:

          (with-cms-address (...)
            (with-session
              ...
              (with-session ...)
              ...
              (with-session ...)
              ...))
     

Not OK:

          (with-cms-address (...)
            ...
            (with-session ...)
            ...
            (with-session ...)
            ...)
     

Detailed

Note that with-session must be dynamically around all session-using code, not necessarily lexically. Most of the time this is the same, but not always. Examples:

Not OK:

     (with-cms-address (...)
       (funcall (with-session
                  #'(lambda ()
                      (princ (sess-var 'foo))))))

OK:

     (with-cms-address (...)
       (labels ((foo ()
                 (princ (sess-var 'foo))))
         (with-session (foo))))

If you want to use cookies securely, you must take care that the session cookies are not stolen in transit: currently, sessions aren't limited to one IP address or something.

If you want to use multiple session variables with less code, you can use with-session-vars.

— Macro: with-session-vars vars &body body

Execute body with each lexical var in vars bound to the sess-var of that symbol. There is an implicit with-session around with-session-vars.

          (with-session-vars (foo)
            (princ (incf foo)))
          ==
          (with-session
            (princ (incf (sess-var 'foo))))
     

As a cms-var always sets the default cookie path to the root of that cms-var, you can have multiple sessions at one host, just by maintaining multiple cms-vars.

The active session is stored in *session*.

Source files

See src/cms/session.lisp for the source code.


Next: , Previous: Sessions, Up: Reference

4.7 Users

Brief

Like most PHP cmses, LispCMS implements users. See Sessions, for most of the talk about sessions applies for users too: you can set some values for a user, and they will be stored on the server side. When a user logs in, his session gets (sess-var :user) set to his user instance, after which you can use his user-vars.

Like for sessions: wrap all your user-using code in a with-user, use user-var to get/set a user var.

— Function: user-var key

Get the user var for key. user-var must have a with-session somewhere dynamically around it. user-var is setf'able.

— Macro: with-user &body body

Do body with a user active. If no user can be found, with-user signals a condition of class not-logged-in, which you can catch.

Note that with-user has an implicit with-session around it, so if you use multiple with-users in one request, you must wrap either a with-user or a with-session around it.

See the explanation of with-session in this Guide, for why you should not have multiple with-session calls that are not nested within one request.

In the default setup, LispCMS has a scripts to let users log in and out:

/cms/user/login
A simple login form. It doesn't currently require a password, however.

This is purely for convenience, because I don't expect anybody to use LispCMS for some time for production environments. (Although you're welcome to do so, and you only need to adjust the login script to check for the password. The admin facility is there already.)

/cms/user/logout
Logs the current user out, visiting the file is enough.

Detailed

— Function: require-user

Require the browser to be logged in. If it isn't, abort the current execution and display an error message with a link to a login form.

You can recover from the not-logged-in condition signalled by using test-page: there is a restart to set the user to the root user.

— Condition: not-logged-in

The condition that should be signalled with error or cerror when the browser isn't logged in. not-logged-in is a subclass of abort-response. It should display an error message if not handled.

— Function: make-user uname &key password perms props

Make (and store) a user with user name uname. perms is a list of permission the user has (see Permissions).

— Function: retrieve-user uname

Get the user instance for user name uname.

— Function: list-users

Get an alist of (uname . user-instance) for the current user table.

If you use multiple user vars in your code, with-user-vars may be shorter.

— Macro: with-user-vars vars &body body

Execute body with each lexical var in vars bound to the user-var of that symbol. There is an implicit with-user around with-user-vars.

          (with-user-vars (foo)
            (princ (incf foo)))
          ==
          (with-user
            (princ (incf (user-var 'foo))))
     
— Class: user uname permissions

A representation of a user. There are accessors named after the slot names. Note that changing uname won't update the user table automagically. Just don't, for now. A user instance can have properties.

Note that, like in sessions, there must be a with-user dynamically around all user-using code, not necessarily lexically. Most of the time this is the same, but not always. Examples:

Not OK:

     (with-cms-address (...)
       (funcall (with-user
                  #'(lambda ()
                      (princ (user-var 'foo))))))

OK:

     (with-cms-address (...)
       (labels ((foo () (princ (user-var 'foo))))
         (with-user (foo))))

Source files

See src/cms/users.lisp for the source code.


Next: , Previous: Users, Up: Reference

4.8 Permissions

As mentioned in the section about users, users can have permissions.

Brief

Permissions in LispCMS were made to mimic the Common Lisp type system: you can combine them with and and or. They can also be more complex, like (:edit-news-item (a news item)), with Lisp objects inside them. Most of the time, however, they are simple keyword symbols like :admin.

To require that the user has some permission, use with-permission.

— Macro: with-permission permission &body body

Requires that the current user has permission. Display an error message if (s)he doesn't have that permission. Also, any anonymous links you create in body will also require that permission, and the anonymous links in their code, and so on.

When test-page is used, you can recover: it has a continue restart to ignore the permission error.

with-permission calls require-user.

— Function: require-permission permission

Requires that the current user has permission. See with-permission for details, except that require-permission has no body in which anonymous links can require that permission too.

          (require-permission :blah)
          ==
          (with-permission :blah)
     
— Condition: not-allowed

The condition that should be signalled when some user doesn't have the right permissions. Displays a nice error message if not caught.

Detailed

You can combine multiple tests that must all be passed with and:

     (defun do-a-and-b ()
       (require-permission '(and :do-a :do-b))
       ...)

Someone with permissions :do-a and :do-b would pass this test, and so would someone with a single permission (and :do-a :do-z :do-b).

You can combine multiple tests of which one must be passed with or:

     (defun edit-news (news-instance ...)
       (require-permission `(or :global-news-admin
                                (:news-admin ,news-instance)))
       ...)

A required permission of nil will never match, a required permission of t will always match.

(These functions are fictional.)

— Function: have-permission-p permission

Like require-permission, but returns true when a user is allowed, false (nil) when a user is not allowed.

have-permission-p calls require-user, which errors when the browser is not logged in.

— Function: test-permission given test

Returns true when a user with permission given should be able to access something that requires permission test.

Source files

See src/cms/perm.lisp for the source code.


Next: , Previous: Permissions, Up: Reference

4.9 Anonymous Links

LispCMS implements a mechanism for anonymous links: you give a function, it returns a link to a file that will execute that function. This can rid your code of fixed paths, but the drawback is that at each cont call, a new entry is made in a hash table for that link. Currently, it stays there until the server is restarted, and if you use closures, these can prevent garbage collecting.

— Function: cont fn

Get a link to a file that will call fn. In the default setup, this will generate something like /cms/cont/123.

If you use with-permission to require permissions, there is no need to check for that permission in every anonymous link: that is automatically done (recursively). If you do not use it, e.g. you use require-permission, you need to check for that permission inside each anonymous link: these links are easily guessable.

Note that these 'links' are not restricted to links: they can just as easily be the target of a POST form.

When the user clicks that anonymous link, *cont* is set to the current 'continuation'. If that link does some things with side effects, and you don't want those side effects to happen each time that link is clicked, you can use with-screen.

— Macro: with-screen &body body

Run body. Also, make body the target of the 'current link'.

These links are called 'continuations', but they're not the same as call/cc things. There is more functionality for them, e.g. you can store values for them; look in the source code if you want to know more. I do not expect you to use them, as I don't, but it's possible.

Note that these addresses can be guessable, so if your script requires some permission, you should put a require-permission in each cont function. (Or implement random addresses, which would also be good, I think.)

Source files

See src/cms/cont/basic.lisp for the source code.


Next: , Previous: Anonymous Links, Up: Reference

4.10 Easy form handling

Brief

Anonymous links can make forms shorter. LispCMS's easy form handling uses them to let developers develop forms (and their handlers) in less code, assuming they use the higher-level input field functions. It also provides better abstraction, and you don't need to remember field names any more.

To use this, wrap the page-outputting code in with-form-env. Then wrap all that should be inside <form> tags in with-form-out. Output a field to change a variable with change-field. Put an error message on top with status-line. Output a submit button with submit-button, or one with a custom action with action-button. Define a handler for when all is filled in with do-next, or let a standard message do the job.

See Introduction to LispCMS, for an example.

— Macro: with-form-env &body body

Do body within an easy-form-handling environment. Don't nest multiple with-form-envs.

— Macro: with-form-out &body body

Output the right <form> tags around body. body is parsed with with-html-output (see section the section called 'HTML/XML output').

— Macro: change-field field &optional id &key validator (parser #'identity) input-type

Output a change-field: a field that, when the form is filled in without detected errors, will change field to the string filled in, parsed by parser.

At a form submission, validator is called with an argument of the submitted value. If it returns false or errors, the whole submission is invalid.

It is no error at all to call change-field e.g. in a loop, with different fields, like below. In a lot of cases, it's just handy.

          (dolist (s '(*foo* *bar* *baz*)) ; make sure these are set before..
            ;; bad HTML style, but it's just for the example.
            (htm :br (princ s) ": ")
            (change-field (symbol-value s)))
     

When id is not nil and unique for that with-form-env, the HTML name attribute will stay the same. id can be any Lisp value.

The input-type field determines the HTML type attribute of the input element.

— Function: status-line &optional error-message

If something invalid was detected in the form submission, display error-message. error-message should be a string, status-line will take care of proper formatting. (red, bold, etc.)

— Function: submit-button &optional (value "Submit")

Output a submit button which says value. Just a simple HTML outputter, nothing really special, but it's shorter and more readable than typing `(:input :type "submit" :value value)'.

— Macro: action-button &optional value &body body

A submit-button, but when that button is called, the success handler changes: when the first thing in body is :replace, it replaces the old success handler; otherwise, it is called before the old one.

action-button can be used to display a form with two (or more) submit buttons, and let behavior depend on what button was clicked.

— Pseudo-macro: do-next &body specs

Make specs the current success handler, instead of the default one. This can be overridden by an (earlier or later) action-button.

do-next accepts a lambda body, something like #'(lambda ...), something like #'foo and something like 'foo. In the last case, the function will be looked up when needed. That may be multiple times, in which case a redefinition of foo would be picked up. (Just like the funcall behavior, what a coincidence!)

When multiple do-nexts are done in one with-form-env, the last one prevails.

When you want the form to redisplay itself when all is ok, make it recursive in do-next or an action-button, like this:

     (with-cms-address ("/test/foo")
        (labels ((foo (&optional thanksp)
                   (with-form-env
                     (style-page
                       (with-form-out
                         (:h3 "Some really interesting form greets you.")
                         (if thanksp
                           (htm (:p "Thanks for filling in the form.")))
                         (submit-button)))
                     (do-next (foo t)))))
          (foo)))

Advanced

— Function: input-field &optional id &key value writer validator input-type

A more generic input field than change-field. Display an <input> field of type input-type and default value value. Register a validator function that will call validator with the string filled in. Register a function that will call writer on the validated, but unchanged string when the whole form is valid.

When id is a Lisp value, unique for this with-form-env and not nil, the HTML <input> name attribute will stay the same when the form is redisplayed because of invalid values.

input-field is the most low-level input field function defined in LispCMS. Have a look at it, for how to write those functions/macros.

4.10.1 How it works

Easy form handling is all about with-form-env. Inside, the with-form-env gets itself a handler url. It also binds some variables that are used by the input field functions. It then runs the code inside with-form-env.

In the code there are input fields: they can register functions that are called without arguments when the form is submitted OK. They can also register functions that validate a submission. By using closures, the functions can know what request-var key to look for, and thus what e.g. to store in *foo*.

When the form is submitted and all is OK, first submission-handling functions are called (see above paragraph). Then a page outputting function is called, and it should output a nice page that tells the user we did something with it. Or not, depending on the form.

When anything is not OK, the body of with-form-env is called again, this time with *form-error-count* set to the number of submission errors. This is why you should put all the code that outputs the page inside with-form-env, and it is not the same as with-form-out: if you don't have the <html>-tag generating code within with-form-env, your HTML is broken when the user makes an error.

with-form-env binds a lot a variables, but only the variables below should be used by 'normal code', input field operators, action-buttons, etc. You can use them to create new input field operators.

*form-validate-fns*
A list of functions that are called when the form is submitted. The functions should require no arguments.

When a validate function returns nil or errors, the form is considered invalid and one submission error is counted.

*form-ok-fns*
A list of functions that is to be called when the form is submitted and considered valid. These should not print a success page or something, although they should have side effects, e.g. updating a value somewhere.
*form-next-fn*
A function that is called after everything has been validated, and all functions in *form-ok-fns* have been called. This should output e.g. a success page, or redisplay the form with the notice that the submission was received.

By default, this is set to some boring standard success page, telling the user you were too lame to set one. Well, not by those words, but it says you didn't set one. It also logs a message, telling you to do so.

*form-handler-url*
A string for the URL at which the user should be sent to submit the page.

*form-handler-url* is used in with-form-out: that is just shorthand for this, inside with-html-output:

          (:form :action *form-handler-url* :method "POST" . body)
     

*form-error-count*
A count of the errors found in validating the form. This is set after calling the validating functions. status-line uses this.

When you want to make an input field operator, you have to make sure that the HTML name attribute ((request-var key)) is unique for that form. To be sure, you can use get-new-field-name. You can then make your 'ok-fn's and 'validate-fn's closures that retrieve the value for that field name.

— Function: get-new-field-name

Get a field name, to be used in a <input name=...>, and that is unique for the current with-form-env.

If you want to see an example on how to make input fields, check out the source of input-button.

The id argument

A (small) problem with the current way of generating forms may be that the field names get changed every time the form is generated: browsers may get messed up. To prevent this, you can connect an id to the field name. You then get your old field name with get-field-name, which just returns a fresh one if no old one was found; you make the field name accessible for the next time with store-field-name.

Using an id of nil means that no storing will take place at all. (Handy for optional arguments, no need to test for a given id.)

— Function: get-field-name &optional id

Get the old field name for id, or a new one if none was found.

— Function: store-field-name id name

Make field name name accessible under id for if the user errors and the form gets displayed again. Note that it must error, just calling it recursively from e.g. a do-next won't do.

Source files

See src/cms/form.lisp for the source code.


Next: , Previous: Easy form handling, Up: Reference

4.11 The cms-root

Brief

LispCMS allows for multiple cms-vars. A cms-var instance is a centralized place where e.g. logs and (in the future) users are stored. By having multiple cms-vars, you can easily have multiple user databases and logs.

A cms-root is simply a place in the tree where some cms-var is stored, e.g. `/cms'.

It is advisable that you put all your files inside a cms-var, this makes sure e.g. users and sessions remain to work in the future, and you don't have to use the global log, which isn't readable from within the log admin. Also, cookies will by default have the path parameter set to the cms root, unless you specify a path. This is easy for having multiple sites at the same host that try to set the same cookie.

Detailed

cms-vars are normal instances, so you can subclass them. The behavior of cms-vars is likely to change in the future, e.g. it may become e.g. an object subclassing a `user-db-central' and a `log-central'. This would allow having files in which only the logs are centralized.

Source files

See src/cms/paths.lisp for the source code.


Next: , Previous: The cms-root, Up: Reference

4.12 Server Layer

This section is about the interaction between Apache and Lisp, and how you can get Apache's information in Lisp.


Next: , Previous: Server Layer, Up: Server Layer

4.12.1 Getting info from Apache

In LispCMS, all output is cached. This makes sending headers after 'outputting' content possible.

— Function: get-header key

Get the HTTP request header value for key, nil if not found.

— Function: add-header key value

Output the HTTP header key: value. If key is not a string, it is made into a string.

If key and value are not strings, they are made into strings.

— Function: set-cookie key value &key comment domain max-age path secure version auto-nocache

Output a set-cookie header for key=value. See the HTTP specs for details about the rest parameters. If auto-nocache is true (default), a HTTP header is also sent telling routers not to cache this request. If path is not set, and we're in an cms-var, the cookie path is set to the cms-var path.

— Function: request-var key

Get the request-var for key. These things are searched in order for request-vars:

It is recommended that you use request-var to get info from Apache: it makes changing form methods easier and you can set cookies to provide defaults. Also, it is easier to remember just 1 function. request-var has about the same meaning as PHP's $_REQUEST. request-var is setf'able. If key is not a string, it is made a string.

— Macro: with-request-vars vars &body body

Do body with each symbol in vars bound to its appropriate request-var.

— Function: test-page uri &rest post-vars

Test page uri with POST vars post-vars. Unlike normal request handling, this function lets any errors/warnings through to the normal Lisp debugger. Look in the code for more test functions. See Error Handling, for more info about normal error handling.

— Function: test-page-no-catch uri &rest post-vars

Test page uri with POST vars post-vars. Unlike test-page, this function lets any abort-responses through.

— Variable: *apache-command*

An alist of HTTP headers, and some extra things: the value for key "method" holds the HTTP method, "posted-content" holds the POST part of the request, but check with mod_lisp for more details.

You should use this variable as little as possible, try to use request-var instead. You can get the values from *apache-command* with request-var too, if they're not overridden.

There is a live demo of an *apache-command* (although it's not named that way there) at boundp.net.


Previous: Getting info from Apache, Up: Server Layer

4.12.2 Parsing input from Apache

When LispCMS is started up (see Loading Order), a thread is started up that listens to a port. When mod_lisp connects to that port to pass through a request, that request is first parsed into an apache-command, an alist of HTTP header keys and values. That apache-command is then passed to apache->response, with an appropriate handler function: output-file of the *root-file*.

— Function: apache->response command fn &rest args

Set up an appropriate environment for handling request command, and call fn with args. The environment will make sure various functions will work as intended, see below. It also rebinds *standard-output* and passes the output back to mod_lisp.

You can make LispCMS listen on a different port by changing +apache-port+ in src/base/server.lisp.

Source files

See src/base/server.lisp, src/base/pre-server.lisp and src/base/gpc.lisp for the source code.


Next: , Previous: Server Layer, Up: Reference

4.13 Error Handling

If Lisp signals an error or warning in a request received via mod_lisp, that error/warning is caught and logged. For errors, an abort-response is signalled that displays an error page. Warnings get muffled and normal evaluation continues.

See Logging below, for more info about logging; and see abort-responses below.

4.13.1 Displaying errors

— Function: display-error-page &optional (code 500)

Display an error page for HTTP response code code.

4.13.2 Redirecting browsers

— Function: redirect-to uri &optional type

Redirect the browser to uri. Use HTTP response code type or 303.

4.13.3 abort-responses

abort-responses are a way of aborting the current handler, and have a function display an error message or something like that. When an abort-response is signalled in normal requests, the current handler is stopped and a new function, specified in the abort-response, is called.

— Condition: abort-response instead-function

A condition that tells LispCMS to abort the current response, and continue with instead-function in a fresh handling cycle. This means that e.g. any setf'd request-vars are cleaned, and the output cache is emptied.

Use `(error 'abort-response :fn (some function))' to throw an abort-response. To throw one that is correctable if test-page is used, use `(cerror "Continue evaluation." 'correctable-error-response (some function))'.

4.13.4 Logging

LispCMS implements a logging facility. You can use do-log for logging anything you'd like, and it will be stored and, if the log admin file is somewhere in the virtual file system (default /cms/admin/log-view), admins can read it.

Currently, the global logs are stored in *log-vector*, and the logs for a cms-var are stored in (log-vector (cms-var)). Inspecting probably gives useful information.

— Function: do-log type format-string &rest format-args

Log a message. When it is printed, it uses format to display a message per format-string and format-args. See below for the log levels you should use in type.

Note that each format-arg and format-string is stored in raw form, so you can later inspect the logs and inspect the values inside a log message.

— Function: log-message message

Log log-message message.

— Class: log-message type level control-string format-args dynamic-bindings

A log message, see do-log. type should be a symbol describing the seriousness, level a number. dynamic-bindings is an alist of automatically stored dynamic bindings that were in effect at log time.

log-messages can have properties (see Properties).

The standard log levels/types are:

-1, :debug
A debugging message. Probably isn't useful when you're not debugging.
0, :info
An info message, like someone logging in or out, or a poll vote.
1, :notice, :code-warning
Something that should be noticed, but that's not that serious either. This includes style-warnings signalled by Lisp.
2, :warning, :warn
Something that you really should see, because something is probably not right, (deadlock, code signalled error)
3, :error
There has been some serious error in some part, but LispCMS still runs.
4, :nearly-fatal, :fatal
There has been an error that was almost fatal.

Source files

See src/base/error.lisp, src/base/log.lisp, and src/base/content/error.lisp for the source code.


Next: , Previous: Error Handling, Up: Reference

4.14 Properties

In LispCMS, various instances can have properties. You use props-var to set and get a property.

— Function: props-var key object &key (test #'eql)

Get the property key on object, compared with test.

props-var is setf'able.


Previous: Properties, Up: Reference

4.15 Loading Order

LispCMS loads itself via ASDF, Another System Definition Facility. The LispCMS system description is in src/lispcms.asd. However it is possible to load LispCMS by hand via ASDF, it is probably more handy just to load src/loader.lisp. src/loader.lisp then loads all it needs to load for LispCMS to work:


Next: , Previous: Reference, Up: Top

Appendix A Copying This Manual


Up: Copying This Manual

A.1 GNU Free Documentation License

Version 1.2, November 2002
     Copyright © 2000,2001,2002 Free Software Foundation, Inc.
     51 Franklin St, Fifth Floor, Boston, MA  02110-1301, USA
     
     Everyone is permitted to copy and distribute verbatim copies
     of this license document, but changing it is not allowed.
  1. PREAMBLE

    The purpose of this License is to make a manual, textbook, or other functional and useful document free in the sense of freedom: to assure everyone the effective freedom to copy and redistribute it, with or without modifying it, either commercially or noncommercially. Secondarily, this License preserves for the author and publisher a way to get credit for their work, while not being considered responsible for modifications made by others.

    This License is a kind of “copyleft”, which means that derivative works of the document must themselves be free in the same sense. It complements the GNU General Public License, which is a copyleft license designed for free software.

    We have designed this License in order to use it for manuals for free software, because free software needs free documentation: a free program should come with manuals providing the same freedoms that the software does. But this License is not limited to software manuals; it can be used for any textual work, regardless of subject matter or whether it is published as a printed book. We recommend this License principally for works whose purpose is instruction or reference.

  2. APPLICABILITY AND DEFINITIONS

    This License applies to any manual or other work, in any medium, that contains a notice placed by the copyright holder saying it can be distributed under the terms of this License. Such a notice grants a world-wide, royalty-free license, unlimited in duration, to use that work under the conditions stated herein. The “Document”, below, refers to any such manual or work. Any member of the public is a licensee, and is addressed as “you”. You accept the license if you copy, modify or distribute the work in a way requiring permission under copyright law.

    A “Modified Version” of the Document means any work containing the Document or a portion of it, either copied verbatim, or with modifications and/or translated into another language.

    A “Secondary Section” is a named appendix or a front-matter section of the Document that deals exclusively with the relationship of the publishers or authors of the Document to the Document's overall subject (or to related matters) and contains nothing that could fall directly within that overall subject. (Thus, if the Document is in part a textbook of mathematics, a Secondary Section may not explain any mathematics.) The relationship could be a matter of historical connection with the subject or with related matters, or of legal, commercial, philosophical, ethical or political position regarding them.

    The “Invariant Sections” are certain Secondary Sections whose titles are designated, as being those of Invariant Sections, in the notice that says that the Document is released under this License. If a section does not fit the above definition of Secondary then it is not allowed to be designated as Invariant. The Document may contain zero Invariant Sections. If the Document does not identify any Invariant Sections then there are none.

    The “Cover Texts” are certain short passages of text that are listed, as Front-Cover Texts or Back-Cover Texts, in the notice that says that the Document is released under this License. A Front-Cover Text may be at most 5 words, and a Back-Cover Text may be at most 25 words.

    A “Transparent” copy of the Document means a machine-readable copy, represented in a format whose specification is available to the general public, that is suitable for revising the document straightforwardly with generic text editors or (for images composed of pixels) generic paint programs or (for drawings) some widely available drawing editor, and that is suitable for input to text formatters or for automatic translation to a variety of formats suitable for input to text formatters. A copy made in an otherwise Transparent file format whose markup, or absence of markup, has been arranged to thwart or discourage subsequent modification by readers is not Transparent. An image format is not Transparent if used for any substantial amount of text. A copy that is not “Transparent” is called “Opaque”.

    Examples of suitable formats for Transparent copies include plain ascii without markup, Texinfo input format, LaTeX input format, SGML or XML using a publicly available DTD, and standard-conforming simple HTML, PostScript or PDF designed for human modification. Examples of transparent image formats include PNG, XCF and JPG. Opaque formats include proprietary formats that can be read and edited only by proprietary word processors, SGML or XML for which the DTD and/or processing tools are not generally available, and the machine-generated HTML, PostScript or PDF produced by some word processors for output purposes only.

    The “Title Page” means, for a printed book, the title page itself, plus such following pages as are needed to hold, legibly, the material this License requires to appear in the title page. For works in formats which do not have any title page as such, “Title Page” means the text near the most prominent appearance of the work's title, preceding the beginning of the body of the text.

    A section “Entitled XYZ” means a named subunit of the Document whose title either is precisely XYZ or contains XYZ in parentheses following text that translates XYZ in another language. (Here XYZ stands for a specific section name mentioned below, such as “Acknowledgements”, “Dedications”, “Endorsements”, or “History”.) To “Preserve the Title” of such a section when you modify the Document means that it remains a section “Entitled XYZ” according to this definition.

    The Document may include Warranty Disclaimers next to the notice which states that this License applies to the Document. These Warranty Disclaimers are considered to be included by reference in this License, but only as regards disclaiming warranties: any other implication that these Warranty Disclaimers may have is void and has no effect on the meaning of this License.

  3. VERBATIM COPYING

    You may copy and distribute the Document in any medium, either commercially or noncommercially, provided that this License, the copyright notices, and the license notice saying this License applies to the Document are reproduced in all copies, and that you add no other conditions whatsoever to those of this License. You may not use technical measures to obstruct or control the reading or further copying of the copies you make or distribute. However, you may accept compensation in exchange for copies. If you distribute a large enough number of copies you must also follow the conditions in section 3.

    You may also lend copies, under the same conditions stated above, and you may publicly display copies.

  4. COPYING IN QUANTITY

    If you publish printed copies (or copies in media that commonly have printed covers) of the Document, numbering more than 100, and the Document's license notice requires Cover Texts, you must enclose the copies in covers that carry, clearly and legibly, all these Cover Texts: Front-Cover Texts on the front cover, and Back-Cover Texts on the back cover. Both covers must also clearly and legibly identify you as the publisher of these copies. The front cover must present the full title with all words of the title equally prominent and visible. You may add other material on the covers in addition. Copying with changes limited to the covers, as long as they preserve the title of the Document and satisfy these conditions, can be treated as verbatim copying in other respects.

    If the required texts for either cover are too voluminous to fit legibly, you should put the first ones listed (as many as fit reasonably) on the actual cover, and continue the rest onto adjacent pages.

    If you publish or distribute Opaque copies of the Document numbering more than 100, you must either include a machine-readable Transparent copy along with each Opaque copy, or state in or with each Opaque copy a computer-network location from which the general network-using public has access to download using public-standard network protocols a complete Transparent copy of the Document, free of added material. If you use the latter option, you must take reasonably prudent steps, when you begin distribution of Opaque copies in quantity, to ensure that this Transparent copy will remain thus accessible at the stated location until at least one year after the last time you distribute an Opaque copy (directly or through your agents or retailers) of that edition to the public.

    It is requested, but not required, that you contact the authors of the Document well before redistributing any large number of copies, to give them a chance to provide you with an updated version of the Document.

  5. MODIFICATIONS

    You may copy and distribute a Modified Version of the Document under the conditions of sections 2 and 3 above, provided that you release the Modified Version under precisely this License, with the Modified Version filling the role of the Document, thus licensing distribution and modification of the Modified Version to whoever possesses a copy of it. In addition, you must do these things in the Modified Version:

    1. Use in the Title Page (and on the covers, if any) a title distinct from that of the Document, and from those of previous versions (which should, if there were any, be listed in the History section of the Document). You may use the same title as a previous version if the original publisher of that version gives permission.
    2. List on the Title Page, as authors, one or more persons or entities responsible for authorship of the modifications in the Modified Version, together with at least five of the principal authors of the Document (all of its principal authors, if it has fewer than five), unless they release you from this requirement.
    3. State on the Title page the name of the publisher of the Modified Version, as the publisher.
    4. Preserve all the copyright notices of the Document.
    5. Add an appropriate copyright notice for your modifications adjacent to the other copyright notices.
    6. Include, immediately after the copyright notices, a license notice giving the public permission to use the Modified Version under the terms of this License, in the form shown in the Addendum below.
    7. Preserve in that license notice the full lists of Invariant Sections and required Cover Texts given in the Document's license notice.
    8. Include an unaltered copy of this License.
    9. Preserve the section Entitled “History”, Preserve its Title, and add to it an item stating at least the title, year, new authors, and publisher of the Modified Version as given on the Title Page. If there is no section Entitled “History” in the Document, create one stating the title, year, authors, and publisher of the Document as given on its Title Page, then add an item describing the Modified Version as stated in the previous sentence.
    10. Preserve the network location, if any, given in the Document for public access to a Transparent copy of the Document, and likewise the network locations given in the Document for previous versions it was based on. These may be placed in the “History” section. You may omit a network location for a work that was published at least four years before the Document itself, or if the original publisher of the version it refers to gives permission.
    11. For any section Entitled “Acknowledgements” or “Dedications”, Preserve the Title of the section, and preserve in the section all the substance and tone of each of the contributor acknowledgements and/or dedications given therein.
    12. Preserve all the Invariant Sections of the Document, unaltered in their text and in their titles. Section numbers or the equivalent are not considered part of the section titles.
    13. Delete any section Entitled “Endorsements”. Such a section may not be included in the Modified Version.
    14. Do not retitle any existing section to be Entitled “Endorsements” or to conflict in title with any Invariant Section.
    15. Preserve any Warranty Disclaimers.

    If the Modified Version includes new front-matter sections or appendices that qualify as Secondary Sections and contain no material copied from the Document, you may at your option designate some or all of these sections as invariant. To do this, add their titles to the list of Invariant Sections in the Modified Version's license notice. These titles must be distinct from any other section titles.

    You may add a section Entitled “Endorsements”, provided it contains nothing but endorsements of your Modified Version by various parties—for example, statements of peer review or that the text has been approved by an organization as the authoritative definition of a standard.

    You may add a passage of up to five words as a Front-Cover Text, and a passage of up to 25 words as a Back-Cover Text, to the end of the list of Cover Texts in the Modified Version. Only one passage of Front-Cover Text and one of Back-Cover Text may be added by (or through arrangements made by) any one entity. If the Document already includes a cover text for the same cover, previously added by you or by arrangement made by the same entity you are acting on behalf of, you may not add another; but you may replace the old one, on explicit permission from the previous publisher that added the old one.

    The author(s) and publisher(s) of the Document do not by this License give permission to use their names for publicity for or to assert or imply endorsement of any Modified Version.

  6. COMBINING DOCUMENTS

    You may combine the Document with other documents released under this License, under the terms defined in section 4 above for modified versions, provided that you include in the combination all of the Invariant Sections of all of the original documents, unmodified, and list them all as Invariant Sections of your combined work in its license notice, and that you preserve all their Warranty Disclaimers.

    The combined work need only contain one copy of this License, and multiple identical Invariant Sections may be replaced with a single copy. If there are multiple Invariant Sections with the same name but different contents, make the title of each such section unique by adding at the end of it, in parentheses, the name of the original author or publisher of that section if known, or else a unique number. Make the same adjustment to the section titles in the list of Invariant Sections in the license notice of the combined work.

    In the combination, you must combine any sections Entitled “History” in the various original documents, forming one section Entitled “History”; likewise combine any sections Entitled “Acknowledgements”, and any sections Entitled “Dedications”. You must delete all sections Entitled “Endorsements.”

  7. COLLECTIONS OF DOCUMENTS

    You may make a collection consisting of the Document and other documents released under this License, and replace the individual copies of this License in the various documents with a single copy that is included in the collection, provided that you follow the rules of this License for verbatim copying of each of the documents in all other respects.

    You may extract a single document from such a collection, and distribute it individually under this License, provided you insert a copy of this License into the extracted document, and follow this License in all other respects regarding verbatim copying of that document.

  8. AGGREGATION WITH INDEPENDENT WORKS

    A compilation of the Document or its derivatives with other separate and independent documents or works, in or on a volume of a storage or distribution medium, is called an “aggregate” if the copyright resulting from the compilation is not used to limit the legal rights of the compilation's users beyond what the individual works permit. When the Document is included in an aggregate, this License does not apply to the other works in the aggregate which are not themselves derivative works of the Document.

    If the Cover Text requirement of section 3 is applicable to these copies of the Document, then if the Document is less than one half of the entire aggregate, the Document's Cover Texts may be placed on covers that bracket the Document within the aggregate, or the electronic equivalent of covers if the Document is in electronic form. Otherwise they must appear on printed covers that bracket the whole aggregate.

  9. TRANSLATION

    Translation is considered a kind of modification, so you may distribute translations of the Document under the terms of section 4. Replacing Invariant Sections with translations requires special permission from their copyright holders, but you may include translations of some or all Invariant Sections in addition to the original versions of these Invariant Sections. You may include a translation of this License, and all the license notices in the Document, and any Warranty Disclaimers, provided that you also include the original English version of this License and the original versions of those notices and disclaimers. In case of a disagreement between the translation and the original version of this License or a notice or disclaimer, the original version will prevail.

    If a section in the Document is Entitled “Acknowledgements”, “Dedications”, or “History”, the requirement (section 4) to Preserve its Title (section 1) will typically require changing the actual title.

  10. TERMINATION

    You may not copy, modify, sublicense, or distribute the Document except as expressly provided for under this License. Any other attempt to copy, modify, sublicense or distribute the Document is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance.

  11. FUTURE REVISIONS OF THIS LICENSE

    The Free Software Foundation may publish new, revised versions of the GNU Free Documentation License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. See http://www.gnu.org/copyleft/.

    Each version of the License is given a distinguishing version number. If the Document specifies that a particular numbered version of this License “or any later version” applies to it, you have the option of following the terms and conditions either of that specified version or of any later version that has been published (not as a draft) by the Free Software Foundation. If the Document does not specify a version number of this License, you may choose any version ever published (not as a draft) by the Free Software Foundation.

A.1.1 ADDENDUM: How to use this License for your documents

To use this License in a document you have written, include a copy of the License in the document and put the following copyright and license notices just after the title page:

       Copyright (C)  year  your name.
       Permission is granted to copy, distribute and/or modify this document
       under the terms of the GNU Free Documentation License, Version 1.2
       or any later version published by the Free Software Foundation;
       with no Invariant Sections, no Front-Cover Texts, and no Back-Cover
       Texts.  A copy of the license is included in the section entitled ``GNU
       Free Documentation License''.

If you have Invariant Sections, Front-Cover Texts and Back-Cover Texts, replace the “with...Texts.” line with this:

         with the Invariant Sections being list their titles, with
         the Front-Cover Texts being list, and with the Back-Cover Texts
         being list.

If you have Invariant Sections without Cover Texts, or some other combination of the three, merge those two alternatives to suit the situation.

If your document contains nontrivial examples of program code, we recommend releasing these examples in parallel under your choice of free software license, such as the GNU General Public License, to permit their use in free software.


Next: , Previous: Copying This Manual, Up: Top

Operator and Variable Index