file upload

input type=file の挙動については JavaScript の問題ではないが、JavaScript に渡された file path の処理に絡むので JavaScript 関連の話題として取り上げた。 調査対象は、下のような input type=file を使った form がある場合、ボタンの onClick で呼ばれる JavaScript の関数には、file path がどのような文字列として渡されるか、である。この file path は local machine 上で使われるだけだが、path 文字列を利用した処理(例えば server 上に保存する場合の file name の default 値を決めるなど)がある場合に、field separater がどの文字かを確認する必要がある。 ここで OS, browser 依存性が(例によって)出てくるので、それについて以下にまとめた。

file path を alert() で表示


調査には上記のように、input type=button の onClick から func() を呼ぶ form を用いた。 この form で選択するファイル名は、escape の状況などを確認するために field separater や escape に使われる文字を含む「/情%報 \部@a:b&」というものとした。 ただし Mac OS 9.x/X ではファイル名に ":" は使えないので、「/情%報 \部@a-b&」というファイル名を、Windows の場合には "/", "\", ":" が使えないので「-情%報 -部@a-b&」というファイル名を使用した。 func() の内容は基本的には alert( document.fileform.filename.value ); と同値だが、escape 検知のために '%', '&', '\' の置換を噛ませた(下記参照)。 ただし、以下の結果のうち「func() に渡されている文字列」欄には、置換前の文字列を表示している。

function func(){
  var str1 = document.fileform.filename.value

  str1 = str1.replace( /:/g, "*" );
  str1 = str1.replace( /%/g, "-" );
  str1 = str1.replace( /&/g, "=" );
  str1 = str1.replace( /\\/g, "_" );
  alert( str1 + "\n" + document.fileform.filename.value );
}

結果

各 OS, browser ごとに

を、以下の表にまとめた。

