[PREVIOUS CHAPTER]
1 HTML形式の記事を作成する


[アブストラクト]
MLにながれる記事をHTML形式で"も"作成します。つまりMLのホームには
「spoolディレクトリの下に普通の記事、htdocsの下にHTML化された記事」が
作られます。スレッドのindexも作ります。WWWサーバにとっては単にファイル
を読むだけなので負担が軽いです。でもCGIではないので高度なことができた
りしません。


(たぶん2.1以前からのUPGRADEの人への)注意: 
HTML を作る場所ですが、デフォールトでは var/htdocs -> htdocs/ に変わっ
ています。var は nobody 等へpermission を出していないからです。

このルーチンは htdocs/ の下に記事をHTMLファイルとして成し適当に 
index.html や thread.html を再生成しています。そのため運用ポリシーとし
てWWWサーバでCGIなどが使えない場合(使いたくない場合)にも問題はありませ
ん。一般にCGIの方が自由度は高いでしょうが、普通WWW管理者はセキュリティ
的にそういうものは使わせたくないし、一つ記事を読むたびに毎回プログラム
が走ると重たいということもあります。fmlの方式はそういう事情に左右され
ませんが、そのために支払わねばならないトレードオフは当然あります。

1.1	自動的に スプールを html 化する(Expireはしない)
../utility_programs 6.20

$AUTO_HTML_GEN = 1; をセットすると、自動的にHTML化された記事も作ります。
作る場所は $DIR の下の $HTML_DIR (デフォールトは htdocs) という場所で
す。この時普通のPLAINTEXTのスプール($SPOOL_DIRへ溜る)も同時に作ってい
ます。

HTML化の実体は HOOK で呼び出されます。fml.pl の中から外部の 
SyncHTMLfiles.pl を呼んでやらせるのは美しくないので;-)、HOOK でやれる
ように書き直しました。
注意: libsynchtml.pl により SyncHtml.pl は obsolete になりました

記事は htdocs/ の下に階層構造を作りその下に作られます。階層構造は日や
記事番号100通ごとなどを単位にしています。単位は $HTML_INDEX_UNIT で決
められます。

Example:

	htdocs/
	htdocs/19980120/
	htdocs/19980120/1.html
	htdocs/19980120/2.html
	.....

1.2	&SyncHtml($HTML_DIR, $ID, *Envelope);

SYNOPSIS:

	&SyncHtml($HTML_DIR, $ID, *Envelope);

	$HTML_DIR 	生成されたHTMLを置く場所
	$ID		記事番号は &Distribute; で
			グローバル変数 $ID はセットされる。
	*Envelope	%Envelope

Example: 

	$FML_EXIT_HOOK .= q#;
		&use('synchtml');
		$HTML_DIR = 'htdocs';
		&SyncHtml($HTML_DIR, $ID, *Envelope);
	#;

&SyncHtml を走らせると

	htdocs/index.html 
	htdocs/ID.html 

を生成します。index.html の中身は LIST 構造を成しています。

	<UL>
	<LI>
	<A HREF=1310.html>
	96/09/16 18:12:33 Subject
	</A>


$HTML_INDEX_REVERSE_ORDER がセットされていると逆方向に <LI> エントリを
作ります。つまり新しい記事が最初に来るわけです。

この時各 directory の .indexcache にキャッシュされているデータから生成
しています。ファイル .indexcache は $HTML_DATA_CACHE で変更できます。

またスレッドを生成するためのキャッシュのファイル名は $HTML_DATA_THREAD 
です。

同じライブラリを呼んで同じことをするコマンドラインからのためのインター
フェイスに spool2html.pl というのもあります。
../utility_programs 6.20
../utility_programs 6.20

1.3	HTML化する単位 (数 or 日)

	$HTML_INDEX_UNIT (default is 'day')

	設定できる値:

		"day"
		"week"
		"month"
		"infinite"
		number (e.g. 100, 1000, ...)

現在の標準実装のデフォールトは $HTML_INDEX_UNIT = 'day'; です。

もしexpireしない場合一つの htdocs/ に数千のファイルができることになり
かねません。これよりはファイル100個ごと、もしくは日ごとにdirectoryをま
とめておくなどが見やすいでしょう。

Example: Creation of HTML articles on 1996/09/16

	htdocs/19960916/index.html
	htdocs/19960916/100.html
	htdocs/19960916/101.html
	...

のように 1996/09/16 日のMLの記事を htdocs/19960916/ 以下にHTML化
します。

また $HTML_INDEX_UNIT = 数字; (e.g. 100)とした場合は記事100個ごとに別
のdirectoryを作ります。

