WindowsのApacheはUnicode対応?

WindowsのApacheはUnicode対応?

- Haruhiko Okumura の投稿
返信数: 9

Windowsは奥深くではUnicodeを使っているはずだけれど,Windowsに送るZipファイルはファイル名をCP932にしないと化けるのが謎でしたが,Linux Conference 2006の岩本さんの論文CP-04を見てなんとなくわかりました。例えばファイルを作るシステムコールはCreateFile()を使うけれど実際にはCreateFileA()とCreateFileW()があり,前者はANSI(CP932),後者はUnicode(UTF-16LE)を使い,実際のファイルシステムにはUTF-16LEで格納されるということのようです。WindowsのZipがCreateFileA()を呼んでいるのが問題なんでしょう。ならApacheもそうかと思ってApache 2.0 の新機能の概要を見たらWindows NT上ではUTF-8でファイル名を扱えると書いてあります。このあたり,白井先生から昔お聞きした話がよく理解できていないので,混乱しています。

Haruhiko Okumura への返信

Re: WindowsのApacheはUnicode対応?

- Tatsuya Shirai の投稿
 確認はしていませんが、WindowsNT版ApacheがUnicodeファイル名に対応している可能性はあります。CreateFile()の説明を読んで見ましたが、CreateFileW()を使用し、さらにパスの前に"\\?\"なるマジックワードを付ければUnicodeのファイル名が与えられたと解釈するようですね。
 問題はApache以外のアプリケーションのUnicodeファイル名への対応ですね。PHP,テキストエディタ,そしてエクスプローラ(IEではなくファイルエディタ)。これらも対応していないとダメですね。
 あと、不安なのは、あのApache2.0の説明で書かれているWindowsNTに日本語WindowsNTは含まれていないという悲惨な可能性。さすがにそれは無いと期待したいですね。
 先日の調査で、PHPを介した日本語.Windowsへのファイルの読み書きにおいて、Windowsは与えられたファイル名がマルチバイト文字列がシフトJISであるという前提でUTF-16LEに変換していました。この操作、fopen()のWide版関数を用いればPCのロケールに依らずにUTF-16LEのままファイルシステムに対してスルーでアクセスできるのかも知れません。でも、PHPはまだ対応できていないように見えますね。
Tatsuya Shirai への返信

Re: WindowsのApacheはUnicode対応?

- Haruhiko Okumura の投稿
CP932にない文字でファイル名が付けられるということは,少なくともエクスプローラ(Windowsのシェル)はUnicode対応なんですよね。

PHPのfopen()の問題なのかもしれません。#define UNICODEしてPHPを再コンパイルすればいいのでしょうか。PHP6になればファイル名もUnicodeに対応できるといったことを書いてあるページもありました。

Haruhiko Okumura への返信

Re: WindowsのApacheはUnicode対応?

- Tatsuya Shirai の投稿
 裏技を使うことでシフトJISには存在しない文字(ハートだったか?)をファイル名に付けることが出来ることを示しているページを見たことがあります。残念ながらそのページでは方法を示していませんでしたが、デスクトップ上に特殊な文字を表示できていました。
 もしかしたら、CreateFile()の説明に書いてあったパス名の前に付ける特殊な文字列を追加したら、現状でもPHPやエクスプローラ上でUnicodeのファイル名が付けられる? だと良いですね〜。
 現在は強制的にOSサイドでシフトJIS←→UTF-16LEの相互変換を行っています。多分、CreateFileW()を用いても与えられたファイル名の文字コードを自動認識してUTF-16LEと相互変換するようにはできません(UTF16-LEとシフトJISで異文字に同じ文字コードが割り当てられているかも)よね。となると与えられたファイル名の文字コードはUTF-16LEだから余計な変換はしないでね、という識別子が必要か、と考えた次第。
 もしWindows用のソフトウェアをCreateFile()を用いて作成したとして、渡されたファイル名の文字コードを識別する手段が何か無いと困ります。プログラム中で自動作成されたファイル名ならばUTF-16LEかも知れないし、ユーザがキーボードから入力したのならばシフトJISなのかも知れない。
 まとまりがなくて申し訳ありません。CreateFileW()を起点とし、もう少し調査してみます。もしかしたら"長いファイル名"と"短いファイル名"のように、比較的互換性の高い方法で対応されていて、それに気付いていないだけという可能性があります。理想はfs_moodleが不要な世界、ですね。