OSbrowserinput type=file の表示alert() の表示escape() した結果func() に渡されている文字列
Mac OS 9.2.2
(HD 直下の tmp の中の hoge.txt を選択)
Netscape 4.76 /情%報 \部@a-b& /MacintoshHD/tmp/:情%報 \部@a-b& /MacintoshHD/tmp/%3A%8F%EE%25%95%F1%20%5C%95%94%40a-b%26 /MacintoshHD/tmp/%3A%8F%EE%25%95%F1%20%5C%95%94%40a-b%26
Netscape 6.1 MacintoshHD:tmp:/情%報 \部@a-b& MacintoshHD:tmp:/情%報 \部@a-b& MacintoshHD%3Atmp%3A/%BE%F0%25%CA%F3%20%5C%C9%F4%40a-b%26 (EUC-JP)
MacintoshHD%3Atmp%3A/%8F%EE%25%95%F1%20%5C%95%94%40a-b%26 (Shift-JIS)
MacintoshHD%3Atmp%3A/%1B%24B%3Ep%1B%28B%25%1B%24BJs%1B%28B%20%5C%1B%24BIt%1B%28B%40a-b%26 (ISO-2022-JP)
MacintoshHD:tmp:/情%報 \部@a-b&
Netscape 7.02 MacintoshHD:tmp:/情%報 \部@a-b& MacintoshHD:tmp:/情%報 \部@a-b& MacintoshHD%3Atmp%3A/%BE%F0%25%CA%F3%20%5C%C9%F4%40a-b%26 (EUC-JP)
MacintoshHD%3Atmp%3A/%8F%EE%25%95%F1%20%5C%95%94%40a-b%26 (Shift-JIS)
MacintoshHD%3Atmp%3A/%1B%24B%3Ep%1B%28B%25%1B%24BJs%1B%28B%20%5C%1B%24BIt%1B%28B%40a-b%26 (ISO-2022-JP)
MacintoshHD:tmp:/情%報 \部@a-b&
Mozilla 1.0rc2 MacintoshHD:tmp:/情%報 \部@a-b& MacintoshHD:tmp:/情%報 \部@a-b& MacintoshHD%3Atmp%3A/%BE%F0%25%CA%F3%20%5C%C9%F4%40a-b%26 (EUC-JP)
MacintoshHD%3Atmp%3A/%8F%EE%25%95%F1%20%5C%95%94%40a-b%26 (Shift-JIS)
MacintoshHD%3Atmp%3A/%1B%24B%3Ep%1B%28B%25%1B%24BJs%1B%28B%20%1B%28J%5C%1B%24BIt%1B%28B%40a-b%26 (ISO-2022-JP)
MacintoshHD:tmp:/情%報 \部@a-b&
Mozilla 1.2.1 MacintoshHD:tmp:/情%報 \部@a-b& MacintoshHD:tmp:/情%報 \部@a-b& MacintoshHD%3Atmp%3A/%BE%F0%25%CA%F3%20 (EUC-JP)
MacintoshHD%3Atmp%3A/%8F%EE%25%95%F1%20 (Shift-JIS)
MacintoshHD%3Atmp%3A/%1B%24B%3Ep%1B%28B%25%1B%24BJs%1B%28B%20%1B%(ここではみ出た) (ISO-2022-JP)
MacintoshHD:tmp:/情%報 \部@a-b&
Internet Explorer 5.0 /情%報 \部@a-b& /MacintoshHD/tmp//????@a-b& /MacintoshHD/tmp//%uFF8F%uFFEE%25%uFF95%uFFF1%20%5C%uFF95%uFF94@a-b%26 /MacintoshHD/tmp//マ?-ユ? _ユヤ@a-b&
(カタカナは半角)
Internet Explorer 5.1.7 /情%報 \部@a-b& /MacintoshHD/tmp//????@a-b& /MacintoshHD/tmp//%uFF8F%uFFEE%25%uFF95%uFFF1%20%5C%uFF95%uFF94@a-b%26 /MacintoshHD/tmp//マ?-ユ? _ユヤ@a-b&
(カタカナは半角)
Opera 6.03J "MacintoshHD:tmp:/情%報 \部@a- "MacintoshHD:tmp:/情%報 \部@a- "MacintoshHD:tmp:/情%報 \部@a-
iCab 2.8 /情%報 \部@a-b& /カ□□ \□@a-b&
(カタカナは半角、□は豆腐)
/%8F%EE%25%95%F1%20%5C%95%94@a-b%26 /カ□□ \□@a-b&
(カタカナは半角、□は豆腐)
iCab 2.97 /情%報 \部@a-b& /カ□□ \□@a-b&
(カタカナは半角、□は豆腐)
/%8F%EE%25%95%F1%20%5C%95%94@a-b%26 /カ□□ \□@a-b&
(カタカナは半角、□は豆腐)
Mac OS X 10.2
(home dir の hoge.txt を選択)
Netscape 7.0 Macintosh HD:Users:satodai:/情%報 \部@a-b& Macintosh HD:Users:satodai:/情%報 \部@a-b& Macintosh%20HD%3Atmp%3A/%BE%F0%25%CA%F3%20%5C%C9%F4%40a-b%26 (EUC-JP)
Macintosh%20HD%3Atmp%3A/%8F%EE%25%95%F1%20%5C%95%94%40a-b%26 (Shift-JIS)
Macintosh HD:Users:satodai:/情%報 \部@a-b&
Mozilla 1.2.1 Macintosh HD:Users:satodai:/情%報 \部@a-b& Macintosh HD:Users:satodai:/情%報 \部@a-b& Macintosh%20HD%3Atmp%3A/%BE%F0%25%CA%F3%20%5C%C9%F4%40a-b%26 (EUC-JP)
Macintosh%20HD%3Atmp%3A/%8F%EE%25%95%F1%20%5C%95%94%40a-b%26 (Shift-JIS)
Macintosh HD:Users:satodai:/情%報 \部@a-b&
Mozilla 1.4 /Users/satodai/:情%報 \部@a-b& /Users/satodai/:情%報 \部@a-b& /Users/satodai/:情%報 \部@a-b&
Internet Explorer 5.2 /情%報 \部@a-b& /Macintosh HD/Users/satodai@a-b& /Macintosh%20HD/Users/satodai//%uFF8F%uFFEE%25%uFF95%uFFF1%20%5C%uFF95%uFF94@a-b%26 /Macintosh HD/Users/satodai//マ?-ユ ? _ユ ヤ @a-b&
(カタカナは半角)
Safari Public Beta /情%報 \部@a-b& /Users/satodai/:情%報 \部@a-b& /Users/satodai/%3A%u60C5%25%u5831%20%A5%u90E8@a-b& /Users/satodai/:情%報 ¥部@a-b&(¥は半角)
Safari 1.1 /情%報 \部@a-b& /Users/satodai/:情%報 \部@a-b& /Users/satodai/:情%報 ¥部@a-b&(¥は半角)
Opera 6.03 "Macintosh HD:Users:satodai:/情%報 \部@a-b& "Macintosh HD:Users:satodai:/情%報 \部@a-b& "Macintosh HD:Users:satodai:/情%報 \部@a-b&
Windows XP Home Edition Internet Explorer 6.0 sp2 C:\Program Files\-情%報 -部@a-b& C:\Program Files\-情%報 -部@a-b& C:\Program Files\-情%報 -部@a-b&
Windows NT 4.0 sp6 Netscape 6.1 C:\Program Files\-情%報 -部@a-b& C:\Program Files\-情%報 -部@a-b& C%3A%5CProgram%20Files%5C-%BE%F0%25%CA%F3%20-%C9%F4%40a-b%26 (EUC-JP)
C%3A%5CProgram%20Files%5C-%8F%EE%25%95%F1%20-%95%94%40a-b%26 (Shift-JIS)
C:\Program Files\-情%報 -部@a-b&
Internet Explorer 5.5 sp2 C:\Program Files\-情%報 -部@a-b& C:\Program Files\-情%報 -部@a-b& C%3A%5CProgram%20Files%5C-%u60C5%25%u5831%20-%u90E8@a-b%26 C:\Program Files\-情%報 -部@a-b&

