Perl+JavaScript+<a href>で謎のエラー

[新着] Webテンプレートを仮オープンしました



0   名前: ウマシカ : 2007/05/05(土) 03:41  ID:hPGqQZMx sub-t1
下記の様なエラーで頭を抱えました。
コンテンツを変えて無理矢理解決しましたが、エラーの原因がハッキリしなくて気持悪いです。
どなたか、この現象について説明が付きますでしょうか。

<条件>
・CGI(Perl)から出力したHTMLの中に
・if〜構文が有り、
・しかも、その中のdocument.write("")の中に<a href>タグが有ると

エラーが出ます。
上の条件のどれか一つでも違う場合は、大丈夫な様ですが、
3つの条件が重なると、関数が動かなくなったりブラウザからエラーが出力されます。

<エラーメッセージの内容>
IE6の「スクリプトエラーごとに通知を表示する」をONにしていると
if〜の行で、「")"がありません」「識別子が有りません」等のアラートが出ます。

リンク先のアドレスくらいは、コンテンツの書き方を変えて他の場所に表記すれば済むので、
<a href>タグを外してしまう事で解決しましたが、エラーの再現パターンがわかるまで苦労しました。
一体、これは何故でしょうか。ifやdocument.writeの書き方に問題があるのでしょうか。
それともIEか何かのバグでしょうか。下記は相談用のサンプルですが、上記の条件が揃っているので、
やはり同じ条件が再現します。CGI出力に使ったのはUNIXベースのAppachで動く無料サーバーです。
CGIで出力していると言っても、ブラウザでソース表示をした時のJavaScriptが化ているわけではありません。
(Perlから出力しているので日本語文字コードはEUCですけど)。
#!/usr/local/bin/perl

$contents= <<EOF;
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=EUC-JP">
<script type="text/javascript"><!--
function test(){
	tmp=1;
	if(tmp==1){
	document.write("<a href=\"http://www.tagindex.com/index.html\">TAGindexを</a>を見ましょう。");
	}else{
	document.write("他にも色々調べてみましょう。");
	}
}
// --></script>
</head>
<body onload="test()">
</body>
</html>
EOF

print "Content-type: text/html\n\n";
print $contents;
exit;

1   名前: Z ◆XTzyosZXcL : 2007/05/05(土) 03:41  ID:tWsRhjqj sub-Cl
 とりあえず、怪しいのは

document.write("<a href=\"http://www.tagindex.com/index.html\">TAGindexを</a>

のところでしょうか。"<a href=\"でいったん文字列がくくられているあとに「http:〜」と続くのが原因だと思います。

関連しそうな過去発言:
http://www.tagindex.com/cgi-lib/q4bbs/patio.cgi?mode=view2&f=1024&no=3

2   名前: ウマシカ : 2007/05/05(土) 03:41  ID:hPGqQZMx sub-t1
有難う御座います。なるほど実体参照を使う方法も研究できそうですね。

でも、やっぱり疑問が・・。
Document.write("")の中にタグが有って、そのタグに"が含まれる場合、
普通は\でエスケープできるハズですが・・。
CGIを使わずディスクに保存したHTMLだけ使う場合は、
定番の手法で、よく下記の様な処理が有りますよね。例えば・・。


[CGIは使わずにHTMLをディスクに保存]
<html><head></head><body>
本文のコンテンツ
<address>
<script type="text/javascript" src="./hooter.js"></script>
<address>
</body></html>

[JSファイル'hooter.js'としてディスクに保存]
document.write("このサイトのトップは<a href=\"./index.html\">こちら</a>です");

これなんか、全くプログラミングがわからない人でも、
タグの仲間として多用していたりする手法だと思います。
私には「同じじゃないか」と思えるのですが・・。

サーバーのディスクにHTMLファイルやJSファイルを保存していようが、
CGIからソースだけ出力していようが、クライアントのメモリーに読込まれるコードは
同じだと思うので・・。この理解が間違っているのでしょうか・・。

3   名前: 匿名 : 2007/05/05(土) 03:41  ID:IB2cj1Mq sub-.G
http://www.tagindex.com/cgi-lib/q4bbs/patio.cgi?mode=view&no=1024
の7辺りが参考になりそうな気がします。
自分だったらたぶんこうします
document.write('このサイトのトップは<a href="./index.html">こちら</a>です');

4   名前: 匿名 : 2007/05/05(土) 03:41  ID:0wLC.8ki sub-Cz
>>0
> document.write("<a href=\"http://www.tagindex.com/index.html\">TAGindexを</a>を見ましょう。");

Perl のヒアドキュメント内ではバックスラッシュが解釈されるんだから
document.write("<a href="http://www.tagindex.com/index.html">TAGindexを</a>を見ましょう。");

と出力されちゃうでしょ。だから >>1、>>3 の言っていることは正しい。

と言うか、JavaScript では「'」と「"」は全く同じ扱い(変数の展開もされない)なんだから、いちいちエスケープなんてしていたら事故の元。>>3 のように使い分けよう。


ついでに補足。

> <body onload="test()">

(on)load イベントはページの関連リソース全てを読み込んだ後に fire するので、それから document.write というのは基本的にありえない。まあ、そういうケースもなくはないが、特殊なテストコードになってる。

> ブラウザでソース表示をした時のJavaScriptが化ているわけではありません

表示する場合と、実行する場合は、あんまり関係ないので念のため。

5   名前: ウマシカ : 2007/05/05(土) 03:41  ID:hPGqQZMx sub-t1
有難う御座います。Perlから出力した時点でバックスラッシュが消えていたんですね。
それで原因がわかりました。

2の様な、やり方も本当はグレーゾーンなのかも・・。
リンクタグ内をクリックするまで、イベントが何も無いからエラーが検出されないだけで、
「文法的には間違い」なのかも・・。

<body onload="test()">の件は了解しました。これをやると。
if構文の評価が終わるまでの間、ブラウザの画面が一瞬真っ白になりますね。

6   名前: 匿名 : 2007/05/05(土) 03:41  ID:0wLC.8ki sub-Cz
>>5
>>2 は「JavaScript の文法」的には問題ないよ。まあ、「HTML の文法」的には、DOCTYPE 宣言も title 要素もないという致命的なエラーはあるけど。

あるいは、>>2 には (a) 非スクリプト環境ではナビが表示されない、(b) アンカーに「こちら」という指示詞を使っている、という「ユーザビリティ」「アクセシビリティ」上の問題はある。

また、今回のように、他言語(に限った話ではないが)のソースコードを出力する場合、エスケープの仕方には極めて気を遣う。これは「セキュリティ」の問題に直結するから。だから、出力させたい言語の仕様は、隅々まで確認しておきたいところ。重箱の隅をつつくような場所で、問題が生じる。

問題の層を切り分けると、今何をすべきかがはっきりするかもしれない。

一覧へ戻る