Example:

	htdocs/100/
	htdocs/100/101.html
	htdocs/100/102.html
	...
	htdocs/200/
	htdocs/200/201.html
	htdocs/200/202.html
	...

1.4	$HTML_INDEX_UNIT == "infinite"

日などでわけずに一つの directory に作る。$HTML_DIR 直下に生成する。
トラフィックが多く数万個の記事ディレクトリ直下にできてしまうことが想定
されるようなケースでは非現実的なので使うべきでない(いろいろな整合性チェッ
クの時間だけで馬鹿にならない)。

1.5	thread.html; スレッド化した index を作成する

スレッド化 HTML (libsynchtml.pl)

	$HTML_THREAD = 1; 

にするとスレッド化したインデックスファイルとして thread.html を作りま
す。両方を作るので好きな階層を見ればいいでしょう。スレッドには 
In-Reply-To: と References: の依存関係を使っています。そういうものをつ
けない MUA を使ってる人からのメールだけはうまく動きません。

	thread.html
	index.html
		SUB-DIRECTORY/thread.html
		SUB-DIRECTORY/index.html
	...

このように両方のファイルが作られ別の階層が形成されるので、見る人にはどっ
ちか好きな方をたどってみてもらえば良いでしょう。

$HTML_INDENT_STYLE (default "UL")はスレッドを作る際に使うHTMLのスタイ
ル?です。現在あるスタイルは『文法<UL>を段をずらすために利用するか?』
か否か?だけです。

$HTML_THREAD_REF_TYPE は依存関係の作り方のタイプです。デフォールトでは
References: In-Reply-To: のすべてのリファレンスへリンクをはります。た
とえ thread.html の中で重複していてもです。リンクは一つだけを選びたい
なら

	$HTML_THREAD_REF_TYPE = "prefer-in-reply-to"; (3.0 default)

と設定すると、
	1.	In-Reply-To: 
	2.	In-Reply-To: がない時は References: に現れる最後のID
を前の記事とみなすようにします。

1.6	Variables to Customize HTML File 

           $HTML_FORMAT_PREAMBLE

		(default) 先頭から <HEAD> まで
		<TITLE>あたり

           $HTML_DOCUMENT_SEPARATOR
		(default) </HEAD><BODY>

		本体

           $HTML_FORMAT_TRAILER

		</BODY></HTML> (default) 

index.html 用には

	$INDEX_HTML_DOCUMENT_SEPARATOR
	$INDEX_HTML_FORMAT_PREAMBLE
	$INDEX_HTML_FORMAT_TRAILER

という変数が用意されています。

メーリングリストの記事のどのヘッダを表示するかは @HtmlHdrFieldsOrder 
で決まります。が $HTML_HEADER_TEMPLATE という変数を使うと 
@HtmlHdrFieldsOrder は無視され、$HTML_HEADER_TEMPLATE だけが書き込まれ
ます。

1.7	HTML 4.0

HTML 4.0 については

	From: TAMURA Kent <kent@hauN.org>
	fml-support: 04153

のパッチをほとんどそのまんま使っています。# ありがとう _o_

$HTML_STYLESHEET_BASENAME はスタイルシートのファイルです。sub
directory の下に html ファイルが作られることを考慮して設定して下さい。
例:

	$HTML_STYLESHEET_BASENAME = "../fml.css";

A style sheet example is automatically installed under automatic html
generation.

1.8	HTMLファイルのExpire

	$HTML_EXPIRE_LIMIT	(default 0)

expire の“日”数。もし0以下ならおこなわない。これが指定されていない
ときは index.html は増える一方:-)
#注意: $HTML_EXPIRE はわかりにくいので $HTML_EXPIRE_LIMIT へ名前を変えた。
#      なお内部では自動変換しているのでどっちでも動く

なお今のアルゴリズムは以下のようなものです。htdocs の下は

	thread.html
	index.html
		SUB-DIRECTORY/thread.html
		SUB-DIRECTORY/index.html
		SUB-DIRECTORY/100.html
		…

のような階層を成しています。今はファイル単位ではなく sub-directory ご
とに expire するか否かを決定しています。
そうしないと中途半端に記事が欠落するとか、中途半端にファイルがなくなっ
た状態で thread を再生成しなければならないので、ものすごく複雑な処理が
必要になるからです。

directory ごと expire する根拠はdirectory 中に含まれる全てのファイルが 
expire だと判定された場合です。よって、ある directory 中の一部のファイ
ルが expire の日付を過ぎていてもそれらは全てのファイルが expire される
まで残り続けることに注意して下さい。なお directory ごと消す時にだけ一
番上の index.html thread.html は再構成されます。