Netscape 4.76 (Mac OS 9.2.2) では、%HH style の encode(URLencode ではない)済みの文字列が func() に渡されていることが分かる。alert window に表示する際には decode などの処理が入っているようだが、その際に "/" を ":" に置換してしまう bug が見付かった(恐らく field separater を Mac OS style に戻すつもりの処理)。その他の browser では、この種の encode は行われていないようだ。

また Mac OS 版の Netscape 4.x, IE, iCab では file path が unix style に変換されている。これに対して Netscape 6.x, 7.x, Mozilla では Mac OS style のままになっている。また Windows では path 表記の変更は行われてないらしい。

さらに Netscape 6, 7, Mozilla においては、HTML file の文字コード (EUC, Shift-JIS, ISO-2022-JP) によって func() に渡される文字列が異なっていた。どうやら文字コードを考慮した処理は一切なく、byte 列をそのまま渡しているようだ。また、Mozilla 1.2.1 では "\" が escape されないためか、escape() が出力する文字列が "\" の直前で切れていた(他の表示には問題なし)。

Mac OS 版の IE では、alert() が生の日本語を受け取ると alert window で文字化けが起こることが分かっている(alert window への日本語表示)が、今回も同様の現象が確認された。 ただし、escape などの処理は特に行われていないらしい。また、この文字化けが発生していなかった iCab においても、今回は文字化けが発生した。

また Mac 版 IE 5.0 による %uHHHH style の escape() の処理が、Windows 版の IE 5.5 と異なっていることが分かった。Windows 版 IE 5.5 では、UCS-2 文字列に対して escape() 処理が行われているようだ。しかし Mac 版 IE 5.0 では、Shift-JIS で 8FEE である「情」が %uFF8F%uFFEE となっており、RFC 1738 にも ECMA-262 (PDF) にも準拠していない中途半端な処理が行われている。。RFC 準拠であれば %HH style になるはずだし、ECMA-262 準拠であれば、Unicode が使われるべきだ。 なお、Safari Public Beta においては、ECMA-262 準拠の escape() が実装されているようだ。

input type=file の value としてセットされる file path 文字列は、local でのみ使用されるためか、その記法については RFC 1867, HTML 4.01 Specification, DOM Level2 HTML Specification では規定されていないようだ。 このためか、file path には unix style, Mac OS style, DOS style と、いくつかの文字コード(少なくとも EUC-JP, Shift-JIS, ISO-2022-JP, UCS-2)が混在し、それぞれを正しく処理するのが非常に難しくなっている。

参考文献

  1. RFC 1867 "Form-based File Upload in HTML"
  2. ECMA-262 (PDF)
  3. HTML 4.01 Specification
  4. Document Object Model (DOM)

[ JavaScript のブラウザ依存性 ] [ HTML 入門 ] [ 大' 小屋 ]
御意見御感想は「けいじわん」(WebBBS) までどうぞ。
satodai@dog.intcul.tohoku.ac.jp