Haruhiko Okumura への返信

Re: WindowsのApacheはUnicode対応?

- Tatsuya Shirai の投稿

 Windowsでファイル名にハートマークを付けている例をもう一度探し出しました.こちらです.

http://beefway.hp.infoseek.co.jp/prog/filename.html

 CreateFileW()を使用しているのでしょうか.


 さて,Windows版PHPでUTF-16LE形式でファイル名をダイレクトに保存可能かどうか,簡単に試して見ました.既存の'testA.pdf'をcopy()で別の名前のファイルにコピーしてみます.

$src  = "testA.pdf";
$dest = "テスト.pdf";
$dest = mb_convert_encoding($dest, 'UTF-16LE', 'UTF-8');
$dest = '\\\\?\\'.$dest;
echo $dest.'<br/>';
copy($src, $dest);

 パスの前にプレフィクスで'\\?\'を付ける,というのは,きっとこういう意味だろうと思って試してみたのですが,ダメでしたね.

\\?\�0�0�0.pdf

Warning: copy(\\?\�0�0�0.) [function.copy]: failed to open stream: No such file or directory in C:\xampplite\htdocs\mech\moodle\test.php on line 35


\\?\テスト.pdf

Warning: copy(\\?\テスト.pdf) [function.copy]: failed to open stream: No such file or directory in C:\xampplite\htdocs\mech\moodle\test.php on line 35

こちらはUTF-16LEに変換しないで,UTF-8のままにした場合です.

 頭の'\\?\'を付けなければ”化けた”ファイル名のファイルが(正しく)作成されます.

 php.iniになにか設定を付けると有効になる可能性はありますが,そこまでの調査はできていません.ファイル名の頭に'\\?\'が付いていたらCreateFileA()が,付いていたらCreateFileW()が呼ばれるように準備されているのかな,と少し甘く期待した実験です.


 現状ですとPHPがUnicodeに対応できていないようですね.ApacheがUnicodeに対応しているとしても,このままではダメです.

Haruhiko Okumura への返信

Re: WindowsのApacheはUnicode対応?

- Tatsuya Shirai の投稿

 先ほどから落雷による瞬停が頻発しているので小出しになります.

 さて,ではCreateFileW()のAPIを使ってWindowsのファイルシステムにUTF-16LE素のままのファイル名でファイルが作成できることを確認し,それが他のソフトウェアにどのような影響を与えるのかを調べてみようと思いました.

 考えたまでは良かったのですが,私がいつもWindowsアプリケーションを作成しているBorland C++ Builder (Turbo-C++)にはCreateFileW()に相当する関数が見当たらない...そもそも普段から”便利なC言語”としてC++言語を使用しているので,ファイルオープンはfopen()を使用している._wfopen()みたいな関数が存在するのかと期待したのですが...というわけで,Unicodeなファイル名を作成することができません.

 ファイルシステムで,このファイルの名前はシステムのロケールに合わせてUTF-16LEと相互変換するべきものかどうか,を判断する属性を持つならばApacheからもUTF-16LEでアクセスできるのかも知れません.ただ,ここでUTF-8ではなくUTF-16LEでファイル名をAPIに渡さなくてはならないのだとすると,面倒ですね.どういうメカニズムでApacheはUnicodeのファイル名に対応しているのでしょうか.

Tatsuya Shirai への返信

Re: WindowsのApacheはUnicode対応?

