/[suikacvs]/messaging/manakai/doc/introduction.ja.html
Suika

Contents of /messaging/manakai/doc/introduction.ja.html

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.4 - (show annotations) (download) (as text)
Mon Apr 1 09:21:23 2002 UTC (22 years, 7 months ago) by wakaba
Branch: MAIN
Changes since 1.3: +2 -2 lines
File MIME type: text/html
*** empty log message ***

1 <?xml version="1.0" encoding="iso-2022-jp"?>
2 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
3 "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
4 <html xml:lang="ja" xmlns="http://www.w3.org/1999/xhtml">
5 <head>
6 <title xml:lang="en">Message::* Perl modules</title>
7 <link rel="index" href="./" />
8 <?xml-stylesheet href="/s/simpledoc"?>
9 <link rel="stylesheet" href="/s/simpledoc" />
10 <link rev="made" href="mailto:w@suika.fam.cx" />
11 <link rel="copyright" href="/c/pd" title="Public Domain." />
12 <meta name="author" content="若葉" />
13 <meta name="keywords" content="Perl, module, pm, Message, RFC 822, RFC 2822, RFC 1036, son-of-RFC 1036, MIME, Usefor, HTTP, CGI, header, field" />
14 </head>
15 <body>
16 <h1>Message::* Perl modules</h1>
17
18 <h2>はじめのはじめに</h2>
19
20 <p>たとえば Perl で書かれた CGI script, それも掲示板なんかには、
21 こんなくだらない code が載っていたりします。</p>
22
23 <pre class="application-x-perl">
24 jcode'convert(*from, "jis");
25 jcode'convert(*subject, "jis");
26 jcode'convert(*message, "jis");
27 open (MAIL, "| $sendmail");
28 print MAIL "From: $mail ($from)\n";
29 print MAIL "To: $mailto\n";
30 print MAIL "Subject: $subject\n";
31 print MAIL "\n";
32 print MAIL "$message";
33 print MAIL "\n";
34 close (MAIL);
35 </pre>
36
37 <p>これでは視認性も良くないですし、うっかり修正し間違えると
38 変なメッセージを送信してしまいます。
39 (筆者はしょっちゅうはまってました:-)
40 (それに多くの code では、
41 HTML でのクロスサイトスクリプティング (CSS) 問題と
42 類似の問題への対処をしていません。)</p>
43
44 <p>オブジェクト指向を取り入れて次のような感じでメッセージを
45 構成したいところです。</p>
46
47 <pre class="application-x-perl">
48 use Message::Entity;
49 my $msg = new Message::Entity;
50 my $hdr = $msg-&gt;header;
51 $hdr-&gt;add ('From')-&gt;add ('me@bar.example');
52 $hdr-&gt;add ('To')-&gt;add ('foo@bar.example', display_name =&gt; 'Mr. foo');
53 $hdr-&gt;add ('Subject' =&gt; $subject);
54 $msg-&gt;body ($body);
55
56 # $smtp-&gt;send は SMTP で送信する method と仮定。
57 $smtp-&gt;send ($msg);
58 </pre>
59
60 <p><a href="http://www.cpan.org/" xml:lang="en">CPAN</a> を探すと、
61 これに似たようなことができそうなモジュールはあるようですが、
62 実際に使ってみると、与える値によっては <a href="urn:ietf:rfc:822">RFC 822</a>/<a href="urn:ietf:rfc:2822">2822</a> に違反する
63 結果を出力するなどの不満があります。 (例えば今の例で
64 <code xml:lang="en">To:</code> 領域に使っている
65 <code xml:lang="en">display_name</code> で「.」が含まれますが、
66 RFC 2822 的には新しいメッセージでは互換性のため
67 <code xml:lang="en" class="bnf rfc2822">quoted-string</code>
68 にする必要があります。しかしそのまま出力されます。)</p>
69
70 <p class="note">参考: 「.」の場合は RFC 2822 的には正しく解釈
71 されなければなりませんが (出力はすべきでない)、
72 これ以外の文字、例えば制御文字 <code class="character">ESCAPE</code> でも同じようになります。
73 こちらは完全に間違いです。</p>
74 <p class="note">参考: 実装方針としては不正な値はモジュールに
75 渡す前に弾くべきという考え方もあるでしょう。
76 でもそんなのは不便です。</p>
77
78 <p>ということで、はじめは既存のモジュールの wrapper (あるいは補完)
79 を書くつもりでしたが、なんだかごちゃごちゃしていて、
80 それなら車輪の再発明になっても一から書いてみようと考えました。</p>
81
82 <h2>特色 (という程のものでもない。)</h2>
83
84 <ol>
85 <li>結構(謎)オブジェクト指向です。</li>
86 <li>RFC 822/2822 の <code class="bnf rfc2822">group</code> を解釈出来ます。</li>
87 <li><a href="urn:ietf:id:draft-ietf-usefor-msg-id-alt-00">draft-ietf-usefor-msg-id-alt-00</a> に基づいた送信アドレスなどによる <code class="rfc2822">Message-ID</code> を生成出来ます。</li>
88 <li>文字コード独立 (CSI) です。 (但し RFC 822 である都合上(謎)、
89 ASCII 互換である必要はあります。 EBCDIC とかは無理です:-&lt;)</li>
90 </ol>
91
92 <h2>各仕様への対応状況</h2>
93
94 <ol>
95 <li>電子メイルのメッセージ (RFC 822, RFC 2822)
96 の全機能に (抜けが無ければ) 対応しています。
97 但し長さ制限などはチェックしていません。 (MIME の
98 <code class="mime">Content-Transfer-Encoding</code>
99 と一緒に実装予定)</li>
100 <li>電子ニュース記事 (<a href="/uri-res/N2L?urn:ietf:rfc:1036">RFC 1036</a>,
101 <a href="spec/son-of-RFC1036">son-of-RFC1036</a>,
102 <a href="/uri-res/N2L?urn:ietf:id:draft-usefor-article-06">
103 draft-usefor-article (06)</a>) の頭領域の多くに対応しています。</li>
104 <li>MIME の本体部分 (body part) にはまだ対応していません。</li>
105 <li>MIME の追加頭領域
106 (<a href="/uri-res/N2L?urn:ietf:rfc:2045">RFC 2045</a>,
107 <code class="mime">Content-Disposition</code>) に対応しています。
108 パラメーター値拡張 (<a href="/uri-res/N2L?urn:ietf:rfc:2231">RFC 2231</a>)
109 も入出力ともに実装しました。</li>
110 <li>MIME 符号化語 (<code class="mime bnf">encoded-word</code>)
111 の解読に対応しています:-) 但し別途変換処理を指定する必要があります。
112 (<a href="#code">文字コードの扱い</a>参照)</li>
113 <li>HTTP/1.0, HTTP/1.1, CGI/1.1, CGI/1.2 の頭領域のうち、
114 ごく一部に対応しています。 MHTML の
115 <code class="mime">Content-Location</code> にも対応しています。</li>
116 <li>日付形式では RFC 822/<a href="urn:ietf:rfc:1123">1123</a>,
117 <a href="urn:ietf:rfc:733">RFC 733</a>, asctime, ISO 8601 (HTML)
118 などに対応しています。</li>
119 </ol>
120
121 <h2>制限事項</h2>
122
123 <ol>
124 <li>類似モジュール(謎)のように、ファイル名やファイル・ハンドルを
125 渡して読み込ませることが出来ません。</li>
126 <li>大きなメッセージでも一気に読み込み、全て主記憶領域で
127 保持しています。ですからあまり大きなメッセージの処理には
128 向いていないでしょう。</li>
129 <li><code>CR</code> や <code>LF</code> が単体で出現する場合、
130 正しく処理出来ません。 (<code>CRLF</code> と等価とみなします。)
131 将来の版ではオプションで制御可能になるかもしれません。</li>
132 <li>あったら良さそうな機能が未実装かもしれません。
133 (<a href="mailto:w@suika.fam.cx">電子メイル</a>などで教えて下さい。)</li>
134 <li>各モジュールのオプション体系があまり整備されていません。
135 (それでも気持ち悪くない程度には体系的だと思います。)</li>
136 <li>説明文 (document) が良い加減です。</li>
137 </ol>
138
139 <h2>今後の予定</h2>
140
141 <ol>
142 <li>電子ニュースの頭領域 (RFC 1036,
143 <a href="spec/son-of-RFC1036">son-of-RFC1036</a>,
144 draft-usefor-article) の完全実装</li>
145 <li><del>MIME の頭領域の実装。</del></li>
146 <li>追加/非標準の頭領域の実装。</li>
147 <li>MIME 本体 (<code class="bnf rfc822">body</code>) の実装。</li>
148 <li><del>文字符号変換のための hook の実装?</del></li>
149 <li>documentation。</li>
150 <li>使用例の作成。</li>
151 </ol>
152
153 <h2>必要環境</h2>
154
155 <ol>
156 <li>Perl (perl 5.6 以降または<span title="human parser">人間解析者</span>:-))
157 <p class="note"><code class="bnf rfc822">comment</code>
158 を表すのに正規表現 <code class="regex">(??{ <var>code</var> })</code>
159 を使っているので、これを解釈出来る、
160 5.6 以降の版である必要があります。</p>
161 </li>
162 <li>Digest::MD2, Digest::MD5, Digest::SHA1
163 <p>Message-ID の生成にこれらを使用する場合のみ、
164 <code>Message::Field::MsgID::MsgID</code> が使います。</p>
165 <p>これらが用意されていない環境ではエラーになるので、
166 (現状では) 上記モジュールの該当部分を書き換えて対処して下さい。</p>
167 </li>
168 <li>文字コード変換処理
169 <p>日本語メッセージを扱うなら必須でしょう。
170 詳しくは<a href="#code">文字コードの扱い</a>
171 の章をご参照下さい。</p>
172 </li>
173 </ol>
174
175 <h2>入手</h2>
176
177 <p>suika.fam.cx の SSH account をお持ちの場合、 CVS から入手出来ます。</p>
178
179 <p class="example">$ cvs -d :ext:<var xml:lang="en">username</var>@suika.fam.cx:/home/cvs -d perl/lib/Message/</p>
180
181 <p>Web からも取り出せます。 &lt;<a href="/gate/cvs/perl/lib/Message/">http://suika.fam.cx/gate/cvs/perl/lib/Message/</a>&gt; (tarball で一括取得も出来ます。)</p>
182
183 <h2>ライセンス</h2>
184
185 <p>Message::* Perl modules は自由ソフトウェアです。
186 GNU GPL に従って利用出来ます。詳しくは各ファイルを御覧下さい。</p>
187
188 <h2>参考文献</h2>
189
190 <ul>
191 <li><a href="spec/">関連する仕様書 (RFC, Internet-Draft 等)</a></li>
192 </ul>
193
194 <h2 id="code">文字コードの扱い</h2>
195
196 <p>卑しいことで頭を悩ますのは嫌なので(藁)、
197 Message::* は符号化方法独立 (CSI) を目指して実装しています。
198 (但し ASCII のしがらみだけは断ち切っていません:-))
199 0x00 〜 0x7F が ASCII (または ASCII と見なして良いもの) である
200 場合は、 Message::* を通したことでデータが壊れることは
201 無いと思います。</p>
202
203 <p>(もちろん、 RFC 822 など各仕様に照らして正統(的)で
204 ある必要があります。 <code class="bnf rfc822">atom</code>
205 に8ビット・コードが含まれていると正しく扱えません。)
206 (早い話が、 <code class="bnf rfc822">quoted-string</code>
207 などでは8ビット透過だということです。回りくどくてごめんなさい。)</p>
208
209 <p>既定の状態では文字コードに関係する変換処理は行われません。
210 しかし、フック関数っぽいもの(謎)を指定することで、
211 変換処理をさせられます。</p>
212
213 <p>指定出来るフック関数っぽいものは2種類です。
214 <code>DECODER</code> は、元のメッセージを解析する時
215 (<code class="perl">parse ()</code>) に適宜呼び出されます。
216 <code>ENCODER</code> は、メッセージとして文字列化する際
217 (<code class="perl">stringify ()</code> など) に適宜呼び出されます。</p>
218
219 <p>これらの関数は、当然、当該処理が呼び出される前に指定しておく
220 必要があります。
221 <samp class="perl">Message::Entity-&gt;parse</samp> などする前に
222 定義しておくと良いでしょう。</p>
223
224 <pre class="example perl">
225 require Message::MIME::Charset;
226 $Message::MIME::Charset::DECODER{'*default'} = sub {jcode::euc ($_[1])};
227 $Message::MIME::Charset::ENCODER{'*default'} = sub {jcode::jis ($_[1], 'euc')};
228 </pre>
229
230 <p>この例では、 jcode.pl を変換処理に使います。
231 (もちろん、既に <code class="perl">require</code>
232 されていると仮定しています。)</p>
233 <p>最初の <code class="perl">require</code> で、変換処理を担当している
234 <code class="perl">Message::MIME::Charset</code> を読み込みます。
235 (こうしておかないと、後から既定値 (= 無変換) で
236 <code class="perl">*default</code> が上書きされてしまいます。)</p>
237
238 <p>この code を使ったスクリプトは内部処理を日本語 EUC
239 で行うと仮定しています。ですから、 <code class="perl">DECODER</code>
240 で日本語 EUC に変換します。</p>
241 <p>また、日本語メッセージでは <code>ISO-2022-JP</code>
242 を使うのが慣習ですから、 <code class="perl">ENCODER</code>
243 では 7ビット JIS に変換しています。</p>
244 <p>処理を行う関数は、引数が2つ以上与えられます。
245 1つ目の引数は呼び出した class module, いわゆる
246 <code class="perl">$self</code> です。(この場合 self ではありませんが:-)
247 でも普通は必要ないでしょう。</p>
248 <p>2つ目の引数は処理対象の文字列です。</p>
249 <p>3つ目以降の引数は、追加オプションのハッシュです。
250 ただし、現在追加オプションは定義されていません。</p>
251 <p>関数が返す値は(今のところ)一つだけです。
252 処理が終わった文字列です。変換結果として何もなくなってしまったら、
253 もちろん空文字列を返して構いません。 (<code class="perl">undef</code>
254 よりも空文字列の方が望ましいでしょう。)</p>
255
256 <p>さて、上記の例では「<code>*default</code>」の EN/DECODER
257 を指定しましたが、ここには代わりに charset 名を指定出来ます。</p>
258
259 <pre class="perl example">
260 $Message::MIME::Charset::DECODER{'iso-2022-jp'} = sub {jcode::euc ($_[1], 'jis')};
261 </pre>
262
263 <p>ここでは、 <code>ISO-2022-JP</code> を内部コードに変換する
264 方法を定義しています。 charset 名 (および「<code>*default</code>」
265 は必ず小文字で書いて下さい!)</p>
266 <p>MIME body や、 encoded-word, RFC 2231 の拡張パラメーター値
267 など、 charset が指定されている時はその charset 名の変換関数が
268 呼び出されます。 (指定された charset 名の変換関数が未定義の時は、
269 何も処理しません。) これ以外の場面では、 <code>*default</code>
270 で定義された関数が使われます。</p>
271
272 <p>最後に、日本語メッセージを扱う際の例を挙げておきます。</p>
273
274 <pre class="example perl">
275 <span class="comment">## jcode.pl を使用</span>
276 require 'jcode.pl';
277 require Message::MIME::Charset;
278 $Message::MIME::Charset::DECODER{'*default'} = sub {jcode::euc ($_[1])};
279 $Message::MIME::Charset::DECODER{'iso-2022-jp'} = sub {jcode::euc ($_[1], 'jis')};
280 $Message::MIME::Charset::DECODER{'euc-jp'} = sub {$_[1]};
281 $Message::MIME::Charset::DECODER{'shift_jis'} = sub {jcode::euc ($_[1], 'sjis')};
282 $Message::MIME::Charset::ENCODER{'*default'} = sub {
283 my $s = $_[1];
284 <span class="comment">## 正規化</span>
285 jcode::tr(\$s,
286 "\xa3\xb0-\xa3\xb9\xa3\xc1-\xa3\xda\xa3\xe1-\xa3\xfa\xa1\xf5".
287 "\xa1\xa4\xa1\xa5\xa1\xa7\xa1\xa8\xa1\xa9\xa1\xaa\xa1\xae".
288 "\xa1\xb0\xa1\xb2\xa1\xbf\xa1\xc3\xa1\xca\xa1\xcb\xa1\xce".
289 "\xa1\xcf\xa1\xd0\xa1\xd1\xa1\xdc\xa1\xf0\xa1\xf3\xa1\xf4".
290 "\xa1\xf6\xa1\xf7\xa1\xe1\xa2\xaf\xa2\xb0\xa2\xb2\xa2\xb1".
291 "\xa1\xe4\xa1\xe3\xA1\xC0\xA1\xA1"
292 => '0-9A-Za-z&amp;,.:;?!`^_/|()[]{}+$%#*@=\'"~-&gt;&lt;\\ ');
293 jcode::jis ($s, 'euc', 'z')
294 };
295 </pre>
296
297 <pre class="example perl">
298 <span class="comment">## Jcode.pm を使用</span>
299 use Jcode;
300 require Message::MIME::Charset;
301 $Message::MIME::Charset::DECODER{'*default'} = sub {jcode::euc ($_[1])};
302 $Message::MIME::Charset::DECODER{'iso-2022-jp'} = sub {Jcode->new ($_[1], 'jis')->euc};
303 $Message::MIME::Charset::DECODER{'euc-jp'} = sub {$_[1]};
304 $Message::MIME::Charset::DECODER{'shift_jis'} = sub {Jcode->new ($_[1], 'sjis')->euc};
305 $Message::MIME::Charset::DECODER{'utf-8'} = sub {Jcode->new ($_[1], 'utf8')->euc};
306 $Message::MIME::Charset::ENCODER{'*default'} = sub {Jcode-&gt;new ($_[1], 'euc')-&gt;jis};
307 $Message::MIME::Charset::ENCODER{'utf-8'} = sub {Jcode-&gt;new ($_[1], 'euc')-&gt;utf8};
308 </pre>
309
310 <p>Perl 5.8 で Encode モジュールが使えるようになれば、
311 もっと楽になると期待しています。</p>
312
313 <div class="navigation">
314 [<a href="/" title="このサーバーの首頁">/</a>
315 <a href="/map" title="このサーバーの案内" rel="index">地図</a>
316 <a href="/search/" title="このサーバーの検索">検索</a>]
317 <a href="http://validator.w3.org/check/referer" xml:lang="en"><img
318 src="http://www.w3.org/Icons/valid-xhtml11" id="w3c-html"
319 alt="Valid XHTML 1.1!" style="height: 31px; width: 88px" /></a>
320 <a href="http://jigsaw.w3.org/css-validator/validator?uri=http://suika.fam.cx/~wakaba/Message-pm/introduction.ja.html" xml:lang="en">
321 <img style="width: 88px; height: 31px" id="w3c-css"
322 src="http://jigsaw.w3.org/css-validator/images/vcss"
323 alt="Valid CSS!" /></a>
324 </div>
325 <div class="update">$Date: 2002/04/01 09:14:50 $</div>
326 <ul class="myuri">
327 <li>&lt;URL:<a href="http://suika.fam.cx/~wakaba/Message-pm/introduction">http://suika.fam.cx/~wakaba/Message-pm/introduction</a>&gt;</li>
328 <li>&lt;CVS:<a href="http://suika.fam.cx/gate/cvs/perl/web/Message-pm/">suika.fam.cx:/home/cvs/perl/web/Message-pm/</a>&gt;</li>
329 </ul>
330 </body></html>

admin@suikawiki.org
ViewVC Help
Powered by ViewVC 1.1.24