262 lines
9.8 KiB
Racket
262 lines
9.8 KiB
Racket
#lang scribble/doc
|
|
@(require "common.rkt" scribble/struct
|
|
(for-label net/mime net/mime-unit net/mime-sig))
|
|
|
|
@(define-syntax-rule (mime-table (type (sub-type0 ref0) (sub-type ref) ...) ...)
|
|
(let ([spacer (hspace 1)]
|
|
[to-flow (lambda (e)
|
|
(make-flow (list (make-paragraph (list e)))))])
|
|
(make-table
|
|
#f
|
|
(append
|
|
(list
|
|
(list (to-flow (racket 'type))
|
|
(to-flow spacer)
|
|
(to-flow (racket 'sub-type0))
|
|
(to-flow spacer)
|
|
(to-flow ref0))
|
|
(list (to-flow spacer)
|
|
(to-flow spacer)
|
|
(to-flow (racket 'sub-type))
|
|
(to-flow spacer)
|
|
(to-flow ref))
|
|
...)
|
|
...))))
|
|
|
|
@title[#:tag "mime"]{MIME: Decoding Internet Data}
|
|
|
|
@defmodule[net/mime]{The @racketmodname[net/mime] library provides
|
|
utilities for parsing and creating MIME encodings as described in RFC
|
|
2045 through RFC 2049.
|
|
|
|
The library was written by Francisco Solsona.}
|
|
|
|
@; ----------------------------------------
|
|
|
|
@section{Message Decoding}
|
|
|
|
@defproc[(mime-analyze [message-in (or/c bytes? input-port)]
|
|
[part? any/c #f])
|
|
message?]{
|
|
|
|
Parses @racket[message-in] and returns the parsed result as a
|
|
@racket[message] instance.
|
|
|
|
If @racket[part?] is @racket[#f], then @racket[message-in] should
|
|
start with the header for a full message; otherwise,
|
|
@racket[message-in] should start with the header for a part within a
|
|
message.}
|
|
|
|
@defstruct[message ([version real?]
|
|
[entity entity]
|
|
[fields (listof string?)])]{
|
|
|
|
A decoded MIME message. The version is @racket[1.0] by default. The
|
|
@racket[entity] field represents the message data. The @racket[fields]
|
|
field contains one string for each field in the message header.}
|
|
|
|
@defstruct[entity ([type symbol?]
|
|
[subtype symbol?]
|
|
[charset symbol?]
|
|
[encoding symbol?]
|
|
[disposition disposition?]
|
|
[params (listof (cons/c symbol? string?))]
|
|
[id string?]
|
|
[description string?]
|
|
[other (listof string?)]
|
|
[fields (listof string?)]
|
|
[parts (listof message?)]
|
|
[body (or/c (output-port? . -> . void?) null?)])]{
|
|
|
|
Represents the content of a message or a sub-part. The
|
|
@racket[mime-analyze] function chooses default values for fields
|
|
when they are not specified in input.
|
|
|
|
Standard values for the @racket[type] field include @racket['text],
|
|
@racket['image], @racket['audio], @racket['video],
|
|
@racket['application], @racket['message], and @racket['multipart].
|
|
|
|
Standard values for the @racket[subtype] field depend on the
|
|
@racket[type] field, and include the following, but any
|
|
@racket[subtype] is allowed as a downcased version of the
|
|
specification from the header.
|
|
|
|
@mime-table[
|
|
(
|
|
text (plain "[RFC1521, NSB]")
|
|
(richtext "[RFC1521, NSB]")
|
|
(tab-separated-values "[Lindner]")
|
|
)(
|
|
multipart (mixed "[RFC1521, NSB]")
|
|
(alternative "[RFC1521, NSB]")
|
|
(digest "[RFC1521, NSB]")
|
|
(parallel "[RFC1521, NSB]")
|
|
(appledouble "[MacMime, Faltstrom]")
|
|
(header-set "[Crocker]")
|
|
)(
|
|
message (rfc822 "[RFC1521, NSB]")
|
|
(partial "[RFC1521, NSB]")
|
|
(external-body "[RFC1521, NSB]")
|
|
(news "[RFC 1036, Spencer]")
|
|
)(
|
|
application (octet-stream "[RFC1521, NSB]")
|
|
(postscript "[RFC1521, NSB]")
|
|
(oda "[RFC1521, NSB]")
|
|
(atomicmail "[atomicmail, NSB]")
|
|
(andrew-inset "[andrew-inset, NSB]")
|
|
(slate "[slate, Crowley]")
|
|
(wita "[Wang Info Transfer, Campbell]")
|
|
(dec-dx "[Digital Doc Trans, Campbell]")
|
|
(dca-rft "[IBM Doc Content Arch, Campbell]")
|
|
(activemessage "[Shapiro]")
|
|
(rtf "[Lindner]")
|
|
(applefile "[MacMime, Faltstrom]")
|
|
(mac-binhex40 "[MacMime, Faltstrom]")
|
|
(news-message-id "[RFC1036, Spencer]")
|
|
(news-transmission "[RFC1036, Spencer]")
|
|
(wordperfect5.1 "[Lindner]")
|
|
(pdf "[Lindner]")
|
|
(zip "[Lindner]")
|
|
(macwriteii "[Lindner]")
|
|
(msword "[Lindner]")
|
|
(remote-printing "[RFC1486,MTR]")
|
|
)(
|
|
image (jpeg "[RFC1521, NSB]")
|
|
(gif "[RFC1521, NSB]")
|
|
(ief "[RFC1314]")
|
|
(tiff "[MTR]")
|
|
)(
|
|
audio (basic "[RFC1521, NSB]")
|
|
)(
|
|
video (mpeg "[RFC1521, NSB]")
|
|
(quicktime "[Lindner]")
|
|
)]
|
|
|
|
Standard values for the @racket[charset] field include
|
|
@racket['us-ascii], which is the default.
|
|
|
|
Standard values for the @racket[encoding] field are @racket['7bit],
|
|
@racket['8bit], @racket['binary], @racket['quoted-printable], and
|
|
@racket['base64]. The default is @racket['7bit].
|
|
|
|
The @racket[params] field contains a list of parameters from other
|
|
MIME headers.
|
|
|
|
The @racket[id] field is taken from the @racket["Content-Id"] header
|
|
field.
|
|
|
|
The @racket[description] field is taken from the
|
|
@racket["Content-description"] header field.
|
|
|
|
The @racket[other] field contains additional (non-standard) field
|
|
headers whose field names start with @racket["Content-"].
|
|
|
|
The @racket[fields] field contains additional field headers whose
|
|
field names @emph{do not} start with @racket["Content-"].
|
|
|
|
The @racket[parts] contains sub-parts from multipart MIME
|
|
messages. This list is non-empty only when @racket[type] is
|
|
@racket['multipart] or @racket['message].
|
|
|
|
The @racket[body] field represents the body as a function that
|
|
consumes an output out and writes the decoded message to the port. If
|
|
@racket[type] is @racket['multipart] or @racket['message]., then
|
|
@racket[body] is @racket['()]. All of the standard values of
|
|
@racket[encoding] are supported. The procedure only works once (since
|
|
the encoded body is pulled from a stream).}
|
|
|
|
@defstruct[disposition ([type symbol?]
|
|
[filename (or/c string? false/c)]
|
|
[creation (or/c string? false/c)]
|
|
[modification (or/c string? false/c)]
|
|
[read (or/c string? false/c)]
|
|
[size (or/c exact-nonnegative-integer? false/c)]
|
|
[params (listof (cons/c symbol? string?))])]{
|
|
|
|
Represents a @racket["Content-Disposition"] header as defined in RFC
|
|
2183.
|
|
|
|
Standard values for the @racket[type] field include @racket['inline]
|
|
and @racket['attachment].
|
|
|
|
The @racket[filename] field is drawn from the @racket["filename"]
|
|
parameter of the @racket["Content-Disposition"] header, if included in
|
|
the message.
|
|
|
|
The @racket[creation], @racket[modification], and @racket[read] fields
|
|
represent file timestamps as drawn from the @racket["creation-date"],
|
|
@racket["modification-date"], and @racket["read-date"] attributes of
|
|
the @racket["Content-Disposition"] header, if included in the message.
|
|
|
|
The @racket[size] field is drawn from the @racket["size"] parameter of
|
|
the @racket["Content-Disposition"] header, if included in the message.
|
|
|
|
The @racket[params] field stores any additional attribute bindings of
|
|
the @racket["Content-Disposition"] header, if included in the message.}
|
|
|
|
@; ----------------------------------------
|
|
|
|
@section[#:tag "mime-exns"]{Exceptions}
|
|
|
|
@defstruct[(mime-error exn:fail) ()]{
|
|
|
|
The supertype of all MIME exceptions. Only the subtype
|
|
@racket[missing-multipart-boundary-parameter] is ever actually
|
|
raised.}
|
|
|
|
@defstruct[(unexpected-termination mime-error) ([msg string?])]{
|
|
|
|
Originally raised when an end-of-file is reached while parsing the
|
|
headers of a MIME entity, but currently a mere warning is logged.}
|
|
|
|
@defstruct[(missing-multipart-boundary-parameter mime-error) ()]{
|
|
|
|
Raised when a multipart type is specified, but no @racket["Boundary"]
|
|
parameter is given.}
|
|
|
|
@defstruct[(malformed-multipart-entity mime-error) ([msg string?])]{
|
|
|
|
Never actually raised.}
|
|
|
|
@defstruct[(empty-mechanism mime-error) ()]{
|
|
|
|
Never actually raised.}
|
|
|
|
@defstruct[(empty-type mime-error) ()]{
|
|
|
|
Never actually raised.}
|
|
|
|
|
|
@defstruct[(empty-subtype mime-error) ()]{
|
|
|
|
Never actually raised.}
|
|
|
|
|
|
@defstruct[(empty-disposition-type mime-error) ()]{
|
|
|
|
Never actually raised.}
|
|
|
|
@; ----------------------------------------
|
|
|
|
@section{MIME Unit}
|
|
|
|
@margin-note{@racket[mime@] and @racket[mime^] are deprecated.
|
|
They exist for backward-compatibility and will likely be removed in
|
|
the future. New code should use the @racketmodname[net/mime] module.}
|
|
|
|
@defmodule[net/mime-unit]
|
|
|
|
@defthing[mime@ unit?]{
|
|
|
|
Imports nothing, exports @racket[mime^].}
|
|
|
|
@; ----------------------------------------
|
|
|
|
@section{MIME Signature}
|
|
|
|
@defmodule[net/mime-sig]
|
|
|
|
@defsignature[mime^ ()]{}
|
|
|
|
Includes everything exported by the @racketmodname[net/mime] module.
|