また expire 処理の overhead がかなりかかります。また directory 単位なの
に毎回 expire するべきか?の判定処理をしてもしょうがありません。デフォー
ルトは投稿数に対し $HTML_EXPIRE_LIMIT * 5 回に一回 expire code は走り
ます。この値は $HTML_EXPIRE_SCAN_UNIT で変更できます。

1.9	BASE64 Decoding

base64 で encode されたものがあった場合$BASE64_DECODE という変数に定義
された base64 decoder を使って展開しその結果をHTMLの中に埋め込みます。
なお展開した結果はFMLが勝手につけた名前でファイルに落されます。
ユーザが与えた名前は security 上使いません。

Example:
	$BASE64_DECODE = "/usr/local/bin/mewdecode";

明示的に $BASE64_DECODE を定義されたない場合は bin/base64decode.pl が
使われます。(2.2A#11以降)
../utility_programs 6.3
../utility_programs 6.3

1.10	$HTML_OUTPUT_FILTER

index.html を作る時 $HTML_OUTPUT_FILTER というプログラムを通してから作
る。具体的には 日本語漢字変換やMIME,BASE64 decoder 等が該当するだろう。

1.11	$HTML_TITLE_HOOK

HTMLに変換された記事をファイルに保存する直前に実行されるフック。

例:

	q#$HtmlTitle = sprintf("%s %s", $Now, $HtmlTitle);#;

で、タイトルのシンタックスを日付を付け加える等…変えられる。

1.12	キーワードによるHTML化の自動分類 (今の実装でOKか未確認?)


1.13	&TalkWithHttpServer

SYNOPSIS:
	&TalkWithHttpServer($host, $port, $request, $tp, *e); 

	$host		ホスト		(e.g. www.iij.ad.jp)
	$port		ポート番号	(70, 80, 21, ...)
	$request	リクエストの内容
	$tp		TYPE OF PROTOCOL (http, gopher, ftp, ...)
	*e		答えを入れるためのstab

http:// で始まらない時には、デフォールトで聞きにいくサーバを

	$DEFAULT_HTTP_SERVER

で、またデフォールトを80から変えたい時は

	$DEFAULT_HTTP_PORT 

で変更できます。同様に gopher についても

	$DEFAULT_GOPHER_SERVER
	$DEFAULT_GOPHER_PORT 

という変数が用意されています。

Example:

    if ($tp =~ /http/i) {
	$host = $host || $DEFAULT_HTTP_SERVER;
	$port = $port || $DEFAULT_HTTP_PORT || 80;

	# connect http server
	&Mesg(*e, ">>> HREF=$tp://$host$request\n");
	&TalkWithHttpServer($host, $port, $request, $tp, *e); 
	&Mesg(*e, ">>> ENDS HREF=$tp://$host$request\n");
    } 

1.14	URLの中身を返すサーバ

一番単純なやり方は

$START_HOOK = q#
    require 'libhref.pl';
    &HRef($Envelope{'Body'}, *Envelope);
    $DO_NOTHING =1;
#;

です。こうするとメール本文をコマンドレポートの形で送り返します。

1.15	HRef関数によるURL先データの引き落とし

SYNOPSIS:
    &HRef($request, *Envelope);

$request のURLの内容を$Envelope{'message'}に入れて送り返す。
$request は

	http://
	gopher://
	ftp://

を理解します。ftp はローカル or ftpmailへのリレーへ自動的に切替えます。
また、もしバイナリデータの場合はuuencodeして送り返します。

1.16	NOTE: Special Character (libsynchtml.pl)

特殊文字

ASCII(or ISO 8859)コードの中の4つのキャラクタは HTMLでは特別な意味を持つため、
そのままでは使用できない。 4つのキャラクタとは、<, >, & と " である。

< と > はタグを示すために使用され、 & は、以下のキャラクタやその他のキャラクタ
のための エスケープシーケンスとなっている。

    &lt;
      <

    &gt;
      > のエスケープシーケンス

    &amp;
      & のエスケープシーケンス

    &quot;
      " のエスケープシーケンス

エスケープシーケンスとは、各キャラクタを表示するために必要な文字列であり、 そ
れぞれ ; が必ず必要。

その他にも、8bitキャラクタをサポートするために以下のような エスケープシーケン
スが用意されている。

注意: この文書は日本語で書かれているため、以下の例では正しく表示されない可能性
がある。

    &ouml;
      小文字の o にウムラルトのエスケープシーケンス

    &ntilde;
      小文字の n にチルダのエスケープシーケンス

    &Egrave;
      大文字の E にグレーブ・アクセントのエスケープシーケンス

このようなエスケープシーケンスに関してはCERN からリストが提供されてい
るのでそちらを参照していただきたい。