SMBとUnicodeファイル名正規化問題
Posted on 2014年3月23日(日) 02:03
かつて、LinuxからSambaを使ってWindowsのファイル共有にアクセスすると、文字コードの変換の問題で大変苦労しました。
時代は流れ、LinuxでもWindowsでもUnicodeが標準になりました。
というわけで、一般的にSMBを使う分には文字コードで苦労することはほぼなくなりました。
しかし・・・。
とりあえず以下の画像をご覧ください。
これはWindows8のエクスプローラーの画面です。
何かおかしいところにお気づきでしょうか。
おかしいですよね。
いいおっさんがプリキュア・・・じゃなくて、同一のファイル名が同じフォルダに存在しています。
実はこれ、「ピ」と「プ」の文字がUNICODEの結合文字列になっています。
通常、Windowsで「プリキュア」と入力した場合、「プ」の文字はU+30D7になります。
しかしMacOSで「プリキュア」と(ファイル名として)入力した場合、「プ」の文字はU+30D5 U+309Aになります。
U+30D5は「フ」です。
U+309Aは半濁点記号です。
つまり、「フ」+「゜」の合成で表現されます。
(なお、ここに書いた「゜」はU+309Cで、合成用ではなくそういう1文字ですので念のため)
Unicodeではこのような複数の表現方法があります。
混ざってる何かと困るので、普通は同一コードになるように正規化して扱います。
合成した方を使うのをNFC(Normalization Form Canonical Composition)、分解した方を使うのをNFD(Normalization Form Canonical Decomposition)と言います。
さて、最初の画像のファイル名ですが、「パ」と「プ」の表現方法を結合文字列、合成文字、混ぜてあります。
結果として4パターンの同名ファイル名が出来てしまったわけです。
何故かWindowsは上記のような状態を許してくれます。
許しているというか、初期の頃になんの正規化もせず扱ってしまったため、以後もそのままになっているんだと思います。(憶測)
さて、一方MacOSですが、上記のようなNFD,NFCの混在を許してくれません。
必ずNFDライクな正規化をされます。(正確にNFDでないのがまた困るんですが・・・)
iOSも一緒です。
よってファイル共有をすると大変困ります。
SMBには明確な仕様がない(もしかしたらあるかもしれなけど、ドキュメント読む限り発見できず)。
おそらくWindowsなのでNFCのUTF16 Little endianなんでしょうが、NFDでもプロトコルとしては問題なく(というかノータッチで)動きます。
さて、どう実装するのが正解なのでしょうか。
困りました。