source: project/release/3/mime/trunk/doc.scm @ 7686

Last change on this file since 7686 was 5248, checked in by hans, 14 years ago

version 1.3: factored out mime-get-attributes from mime-parse-content-type, added a missing backslash in mime-parse-version regexp

File size: 15.7 KB
Line 
1;; eggdoc for mime.egg
2
3(use eggdoc)
4
5(define mime-license
6  `(pre #<<EOF
7Copyright (c) 2000-2004 Shiro Kawai, All rights reserved.
8
9Redistribution and use in source and binary forms, with or without
10modification, are permitted provided that the following conditions
11are met:
12
131. Redistributions of source code must retain the above copyright
14   notice, this list of conditions and the following disclaimer.
15
162. Redistributions in binary form must reproduce the above copyright
17   notice, this list of conditions and the following disclaimer in the
18   documentation and/or other materials provided with the distribution.
19
203. Neither the name of the authors nor the names of its contributors
21   may be used to endorse or promote products derived from this
22   software without specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
25"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
26LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
27A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
28OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
29SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
30TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
31PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
32LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
33NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
34SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
35EOF
36))
37
38(define mime-write-example
39  '(pre #<<EOF
40(mime-part-write
41 (make-mime-part
42  #:type "multipart"
43  #:subtype "mixed"
44  #:headers
45  '(("from" "test <test@test.com>")
46    ("to"   "foo <foo@bar.com>")
47    ("mime-version" "1.0")
48    ("subject" "a test")
49    ("message-id" "<test123@test.com>"))
50  #:content
51  (list
52   (make-mime-part
53    #:transfer-encoding "quoted-printable"
54    #:content
55    "This = a simple test.")
56   (make-mime-part
57    #:type "application" #:subtype "octet-stream"
58    #:transfer-encoding "base64"
59    #:content "a simple test"))))
60EOF
61))
62
63(define mime-write-example-output
64  '(pre #<<EOF
65From: test <test@test.com>
66To: foo <foo@bar.com>
67Mime-Version: 1.0
68Subject: a test
69Message-Id: <test123@test.com>
70Content-Type: multipart/mixed;boundary="MIME-Message-Boundary-"
71Content-Transfer-Encoding: 7bit
72
73This message is in MIME format.
74
75--MIME-Message-Boundary-
76Content-Type: text/plain
77Content-Transfer-Encoding: quoted-printable
78
79This =3D a simple test.
80--MIME-Message-Boundary-
81Content-Type: application/octet-stream
82Content-Transfer-Encoding: base64
83
84YSBzaW1wbGUgdGVzdA==
85
86--MIME-Message-Boundary---
87EOF
88))
89
90(define doc
91  `((eggdoc:begin
92     (name "mime")
93     (description "Parse MIME Messages.")
94     (author "Shiro Kawai, Chicken-port and some additions by Hans Bulfone")
95     (history
96      (version "1.0" "Initial release")
97      (version "1.1" "Generating MIME messages")
98      (version "1.2" "fixed .setup script to handle change in argument processing of csc")
99      (version "1.3" "Added mime-get-attributes (suggested by Moe Aboulkheir)"))
100     (requires "rfc822"
101               "base64"
102               "iconv")
103     (usage)
104     (download "mime.egg")
105     
106     (documentation
107      (p "This documentation is based on Gauches "
108         (tt "rfc.mime") " and " (tt "rfc.quoted-printable")
109         " documentation with some changes where the Chicken version differs.")
110      (p "This egg provides utility procedures to handle "
111         "Multipurpose Internet Mail Extensions (MIME) messages, "
112         "defined in RFC2045 through RFC2049. This egg is "
113         "supposed to be used with the " (tt "rfc822") " egg.")
114
115      (subsection "Quoted-printable encoding/decoding"
116       (p "A few functions to encode/decode Quoted-printable format, "
117          "defined in RFC2045, section 6.7.")
118       (group
119        (procedure "(quoted-printable-encode)"
120         "Reads a byte stream from the current input port, encodes it in "
121         "Quoted-printable format and writes the result character stream "
122         "to the current output port. The conversion ends when it reads "
123         (tt "#!eof") " from the current input port.")
124
125        (procedure "(quoted-printable-encode-string STRING)"
126         "Converts the contents of " (tt "STRING") " to Quoted-printable "
127         "encoded format. The input string can be either a complete or "
128         "incomplete string; it is always interpreted as a byte sequence.")
129
130        (procedure "(quoted-printable-decode)"
131         "Reads characters from the current input port, decodes them from "
132         "Quoted-printable format and writes the result byte stream to the "
133         "current output port. The conversion ends when it reads "
134         (tt "#!eof") ". If it encounters illegal character sequences "
135         "(such as " (tt "#\\=") " followed by non-hexadecimal characters), "
136         "it copies them literally to the output.")
137
138        (procedure "(quoted-printable-decode-string STRING)"
139         "Decodes a Quoted-printable encoded string " (tt "STRING") " and "
140         "returns the result as a string.")))
141
142      (subsection "Utilities for header fields"
143       (p "A few utility procedures to parse MIME-specific header fields.")
144       (group
145        (procedure "(mime-parse-version FIELD)"
146                   "If " (tt "FIELD") " is a valid header field for "
147                   "MIME-Version, returns its major and minor versions "
148                   "in a list. Otherwise, returns " (tt "#f") ". "
149                   "It is allowed to pass " (tt "#f") " to " (tt "FIELD")
150                   ", so that you can directly pass the result of "
151                   (tt "rfc822-header-ref") " to it. Given a parsed header "
152                   "list from " (tt "rfc822-header->list") ", you can get "
153                   "the MIME version (currently, it should be " (tt "(1 0)")
154                   ") by the following code:"
155                   (pre "(mime-parse-version (rfc822-header-ref headers \"mime-version\"))")
156                   "Note: simple regexp such as " (tt "\"\\d+\\.\\d+\"") " doesn't "
157                   "do this job, for " (tt "FIELD") " may contain comments between tokens.")
158        (procedure "(mime-get-attributes INPUT)"
159                   "Reads an attribute/value list in the form "
160                   (tt ";attr1=value1;attr2=value2") " from " (tt "INPUT")
161                   " (which should be an open input-port) and returns it as an alist.")
162        (procedure "(mime-parse-content-type FIELD)"
163                   "Parses the \"content-type\" header field, and "
164                   "returns a list such as:"
165                   (pre "(type subtype (attribute . value) ...)")
166                   "where " (tt "type") " and " (tt "subtype") " are "
167                   "MIME media type and subtype in a string, respectively."
168                   (pre "(mime-parse-content-type \"text/html; charset=iso-2022-jp\")\n"
169                        "=> (\"text\" \"html\" (\"charset\" . \"iso-2022-jp\"))")
170                   "If " (tt "FIELD") " is not a valid content-type field, "
171                   (tt "#f") " is returned.")
172        (procedure "(mime-decode-word WORD)"
173                   "Decodes RFC2047-encoded word. If " (tt "WORD") " isn't an "
174                   "encoded word, it is returned as is."
175                   (pre "(mime-decode-word \"=?iso-8859-1?q?this=20is=20some=20text?=\")\n"
176                        "=> \"this is some text\""))))
177
178      (subsection
179       "Streaming parser"
180       (p "The streaming parser is designed so that you can decide "
181          "how to do with the message body before the entire message is read.")
182       (group
183        (procedure "(mime-parse-message PORT HEADERS HANDLER)"
184          (p "The fundamental streaming parser. " (tt "PORT") " is an "
185             "input port from where the mssage is read. " (tt "HEADERS")
186             " is a list of headers parsed by " (tt "rfc822-header->list")
187             "; that is, this procedure is supposed to be called after "
188             "the header part of the message is parsed from port:")
189
190          (pre "(let* ((headers (rfc822-header->list port)))\n"
191               "  (if (mime-parse-version (rfc822-header-ref headers \"mime-version\"))\n"
192               "     ;; parse MIME message\n"
193               "     (mime-parse-message port headers handler)\n"
194               "     ;; retrieve a non-MIME body\n"
195               "     ...))")
196
197          (p (tt "mime-parse-message") " analyzes headers, and calls "
198             (tt "HANDLER") " on each message body with two arguments:")
199
200          (pre "(HANDLER PART-INFO XPORT)")
201
202          (p (tt "PART-INFO") " is a " (tt ":mime-part") " record described "
203             "below that encapsulates the information of this part of the "
204             "message. " (tt "XPORT") " is an input port, initially points "
205             "to the beginning of the body of message. The handler can "
206             "read from the port as if it is reading from the original port. "
207             "However, " (tt "XPORT") " recognizes MIME boundary internally, "
208             "and returns " (tt "#!eof") " when it reaches the end of the "
209             "part. (Do not read from the original port directly, or it will "
210             "mess up the internal state of " (tt "XPORT") ").")
211
212          (p (tt "HANDLER") " can read the part into the memory, or save it "
213             "to the disk, or even discard the part. Whatever it does, it has "
214             "to read from " (tt "XPORT") " until it returns " (tt "#!eof") ".")
215
216          (p "The return value of handler will be set in the content slot "
217             "of " (tt "PART-INFO") ". If the message has nested multipart "
218             "messages, " (tt "HANDLER") " is called for each \"leaf\" part, "
219             "in depth-first order. " (tt "HANDLER") " can know its nesting "
220             "level by examining " (tt "PART-INFO") " record. The message "
221             "doesn't need to be a multipart type; if it is a MIME message "
222             "type, " (tt "HANDLER") " is called on the body of enclosed "
223             "message. If it is other media types such as " (tt "text") " or "
224             (tt "application") ", " (tt "HANDLER") " is called on the "
225             "(only) message body."))
226
227        (record ":mime-part"
228          (p "A SRFI-9 record that encloses metainformation about a "
229             "MIME part. It is constructed when the header of the part is "
230             "read, and passed to the handler that reads the body of the "
231             "part.")
232
233          (p "The following procedures for manipulating " (tt ":mime-part")
234             "-records exist:")
235
236          (group
237           (procedure "(make-mime-part #:type TYPE #:subtype STYPE #:parameters PARAMS #:transfer-encoding TENC #:parent P #:index I #:headers HDRS #:content C #:attrs ATTRS"
238             "Create a " (tt ":mime-part") "-record.  The arguments default "
239             "to " (tt "\"text\"") ", " (tt "\"plain\"") ", " (tt "'()") ", "
240             (tt "\"7bit\"") ", " (tt "#f") ", " (tt "0") ", " (tt "'()") ", "
241             (tt "#f") ", and " (tt "'()") ".")
242
243           (procedure "(mime-part:type PART-INFO)")
244           (procedure "(mime-part:type-set! PART-INFO TYPE)"
245             "MIME media type string. If " (tt "content-type") " header is "
246             "omitted to the part, an appropriate default value is set.")
247
248           (procedure "(mime-part:subtype PART-INFO)")
249           (procedure "(mime-part:subtype-set! PART-INFO SUBTYPE)"
250             "MIME media subtype string. If " (tt "content-type") " header "
251             "is omitted to the part, an appropriate default value is set.")
252
253           (procedure "(mime-part:parameters PART-INFO)")
254           (procedure "(mime-part:parameters-set! PART-INFO PARAMETERS)"
255             "Associative list of parameters given to " (tt "content-type")
256             " header field.")
257
258           (procedure "(mime-part:transfer-encoding PART-INFO)")
259           (procedure "(mime-part:transfer-encoding-set! PART-INFO TRANSFER-ENCODING)"
260             "The value of the " (tt "content-transfer-encoding") " header "
261             "field. If the header field is omitted, an appropriate default "
262             "value is set.")
263
264           (procedure "(mime-part:parent PART-INFO)")
265           (procedure "(mime-part:parent-set! PART-INFO PARENT)"
266             "If this is a part of multipart message or encapsulated message, "
267             "points to the enclosing part's " (tt ":mime-part") " record. "
268             "Otherwise " (tt "#f") ".")
269
270           (procedure "(mime-part:index PART-INFO)")
271           (procedure "(mime-part:index-set! PART-INFO INDEX)"
272             "Sequence number of this part within the same parent.")
273
274           (procedure "(mime-part:headers PART-INFO)")
275           (procedure "(mime-part:headers-set! PART-INFO HEADERS)"
276             "The list of header fields, as parsed by "
277             (tt "rfc822-header->list") ".")
278
279           (procedure "(mime-part:content PART-INFO)")
280           (procedure "(mime-part:content-set! PART-INFO CONTENT)"
281             "If this part is " (tt "multipart/*") " or " (tt "message/*")
282             " media type, this slot contains a list of parts within it. "
283             "Otherwise, the return value of handler is stored.")
284
285           (procedure "(mime-part:attrs PART-INFO)")
286           (procedure "(mime-part:attrs-set! PART-INFO ATTRS)"
287             "This alist provides a place for the message parser/generator "
288             "or the application to store additional information. "
289             "At the moment, only the " (tt "'qp-encode-binary?")
290             " attribute is used by the quoted-printable encoder to decide "
291             "if the content should be treated as binary.")))
292
293        (procedure "(mime-retrieve-body PART-INFO XPORT OUTP)"
294          (p "A procedure to retrieve a message body. It is intended to be "
295             "a building block for a handler to be passed to "
296             (tt "mime-parse-message") ".")
297
298          (p (tt "PART-INFO") " is a " (tt ":mime-part") " record. "
299             (tt "XPORT") " is an input port passed to the handler, "
300             "from which the MIME part can be read. This procedure reads "
301             "from " (tt "XPORT") " until it returns " (tt "#!eof") ". "
302             "It also looks at the " (tt "transfer-encoding") " of "
303             (tt "PART-INFO") ", and decodes the body accordingly; that is, "
304             "base64 encoding and quoted-printable encoding is handled. "
305             "The result is written out to an output port " (tt "OUTP") ".")
306
307          (p "This procedure does not handle charset conversion. The caller "
308             "can use facilities from the " (tt "charconv") " and/or "
309             (tt "iconv") " modules if conversion is desired.")))
310
311       (p "A couple of convenience procedures are defined for typical cases "
312          "on top of " (tt "mime-retrieve-body") ".")
313
314       (group
315        (procedure "(mime-body->string PART-INFO XPORT)")
316        (procedure "(mime-body->file PART-INFO XPORT FILENAME)"
317          "Reads in the body of mime message, decoding transfer encoding, "
318          "and returns it as a string or writes it to a file, respectively.")))
319
320      (subsection
321       "Message generator"
322       (p "The message generator generates a RFC822/MIME message out of "
323          (tt ":mime-part") " objects.")
324
325       (group
326        (procedure "(mime-part-write PART-INFO)"
327          (p "Formats " (tt "PART-INFO") " as a MIME message and writes "
328             "the result to the current output port.")
329          (p (tt "PART-INFO") " may describe a single mail body or a "
330             (tt "multipart/*") " or " (tt "message/*") " hierarchy.")
331          (p "For multipart messages a boundary may be given in "
332             (tt "(mime-part:parameters PART-INFO)") " which will be "
333             "used as a base for the message boundary (but modified "
334             "if needed).")
335          (p "If " (tt "(mime-part:transfer-encoding PART-INFO)")
336             " specifies " (tt "\"base64\"") " or " (tt "\"quoted-printable\"")
337             " the body is encoded accordingly; else it is put into the "
338             "message literally."))
339
340        (procedure "(mime-part->string PART-INFO)"
341          (p "Like " (tt "(mime-part-write)") " but returns the message as a "
342             "string.")))))
343     
344     (examples
345      (p "The simplest form of MIME message parser would be like this:")
346
347      (pre "(let ((headers (rfc822-header->list port)))\n"
348           "  (mime-parse-message port headers\n"
349           "                      (cut mime-body->string <> <>)))\n")
350
351      (p "This reads all the message on memory (i.e. the \"leaf\" "
352         (tt ":mime-part") " records' content fields would hold the "
353         "part's body as a string), and returns the top " (tt ":mime-part")
354         " record. Content transfer encoding is recognized and handled, "
355         "but character set conversion isn't done.")
356
357      (p "You may want to feed the message body to a file directly, or even "
358         "want to skip some body according to mime media types and/or other "
359         "header information. Then you can put the logic in the handler "
360         "closure. That's the reason that this module provides building "
361         "blocks, instead of all-in-one procedure.")
362
363      (p "A simple MIME-Message could be generated as follows:")
364      ,mime-write-example
365      ,mime-write-example-output)
366
367     (license ,mime-license))))
368
369(eggdoc->html doc)
Note: See TracBrowser for help on using the repository browser.