新規記事投稿 フォロー記事投稿 記事のキャンセル
From: にあ <nir@mvg.biglobe.ne.jp>
Subject: うぇぶ会議室に存在する2000年問題
Date: 1999/03/06 06:12:50
Reference: mesh.forum.3/00901

3月5日に、かたなさんは書きました。

> 最近ちまたで話題の2000年問題なのですが、この会議室の場合、「contents」
>ファイルに4桁の年を書き込んでいますね。

2000年問題ですか。(^^;;
内部的な時間の扱いは全て4桁年か通し秒数ですので2000年問題は無いのですが、
外部とのインターフェースの部分に一部問題となる部分があります。

> で、そのcgiの231行目に1900+$yearで年を取っているように見られ
>ます。これでは2000年の場合1900になってしまうのでしょうか...

これに付いては、石堂さんがフォローした下さった通り問題無いです。

問題となるのは、user Agentが2桁年を渡してきた場合です。

うぇぶ会議室は If-Modified-Since: リクエストヘッダを見ますが、
この時渡される日時のフォーマットには次の3種があります。

Fri, 05 Mar 1999 20:31:07 GMT   ; RFC822による定義 (RFC1123により更新)
Friday, 05-Mar-99 20:31:07 GMT  ; RFC850による定義だが、RFC1036により廃棄
Fri Mar  5 20:31:07 1999        ; ANSI C asctime()の書式

サーヴァが自分で返すフォーマットは最初のものが望ましく、HTTP/1.1では最初の
ものでなければならないとされていますが、受ける方は過去との互換性を保つ上で
3種全てを解釈できなくてはなりません。

# うぇぶ会議室の生成する日時のフォーマットは、もちろんRFC1123のものです。(^^)
# ここ(Biglobe)のサーヴァ(Netscape-Commerce/1.12)は古いRFC850のを
# 返すので、ヘッダの日時フォーマットは新旧混ざって出力されていますが。(^^;;

一見して分かるとおり、RFC850の日時のフォーマットは2桁年を使うので2000年問題が
存在します。で、実際 forum.pl の中の解釈ルーティンでは2桁年には単純に1900を
足していたので、2000年には1900年になってしまいます。(^^;;

と、言うことで、forum.pl の 377行付近を以下のように変えて下さい。

	$wday = &http'wdaytoi($swday);
	$year += 100 if ($year <= 38);
	$year -= 1900 if ($year >= 1900);

赤字の行が追加された行です。

つまり、、2桁年が渡された場合には、00〜38年だったら2000〜2038年、
39〜99年だったら1939〜1999年と思おう、と言うことです。
# 少々 ad hoc ではありますが。

をっ、日時ルーティンを眺めていたら、もう一つバグを見つけてしまった。(^^;
ANSI C 対応の日付のマッチングは現在のパターンでは1〜9日にマッチしないですね。

そのチョット前の373行付近の、

	($swday, $smon, $mday, $hour, $min, $sec, $year) =
		/^(\w+) (\w+) (\d+) (\d+):(\d+):(\d+) (\d+)/ if ($sec eq '');

の所を、

	($swday, $smon, $mday, $hour, $min, $sec, $year) =
		/^(\w+) (\w+) +(\d+) (\d+):(\d+):(\d+) (\d+)/ if ($sec eq '');

にして下さい。(^^;;;

# まぁ、ほとんどの場合、user agentはRFC1123の日時を渡してくるので、
# 問題は起きないんですけどね。