- Tatsuya Shirai の投稿

 アプリケーションは作れませんでしたが,その代わりエクスプローラで「♡.pdf」というファイル名にリネームできました.さて,このファイルを他のアプリケーションはうまく処理できるか?

(OK)
・秀丸エディタ: 読み込めました(バイナリファイルですが).
・Adobe Reader8: ダブルクリックで開くことができました.
・Firefox3 (+Apache2.2): URLをFirefoxに入力(http://www.suzuka-ct.ac.jp/mech/moodle/test/♡.pdfしてPDFファイルが開けた:これがApacheのUnicode対応という意味?
・Explzh(アーカイバ): ♡.pdfを圧縮した♡.lzhを作成化.それをダブルクリックして解凍&起動OK.

(NG)
・Irfan (Viewer): ♡.jpgを開けませんでした.
・Adobe Photoshop6: ♡.jpgを開けませんでした.

意外と♡はOKのようです.ちょっと古いソフト(特に海外物)はダメな傾向が見えます.

 となると,PHPさえWindowsネィティブなファイルシステムへのアクセスにも対応してくれればWindowsでもUnicode対応が可能な感じがしますね.一部,古いソフトで処理できない点を除けば.
 PHPのUnicodeファイル名への対応法(関数を使い分けるなど)によっては現状のfs_moodleのような大変な方法を継続しないとならないかも知れませんねぇ.


なお,ハート記号はこちらのWebページからコピー&ペーストして利用しました.

http://www.mukaiaki.com/cgi-bin/pc_qa/details.cgi?id=8

 

Tatsuya Shirai への返信

Re: WindowsのApacheはUnicode対応?

- Haruhiko Okumura の投稿
私もWindowsで「萌え♥.txt」のようなファイルを作ってみました。単にWindowsに付いている「文字コード表」ツールを使っただけです。メモ帳では開けましたが,xyzzyでは駄目でした。
添付 moe.png
Haruhiko Okumura への返信

Re: WindowsのApacheはUnicode対応?

- Tatsuya Shirai の投稿

>私もWindowsで「萌え♥.txt」のようなファイルを作ってみました。

なんとなく負けたっという感じです(^^;).

 気になるのは,PHP6のUnicode対応がファイル名/フォルダ名などのファイル関係の関数のことかどうか,ですね.ここが問題になるのはWindowsだけ?と思うと,内部の文字データの取り扱いをUnicodeで統一する(あるいはできる)ようにする拡張とも読み取れます.

 fs_modleではUnicodeのファイル名やフォルダ名をファイルシステムに対してシフトJIS変換して渡しているだけです.データベースにはUnicodeのままの情報で記録されていますから,「よし,対応するぞ」という時には,一気にmoodledataフォルダ以下のファイル名/フォルダ名をシフトJISからUnicodeに変換するソフトウェア(あるならば使うし,無ければ作らなければならない.PHPでも良いかな?)で変換すれば,その後は何事も無かったかのように新システムに移行できます.ですので,PHP6の今後の動向についてチェックを続けようと思います.

Haruhiko Okumura への返信

岩本さん

- Tatsuya Shirai の投稿

 Linux Conferenceの岩本氏の論文を読ませて頂きました.

 内容も参考になりましたが,あのフリーのWindows用ビデオ編集ソフトVmaidの岩本さんだったのですね.特許問題に巻き込まれて公開中止になった時は本当に残念でした.とても使いやすく高性能なソフトでしたので.その後,Video Maidとして新しく公開されたと聞いていたのですが,しばらく情報を追うのを忘れていました. 


以前にまとめたWindowsのファイルシステムに関する論文の抜粋を再構成したものを公開予定です.推敲しようと放置したままですが,ほぼ完成しています.このCreateFile()関係も追加すると発表が遅れるので,それはまた続報として.
(CreateFile()というキーワードのお陰で,未知の情報が沢山,入手できました.ありがとうございました)