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


16 (www data mime-types)

The (www data mime-types) module maintains an internal hash table mapping filename extensions to one or more mime-types.

The exported procedures provide convenience abstractions over the underlying hash-table manipulation operations, including extension and mime-type validation, init from a file in a “standard” format (i.e., that of /etc/mime.types or ~/.mime.types), and support for straightforward incremental init (aka merging). There are two predefined entries in the hash table:

text => text/plain
html => text/html

To support merging, the put-FOO procedures both take a symbol resolve as the first arg, which specifies how conflicts should be handled. This happens when the hash table already contains an entry for extension and new-mime-type differs from old-mime-type.

error

Throw an error with key mime-type-conflict, displaying a message describing the extension, old-mime-type and new-mime-type.

prefix

Make the mime-type of extension a list (unless already one), with new-mime-type at the beginning.

suffix

Make the mime-type of extension a list (unless already one), with new-mime-type at the end.

stomp

Use new-mime-type directly, discarding old-mime-type.

quail

Discard new-mime-type, keeping old-mime-type.

For any other method, the operation throws an error, with key invalid-resolve.

Validation happens on all “put” operations. The extension must be a symbol, such as txt. The mime-type must be a symbol with exactly one ‘/’ (slash) in its name, such as text/plain, or a proper list of such symbols. The mime-type may also be #f, which means to remove extension from the hash table.

If an entry does not validate, the operation throws an error, with key invalid-extension or invalid-mime-type.

Procedure: reset-mime-types! size

Clear all entries from the mime-types hash table, and prepare it for size (approximately) entries. This procedure must be called before any others in this module.

Procedure: put-mime-types-from-file! resolve filename

Open filename and parse its contents as “mime-types” format. This line-oriented file format is briefly described as follows:

  • Blank lines and lines beginning with ‘#’ are ignored.
  • Lines of the format mime-type (only one symbol) are ignored.
  • Otherwise, the line is expected to be in the format mime-type extension extension, that is, at least one extension must be present. Each extension results in an entry in the hash table.

Put those those entries that specify an extension into the hash table, validating both extension and mime-type first. resolve specifies how to resolve extension conflicts.

Procedure: put-mime-types! resolve [extension1 mime-type1 ...]

Put extension1/mime-type1… into the hash table, validating both extension and mime-type first. resolve specifies how to resolve extension conflicts.

If an extension is given but there is no mime-type (i.e., the list has an odd length), throw an error with key missing-mime-type.

Procedure: mime-types<-extension ext

Return the mime-type(s) associated with ext (a symbol or string), or #f if none are found. Note that generally the value may be a single mime-type or a list of them.

Procedure: select-extensions sel

Return a list of extensions in the hash table that match the sel criteria (a symbol). If sel is #t, return all the extensions; if single, only those who have a single mime-type associated; if multiple, only those who have more than one mime-type associated.

why select-extensions?

The last procedure is intended to ease non-generalizable merging, without providing too much exposure to implementation internals. Suppose you want to maintain a local policy of having only one mime-type associated per extension (to keep things simple). In that case, after populating the hash, you can fix up those entries, like so:

(reset-mime-types! 491)
(put-mime-types-from-file! 'prefix "/etc/mime.types")
(define AMBIGUOUS (select-extensions 'multiple))

(use-modules (ice-9 format))
(define (display-ext ext)
  (format #t "~7,@A  ~A~%" ext (mime-types<-extension ext)))

(for-each display-ext AMBIGUOUS)
    ent  (chemical/x-ncbi-asn1-ascii chemical/x-pdb)
    sdf  (application/vnd.stardivision.math chemical/x-mdl-sdfile)
     sh  (application/x-sh text/x-sh)
    csh  (application/x-csh text/x-csh)
    cpt  (application/mac-compactpro image/x-corelphotopaint)
    asn  (chemical/x-ncbi-asn1 chemical/x-ncbi-asn1-spec)
    wrl  (model/vrml x-world/x-vrml)
    tcl  (application/x-tcl text/x-tcl)
     ra  (audio/x-pn-realaudio audio/x-realaudio)
    spl  (application/futuresplash application/x-futuresplash)
    m3u  (audio/mpegurl audio/x-mpegurl)

;; Local policy: For foo.wrl, we want the last variant,
;; but everything else we'll settle for the first.
(define ((keep! yes) ext)
  (put-mime-types!
   'stomp ext
   (yes (mime-types<-extension ext))))

((keep! reverse) 'wrl)
(for-each (keep! car) AMBIGUOUS)

(for-each display-ext AMBIGUOUS)
    asn  chemical/x-ncbi-asn1
    wrl  x-world/x-vrml
    tcl  application/x-tcl
     ra  audio/x-pn-realaudio
    spl  application/futuresplash
    m3u  audio/mpegurl
    ent  chemical/x-ncbi-asn1-ascii
    sdf  application/vnd.stardivision.math
     sh  application/x-sh
    csh  application/x-csh
    cpt  application/mac-compactpro

Seasoned schemers will note that the same result could have been achieved if resolve were allowed to be a general resolution procedure instead of simply a method specifier. Perhaps that feature will be added in the future, and select-extensions replaced by map-mime-types. We’ll see…


Next: GNU Free Documentation License, Previous: (www data http-status), Up: The (www *) Modules   [Contents][Index]