diff -urN ../htmllint.orig/tagslist.cgi ./tagslist.cgi
--- ../htmllint.orig/tagslist.cgi Sat Sep 8 01:00:00 2012
+++ ./tagslist.cgi Thu Sep 13 13:00:00 2012
@@ -151,13 +151,11 @@
$CHARSET = 'ISO-2022-JP';
}
}
-if ($TAGSLIST) {
- # 規則ファイルの日付を調べる
- $RULETIME = (stat($0))[9];
- foreach (keys %doctypes) {
- my $t = (stat($RULEDIR.$_.'.rul'))[9];
- $RULETIME = $t if $RULETIME < $t;
- }
+# 規則ファイルの日付を調べる
+$RULETIME = (stat($0))[9];
+foreach (keys %doctypes, 'common') {
+ my $t = (stat($RULEDIR.$_.'.rul'))[9];
+ $RULETIME = $t if $RULETIME < $t;
}
$rule = 'all' unless $rule;
$| = 1;
@@ -166,7 +164,18 @@
'|NUMBERS|NAMES|NMTOKENS|NUTOKENS|ID|IDREF|ENTITY';
$internalElem = '#\d+';
-if ($tag) {
+if (!$nocgi &&
+ defined($ifModifiedSince = &str2time($ENV{'HTTP_IF_MODIFIED_SINCE'})) &&
+ $ifModifiedSince >= $RULETIME) {
+ # HTTPの要件(rfc2616 10.3.5)では、この場合はContent-Typeなどの
+ # エンティティヘッダを出力すべきではないとされているが、
+ # CGIの要件(rfc3875 6.2.1)では、最低でもContent-Typeは出力する必要がある。
+ print qq|Status: 304 Not Modified\x0D\x0A|,
+ qq|Content-Type: text/html; charset=$CHARSET\x0D\x0A\x0D\x0A|;
+} elsif (!$nocgi && $ENV{'REQUEST_METHOD'} eq 'HEAD') {
+ # メッセージボディを返さないことを除いてGETと同じ(rfc2616 9.4)
+ &PrintHTTPHeader;
+} elsif ($tag) {
$tag = "\U$tag";
&SelectTAGSLIST($tag);
&PrintHTTPHeader unless $TAGSLIST;
@@ -561,7 +570,11 @@
sub PrintHTTPHeader
{
- print qq|Content-Type: text/html; charset=$CHARSET\x0D\x0A\x0D\x0A| unless $nocgi;
+ unless ($nocgi) {
+ my $modtime = &time2str($RULETIME);
+ print qq|Last-Modified: $modtime\x0D\x0A|,
+ qq|Content-Type: text/html; charset=$CHARSET\x0D\x0A\x0D\x0A|;
+ }
}
sub PrintHTMLHeader
{
@@ -606,6 +619,40 @@
}
##############################################################
+# HTTP::Date互換日付変換ルーチン
+
+sub time2str
+{
+ my $time = shift;
+# $time = time unless defined($time);
+ sprintf('%s, %02d %s %d %s GMT', @{[split(/\s+/, gmtime($time))]}[0,2,1,4,3]);
+}
+
+sub str2time
+{
+ my $str = shift;
+ return undef unless defined($str);
+ my $MoY = 'Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec';
+ my @tm;
+
+ # HTTP::Dateとは異なり、後ろの余計な文字は無視する
+ if ($str =~ /^\s*[SMTWF][a-z]{2,}, +(\d\d?) +($MoY) +(\d{4}) +(\d\d):(\d\d):(\d\d) +GMT/) {
+ @tm = ($6, $5, $4, $1, index($MoY,$2)/4, $3); # rfc1123 HTTP format
+ } elsif ($str =~ /^\s*[SMTWF][a-z]{2,}, +(\d\d?)-($MoY)-(\d{2,4}) +(\d\d):(\d\d):(\d\d) +GMT/) {
+ @tm = ($6, $5, $4, $1, index($MoY,$2)/4, $3); # rfc850 HTTP format
+ } elsif ($str =~ /^\s*[SMTWF][a-z]{2,} +($MoY) +(\d\d?) +(\d\d):(\d\d):(\d\d) +(\d{4})/) {
+ @tm = ($5, $4, $3, $2, index($MoY,$1)/4, $6); # ANSI C asctime() format
+ } else {
+ return undef;
+ }
+ return eval {
+ require Time::Local;
+ my $t = Time::Local::timegm(@tm);
+ $t < 0 ? undef : $t;
+ };
+}
+
+##############################################################
sub SelectTAGSLIST
{