diff -urN ../htmllint.orig/htmllint.cgi ./htmllint.cgi
--- ../htmllint.orig/htmllint.cgi Fri Apr 25 03:16:29 2014
+++ ./htmllint.cgi Sun May 4 00:30:00 2014
@@ -6,8 +6,8 @@
=ignore
use strict;
use vars qw($VERSION $PROGNAME);
-use vars qw($RULEDIR $LOGSDIR $TMPDIR $IMGDIR $TAGSLIST $HTMLDIR $GATEWAYURL $EXPLAIN $CGIROOT $IMGROOT $HTMLLINTRC $HTMLEXT $INDEXHTML @REJECTREFERER @EXCEPTDOMAINS @PERMITDOMAINS $PERMITPRIVATEIP $NOUSELWP $NOUSEJCODE $MAXHTMLSIZE $TIMEOUT $HTTP_PROXY @HTTP_NOPROXY $GETLOCALFILE $KANJICODE $LYNX $W3M $SCOREFILE $SCORECOUNTER $STATFILE @EXCEPTSCORES $COUNTER $NOCOMMERCIAL $AUTOSCORE);
-use vars qw($HTML $HTMLSIZE $LOCALFILE $URL $RURL @OPT $RESULT $TXTCODE $STYLE $SCRIPT $RULE $FILE $PIPE $WARNS $SCORE $KIND $TAGS $STAT $LANG $outCODE $CHARSET $CTYPE $MIME $TextView $LWPUA $URLGETVer);
+use vars qw($RULEDIR $LOGSDIR $TMPDIR $IMGDIR $TAGSLIST $HTMLDIR $GATEWAYURL $EXPLAIN $CGIROOT $IMGROOT $HTMLLINTRC $HTMLEXT $INDEXHTML @REJECTREFERER @EXCEPTDOMAINS @PERMITDOMAINS $ACCEPTIRI $PERMITPRIVATEIP $NOUSELWP $NOUSEJCODE $MAXHTMLSIZE $TIMEOUT $HTTP_PROXY @HTTP_NOPROXY $GETLOCALFILE $KANJICODE $LYNX $W3M $SCOREFILE $SCORECOUNTER $STATFILE @EXCEPTSCORES $COUNTER $NOCOMMERCIAL $AUTOSCORE);
+use vars qw($HTML $HTMLSIZE $LOCALFILE $URL $RURL $IRI @OPT $RESULT $TXTCODE $STYLE $SCRIPT $RULE $FILE $PIPE $WARNS $SCORE $KIND $TAGS $STAT $LANG $outCODE $CHARSET $CTYPE $MIME $TextView $LWPUA $URLGETVer);
use vars qw(%in $stdio %doctypes $defaultrule %whines $icode $counter $err %warn %whinesStat %seenTagsStat %seenTagsKind %seenMultiBody %statistics %statSeenTags %statKindTags %statMultiBody $statstart $statsample $seensample);
=cut
@@ -141,18 +141,29 @@
}
if ($cgi->param('Method') =~ /^(?:Data|File)$/oi) {
- $RURL = $URL = '';
+ $RURL = $IRI = $URL = '';
} else {
$URL = $cgi->param('URL');
# AbsoluteURLで前後の空白は除去されるが
# 以下のコードではAbsoluteURLを通らない場合があるので
$URL =~ s/^\s*//;
$URL =~ s/\s*$//;
+ $IRI = $URL;
# 日本語文字が含まれている$URLをエラーメッセージの中に表示する場合に備え、
# $URLの文字コードをスクリプトの文字コード($myCODE)に合わせておく。
# さもないとフォームの文字コードが$myCODEと異なる場合に文字化けが起こる。
&Jconvert(\$URL, $myCODE, $formCODE);
+ # HTTP::Requestへ渡すために、$URLをperl内部形式utf8テキストへ変換したものを
+ # $IRIとして別に用意する
+ if ($ACCEPTIRI && $Jcode && $] >= 5.008) {
+ &Jconvert(\$IRI, 'utf8', $formCODE); # Jcode.pm必要
+ utf8::decode($IRI); # perl内部形式へ変換 (perl v5.8.0 〜)
+ } else {
+ $ACCEPTIRI = 0;
+ $IRI = $URL;
+ }
+
# フォームのURL入力欄へ誤ってHTMLそのものをコピペしてしまう人への対処。
# これが週に2人ぐらいの割合でいる。これを除外しないと、AbsoluteURLで
# 絶対URLに変換されWebサーバへのアクセスが発生してしまう場合もあるので。
@@ -172,8 +183,10 @@
# 他にも、UNCパスを表すfile:指定はやや特殊な構文になっているので、
# URL中の連続する/を一つにまとめられると動作しなくなってしまう。
# 除外条件:フォームの初期値(http://)・http:以外の絶対URI・Windowsパス/UNCパス
- $URL = &htmllint::AbsoluteURL($ENV{HTTP_REFERER}, $URL)
- if $URL =~ m#^https?:(?!//$)#oi || $URL !~ m#^([\w.+-]*:|\\\\)#oi;
+ if ($URL =~ m#^https?:(?!//$)#oi || $URL !~ m#^([\w.+-]*:|\\\\)#oi) {
+ $URL = &htmllint::AbsoluteURL($ENV{HTTP_REFERER}, $URL);
+ $IRI = &htmllint::AbsoluteURL($ENV{HTTP_REFERER}, $IRI);
+ }
$RURL = $URL;
}
@@ -259,12 +272,21 @@
unless ($scheme =~ /^http/i) {
&ErrorExit($msgInURL.&HrefURL($URL).$msgCantGet);
}
- if (&Jgetcode(\$host) =~ /^(jis|euc|sjis|utf8)$/) {
+ # IRIへの対応は、LWPが内部で利用しているURIモジュールの働きによる(IRI対応はURI-1.50から)
+ # ASCII以外の文字が含まれる文字列をURLとして与えれば、自動的にIRIとして認識される
+ # 日本語文字を正しく認識させるには、utf8フラグがセットされたUTF-8文字列を与えればよい
+ my $USELWP = (!$NOUSELWP &&
+ eval('require LWP::UserAgent') && eval('require HTTP::Request'));
+ if ($ACCEPTIRI && !($USELWP && $LWP::VERSION >= 5.40 && $URI::VERSION >= 1.50)) {
+ $ACCEPTIRI = 0;
+ $IRI = $URL;
+ }
+ if (!$ACCEPTIRI && &Jgetcode(\$host) =~ /^(jis|euc|sjis|utf8)$/) {
# 対応UAが普及したことで国際化ドメイン名の使用も徐々に増加している。
# ASCII以外の文字を使用できるWebアドレスはIRI(RFC3987)という別規格であって、
# 厳密に言うとURLにASCII以外の文字を使用できないことに変わりはない。
# html5やxhtml1.1では文書中にIRIを使用できる。
- my $noIDN = 'Another HTML-lint では国際化ドメイン名に対応していません。'.
+ my $noIDN = 'このサーバでは国際化ドメイン名は扱えません。'.
'ドメイン名をPunycodeエンコードされた形式で指定してください。';
&ErrorExit($msgInURL.&HrefURL($URL).$msgCantGet.$noIDN);
}
@@ -319,8 +341,7 @@
}
}
# HTMLを読み込んで改行を変換してテンポラリに書く
- if (!$NOUSELWP &&
- eval('require LWP::UserAgent') && eval('require HTTP::Request')) {
+ if ($USELWP) {
$URLGETVer = "LWP $LWP::VERSION";
$LWPUA = new LWP::UserAgent;
# $LWPUA->agent の既定値は libwww-perl/$LWP::VERSION だが、
@@ -334,10 +355,11 @@
$LWPUA->proxy('http', "http://$HTTP_PROXY/") if $HTTP_PROXY;
$LWPUA->no_proxy(@HTTP_NOPROXY) if @HTTP_NOPROXY;
$LWPUA->parse_head(0);
- my $req = new HTTP::Request GET => $URL;
+ my $req = new HTTP::Request GET => $IRI;
# $req->header('Accept' => 'text/html, application/xhtml+xml, */*;q=0.1');
$req->header('Accept' => 'text/html, application/xhtml+xml'); # 20090427
- if ($host =~ m#^//(.+)#o) { $req->header('Host' => $1); }
+ #'Host'は HTTP::Request の内部で自動的に設定される(そもそも必須ヘッダですから)
+ #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;
@@ -461,8 +483,9 @@
'ファイルが存在しないか、ディレクトリ(フォルダ)の読み取りが許可されていません。';
$STAT = '';
} else {
- if (&Jgetcode(\$URL) =~ /^(jis|euc|sjis|utf8)$/) {
- $msgErr = 'URLに日本語などのASCII以外の文字を使うことはできません。';
+ if (!$ACCEPTIRI && &Jgetcode(\$URL) =~ /^(jis|euc|sjis|utf8)$/) {
+ $msgErr = 'このサーバでは国際化URL(IRI)は扱えません。'.
+ '通常のURLに日本語などのASCII以外の文字を使うことはできません。';
} elsif ($STAT =~ /^\s*2\d\d/) {
if (!$existHTML || $RESULT =~ /^X-Died:/oim) {
# LWP内部でコンテントのファイルへのセーブに失敗した場合は、
diff -urN ../htmllint.orig/htmllintenv ./htmllintenv
--- ../htmllint.orig/htmllintenv Tue Oct 16 08:20:00 2012
+++ ./htmllintenv Sun May 4 00:30:00 2014
@@ -50,6 +50,10 @@
# プライヴェートIPを許す (禁止するときコメントアウト)
#$PERMITPRIVATEIP = 1;
+# URL入力欄でIRI (国際化URL) を認識させる
+# LWP および Jcode.pm の使用必須、加えてURI-1.50以降・perl v5.8.0以降が必要です
+$ACCEPTIRI = 1;
+
# LWP や Jcode.pm の使用を制限する (制限したいときコメントを外す)
#$NOUSELWP = 1;
#$NOUSEJCODE = 1;