Next: , Previous: , Up: The (www *) Modules   [Contents][Index]


9 (www server-utils filesystem)

The (www server-utils filesystem) module provides procedures for cleaning filenames, checking filesystem access, and mapping from a URL path to a filename.

Procedure: cleanup-filename name

Return a new filename made from cleaning up filename name. Cleaning up is a transform that collapses each of these, in order:

  • //
  • /./
  • /foo/../

into a single slash (‘/’), everywhere in name, plus some fixups. The transform normally preserves the trailing slash (if any) in name, and does not change any leading ‘..’ components if name is relative, i.e., does not begin with slash. Due to proper ‘/foo/../’ cancellation for relative name, however, the result may be the empty string. (Here, proper means that foo is not ‘..’, but a normal filename component.)

Following is a fairly comprehensive list of the cleanup-filename edge cases, paired by name and result. The numbers represent string lengths.

  0                     ;; empty string
  0                     ;; result is empty string

  1  /
  1  /

  2  ok
  2  ok

  3  ok/
  3  ok/

  3  /ok
  3  /ok

  4  /ok/
  4  /ok/

  1  .                  ;; relative name
  0                     ;; result is empty string

  2  ./                 ;; likewise
  0                     ;; note, end-slash not preserved

  2  /.
  1  /

  3  /./
  1  /

  2  ..                 ;; relative, with leading double-dot
  2  ..                 ;; unchanged

  3  ../                ;; likewise
  3  ../

  3  /..                ;; absolute
  1  /                  ;; can’t go higher than root

  4  /../
  1  /

  4  ./..               ;; next 8 are like the previous 4;
  2  ..                 ;;  they show that . makes no difference

  5  ./../
  3  ../

  5  /./..
  1  /

  6  /./../
  1  /

  4  ../.
  2  ..

  5  .././
  3  ../

  5  /../.
  1  /

  6  /.././
  1  /

  5  ../..              ;; relative
  5  ../..              ;; leading .. sequences unchanged

  6  ../../
  6  ../../

  6  /../..             ;; absolute
  1  /                  ;; can’t go higher than root

  7  /../../
  1  /

  4  z/..               ;; relative
  0                     ;; only dir cancelledempty string

  5  z/../              ;; likewise
  0

  5  /z/..              ;; absolute
  1  /

  6  /z/../
  1  /

  6  z/../o             ;; next 4 like previous 4, with trailing component
  1  o

  7  z/../o/
  2  o/

  7  /z/../o
  2  /o

  8  /z/../o/
  3  /o/

  8  z/./../o           ;; next 4 like previous 4;
  1  o                  ;;  they show that . makes no difference

  9  z/./../o/
  2  o/

  9  /z/./../o
  2  /o

 10  /z/./../o/
  3  /o/

  9  z/../../o          ;; relative, more double-dot than parents
  4  ../o               ;; leftover double-dot preserved

 10  z/../../o/
  5  ../o/

 10  /z/../../o         ;; absolute, more double-dot than parents
  2  /o                 ;; all cancelled

 11  /z/../../o/
  3  /o/

 43  ../../abc/././bye0/./../def/bye1/bye2/../..        ;; bye bye-bye
 14  ../../abc/def/

 44  ../../abc/././bye0/./../def/bye1/bye2/../../
 14  ../../abc/def/

 44  /../../abc/././bye0/./../def/bye1/bye2/../..
  9  /abc/def/

 45  /../../abc/././bye0/./../def/bye1/bye2/../../
  9  /abc/def/
Procedure: access-forbidden?-proc docroot forbid-rx

Create and return a filesystem-access procedure based on docroot and forbid-rx. The returned procedure p takes a filename and returns #t if access to that file should be denied for any of the following reasons:

  • filename does not begin with docroot
  • filename matches regular expression forbid-rx

If forbid-rx is #f, the regular expression check is skipped. p returns #f if access should be granted.

Procedure: upath->filename-proc docroot [dir-indexes]

Create and return a url-path-to-filename mapping procedure based on docroot. The returned procedure p takes a (string) upath and returns a valid local filename path for the requested resource, or #f if that file cannot be found. Optional arg dir-indexes specifies an ordered list of filenames to try if the resolved filename path turns out to be a directory.

If no such files exist, return the directory name. As a special case, when p encounters a value of #f during iteration over dir-indexes, it returns #f immediately.

For example, presuming files /a/b/c.txt and /a/b/index.html both exist and are readable:

(define resolve (upath->filename-proc
                   "/a/b/"
                   '("index.shtml" "index.html")))

(resolve "/random") ⇒ #f
(resolve "/c.txt") ⇒ "/a/b/c.txt"
(resolve "/") ⇒ "/a/b/index.html"

Directory names are always returned with a trailing slash.

MIME type

Additionally, the following procedures and fluid are designed to work with the “MIME type” of a file (in a filesystem). Typically, you use filename->content-type to get the raw MIME type (see (www data mime-types)) and then fully-specified to structure it (possibly with additional charset info) into either an HTTP response header or an HTML element attribute.

Procedure: filename->content-type filename [default]

Return a valid Content-Type string which matches filename best. Matching is done by comparing the extension (part of filename after the last "." if available) against a table. If none match, return "application/octet-stream". Optional arg default specifies another value to use instead of "application/octet-stream".

If there are multiple MIME types associated with the extension, return the first one.

See (www data mime-types), proc put-mime-types!, for more info.

Fluid: default-text-charset

The encoding name (a string) for text/* MIME types. Its initial value is ‘ISO-8859-1’.

Procedure: fully-specified lead mime-type

If mime-type (a string) starts with ‘text/’, return a plist that decorates the basic mime-type with attribute charset with value taken from the fluid default-text-charset. The plist contents depend on lead (a symbol):

type

The plist has two keys, type and charset.

(fully-specified 'type "text/plain")
⇒ (type "text/plain" charset "UTF-8")
anything else

The plist has one key, lead, and one value, a string combining mime-type with the charset attribute.

(fully-specified 'Content-Type "text/html")
⇒ (Content-Type "text/html;charset=UTF-8")

If mime-type does not start with ‘text/’, behave exactly like list, i.e., return a plist with one key, lead, and one value, mime-type.

(fully-specified 'type "image/jpeg")
⇒ (type "image/jpeg")

(fully-specified 'Content-Type "image/jpeg")
⇒ (Content-Type "image/jpeg")

Next: (www server-utils cgi-prep), Previous: (www server-utils form-2-form), Up: The (www *) Modules   [Contents][Index]