diff -urN ../htmllint.orig/htmllint.cgi ./htmllint.cgi
--- ../htmllint.orig/htmllint.cgi Tue Oct 16 08:20:00 2012
+++ ./htmllint.cgi Tue Dec 24 03:00:00 2013
@@ -216,6 +216,17 @@
} elsif ($WIN && $URL =~ /^(\w:|\\\\)/o) {
$LOCALFILE = $URL;
}
+ } else {
+ # ブラウザのアドレスバーから何も考えずにコピペする人が多いのか、
+ # 公開サーバでローカルファイルを指定してくる人が後を絶たない。
+ # ファイルアップロードの使い方を知らないものと思われるので、
+ # (もし知っていればそもそもローカルファイルなんて指定しないはず)
+ # ファイルアップロードチェックを使うように案内を出す。
+ if ($URL =~ /^(file:|\w:|\\\\)/oi) {
+ my $noLocal = 'ローカルファイルやネットワークファイルは指定できません。そのようなファイルをチェック'.
+ 'するには、チェック方式FILEを使用して該当のファイルをアップロードしてください。';
+ &ErrorExit($msgInURL.&HrefURL($URL).$msgCantGet.$noLocal);
+ }
}
if (defined($LOCALFILE)) {
# ローカルファイルを取得
@@ -234,10 +245,21 @@
unless ($scheme =~ /^http/i) {
&ErrorExit($msgInURL.&HrefURL($URL).$msgCantGet);
}
+ if (&Jgetcode(\$host) =~ /^(jis|euc|sjis|utf8)$/) {
+ # 対応UAが普及したことで国際化ドメイン名の使用も徐々に増加している。
+ # ASCII以外の文字を使用できるWebアドレスはIRI(RFC3987)という別規格であって、
+ # 厳密に言うとURLにASCII以外の文字を使用できないことに変わりはない。
+ # html5やxhtml1.1では文書中にIRIを使用できる。
+ my $noIDN = 'Another HTML-lint では国際化ドメイン名に対応していません。'.
+ 'ドメイン名をPunycodeエンコードされた形式で指定してください。';
+ &ErrorExit($msgInURL.&HrefURL($URL).$msgCantGet.$noIDN);
+ }
$host = $1 if $host =~ /\@(.+)$/;
unless ($PERMITPRIVATEIP) {
# Private IP か調べる
- &ErrorExit($msgInHTML.&HrefURL($URL).$msgCantGet) if !CheckPrivateIP($ENV{REMOTE_ADDR}) && CheckPrivateIP($host);
+ my $noPrivIP = '指定できるのは、グローバルIPアドレスでアクセス可能なURLに限られます。';
+ &ErrorExit($msgInHTML.&HrefURL($URL).$msgCantGet.$noPrivIP)
+ if !CheckPrivateIP($ENV{REMOTE_ADDR}) && CheckPrivateIP($host);
}
if (@REJECTREFERER) {
# 拒否REFERER
@@ -300,6 +322,7 @@
if ($host =~ m#^//(.+)#o) { $req->header('Host' => $1); }
my $res = $LWPUA->request($req, $HTML);
$RESULT = $res->status_line()."\n".$res->headers_as_string();
+ ($STAT = "\n".$res->status_line()) =~ s/\s*\(\@INC contains:.+//o;
if ($res->is_success()) {
$RURL = $res->request->url();
my $warning = $res->header('Client-Warning');
@@ -320,7 +343,6 @@
$STYLE = $res->header('Content-Style-Type');
$SCRIPT = $res->header('Content-Script-Type');
} else {
- ($STAT = "\n".$res->status_line()) =~ s/\s*\(\@INC contains:.+//o;
&Unlink;
}
} elsif (eval("require 'httpreq.pl'")) {
@@ -412,11 +434,38 @@
if (!(-e $HTML) || (-z $HTML)) {
# テンポラリファイルがうまくできていない
- my $japURL = (&Jgetcode(\$URL) =~ /^(jis|euc|sjis|utf8)$/)? 'URLに日本語などのASCII以外の文字を使うことはできません。': '';
&Unlink;
- &EscapeRef(\$STAT);
- &EscapeRef(\$FILE);
- &ErrorExit(($URL ne '')? $msgInHTML.&HrefURL($URL).$msgCantGet.$japURL.$STAT: ($FILE ne '')? $msgInFile.$FILE.$msgCantGet: $msgNoData);
+ if ($URL ne '') {
+ my $msgErr = '';
+ if (defined($LOCALFILE)) {
+ $msgErr = '指定されたファイルは'. ((!(-e $HTML))? '存在しません。': '空のファイルです。');
+ $STAT = '';
+ } else {
+ if (&Jgetcode(\$URL) =~ /^(jis|euc|sjis|utf8)$/) {
+ $msgErr = 'URLに日本語などのASCII以外の文字を使うことはできません。';
+ } elsif ($STAT =~ /^\s*2\d\d/) {
+ # 非対応UAに対して空のHTMLを返してくるWebサーバもある(www.rakuten.ne.jpなど)
+ $msgErr = 'Webサーバから空のファイルが返されました。';
+ } elsif ($STAT =~ /^\s*3\d\d/) {
+ # リダイレクトループが発生した場合など
+ $msgErr = 'このURLは別のURLへリダイレクトされていますが、リダイレクト先のHTMLを取得できませんでした。';
+ } elsif ($STAT =~ /^\s*401/) {
+ # LWPでは http://user:pass@host の形式で要認証のHTMLを取得できるようだが、
+ # セキュリティ上は好ましくないのでここでは敢えて言及しない。
+ $msgErr = 'Another HTML-lint では認証を必要とするHTMLの取得には対応していません。';
+ }
+ # エラー原因の特定に役立ちそうなレスポンスヘッダを追加して表示する
+ # Location -> 3xx (LWPがリダイレクトできなかった場合)のリダイレクト先
+ # WWW-Authenticate -> 401 の場合の認証スキームとrealm
+ $STAT = join("\n", $STAT, $RESULT =~ /^(?:Client-Warning|Location|WWW-Authenticate):.*$/oimg);
+ &Jconvert(\$STAT, $myCODE, undef); # realmに日本語が使われている場合があるので
+ }
+ &EscapeRef(\$STAT);
+ &ErrorExit($msgInHTML.&HrefURL($URL).$msgCantGet.$msgErr.$STAT);
+ } else {
+ &EscapeRef(\$FILE);
+ &ErrorExit(($FILE ne '')? $msgInFile.$FILE.$msgCantGet: $msgNoData);
+ }
}
$TextView = lc($cgi->param('LynxView')? 'lynx': $cgi->param('TextView'));
@@ -757,8 +806,10 @@
# 172.16.0.0〜172.31.255.255
# 192.168.0.0〜192.168.255.255
($1==10) || ($1==172 && $2>=16 && $2<32) || ($1==192 && $2==168) ||
- ($1==127 && $2==0 && $3==0); # 127.0.0.*
- } else { 0 }
+ ($1==127); # 127.* (RFC1700, RFC3330)
+ } else {
+ scalar $host =~ m#^(?://)?localhost$#i;
+ }
}
# ドメイン名が指定のものか調べる