WIP/Unzipの日本語特化テストケース……だったがunzipの現状も書いてある文書
基礎知識
Unix/Linuxのunzipは、zipアーカイブに含まれる複数の文字コードを適切に処理しない。ので、誰かがなんとかする必要がある。あるいは、なんとかした後も動作を確認する必要がある。
- 「文字コードを適切に処理しない」症状は二通り。実装による。
- ケース1 保存不能: そもそも展開した結果のファイル名がUnix filename的に妥当でなく、保存不能。
- ケース2 文字列破壊: そもそも展開した結果のファイル名がUnix filename的に妥当で、保存可能だが、オリジナルの文字列とは違う。
- Ubuntuでは「無効なエンコーディング」といった文字列を付与することで、「保存不能」なケースであっても「文字列破壊」にとどめている。
- 「zipの文字化け」は、file-roller(フロントエンド)とunzip(バックエンド)の複合的な問題
- unzip side:
- 「文字化け」対策として、unzipに「文字コードを指定するオプションを付ける」(俗称Ubuntu Patch)か、「文字コードを自動推定する機能を付ける」の2つの方針がある。各方針ごとに複数の実装が存在する。
といったあたりを整理したのがこちら。https://bugs.launchpad.net/ubuntu/+source/unzip/+bug/580961
- 要約:生のunzipは多言語に対応していない(保存不能が起こりうる)。UbuntuのunzipはArch由来のパッチにより-O/-Iオプションを拡張していて、文字コードを指定することで正しい文字コードに展開される。しかし現状(11.10〜12.04ぐらい。11.04以前もかも)file-rollerは-O指定をしない。
俗称「Ubuntu patch」(OpenSolarisあたりの表現)は厳密には正しくなく、Arch由来のパッチ。
- このパッチはunzip 5.x系にしか適用できず、6.x系にはhttps://gist.github.com/573753 を用いる必要がある。
- さらにこのパッチとは別実装として、SUSEに入っているパッチが存在する(たぶん。同じものかもしれないがコード読んでない)。
- libnatspecを経由することで、文字コードを自動で推定することが可能になる。が、unzip 6.10にはlibnatspecを経由する拡張はまだ行われていない。
- libnatspecに含まれる examples/unzip-5.52-alt-natspec.patch を6.0/6.1へ移植すればよい。
- このパッチは-I/-Oサポートの拡張として作られているので(-I/-Oで呼ばれるinit_conversion_charsetsの文字コード推定ルーチンでlibnatspecに含まれる関数を呼んでいるだけ)、libnatspecがmainに入ればunzipへのパッチとしてacceptableになる。unzip(zip)はmainなので、libnatspecもuniverseに入れてMIRしないといけない。
http://pad.lv/580961 と bugs.debian.org/545151 を見ながらMIRする方法を考えると全て解決?
- ……といったものとはさらに別実装の、SHIFT_JIS・ISO-2022-JP・EUC-JP・UTF-8のいずれかであろうと推定して暗黙で推定するパッチを日本語Remix版unzipでは採用している。
- 要約:生のunzipは多言語に対応していない(保存不能が起こりうる)。UbuntuのunzipはArch由来のパッチにより-O/-Iオプションを拡張していて、文字コードを指定することで正しい文字コードに展開される。しかし現状(11.10〜12.04ぐらい。11.04以前もかも)file-rollerは-O指定をしない。
- file-roller side:
- unzipが「何もオプションが与えられていない状態で、自動的に文字コードを推定してデコードする」動作になれば良い。
もしくは、「src/fr-command-zip.c::static void fr_command_zip_list (FrCommand *comm)」を直して、-O CHARSET指定を行えるようにする必要がある
- 現在の言語設定から、zipアーカイブ内のファイル名文字列ストリームで使われていると推定されるCHARSETを類推する仕組みが必要
- natspecの機能として、「現在のシステムロケールから、Windows環境で通常利用されているCHARSETを推定する」関数がある。
- file-roller側からはzipアーカイブに含まれる文字列ストリームを推定材料にすることはできない(原理上当然)。
- よって、unzipの中でnatspecを使う方がよい
- Windowsの実装に揃える、のか?(例:LANG=ja_JP.utf8→SHIFT_JISとか)
- 現在の言語設定から、zipアーカイブ内のファイル名文字列ストリームで使われていると推定されるCHARSETを類推する仕組みが必要
- 追記:Japanese Remixのunzipは、zipアーカイブ内のファイル名から推定してSHIFT_JIS/EUC-JP/ISO-2022-JP/UTF-8から適切なものを自動で選んでくれるので、file-rollerサイドの対応は不要で動作する。
- unzip side:
テスト手順
準備
- 1) テスト環境からp7zip(p7zip-full)パッケージを除去する
$ sudo apt-get remove p7zip
- 2011/04現在、p7zipは多言語サポートが甘く「保存可能だが、オリジナルの文字列とは違う」状態になる。
- なので除去しておかないとテストにならない。
- 2) パッケージ環境を最新に更新する
テスト手順
- 1) 対象ファイルを取得する
- 2) file-roller(書庫マネージャ)で展開する
- 3) unzip コマンドで展開する
文字コード別対象ファイル
UTF-8
対象ファイル: UTF8.zip
- file-rollerの例:
expected:
- unzipの例:
- expected:
$ unzip UTF8.zip Archive: UTF8.zip creating: UTF8/ extracting: UTF8/UTF-8_SHIFTJIS???????????????.txt extracting: UTF8/UTF-8???????????????_( ???????????? ).txt $ ls -al UTF8 合計 8 drwxr-xr-x 2 hito hito 4096 2011-04-05 13:09 ./ drwxr-xr-x 3 hito hito 4096 2011-04-05 14:21 ../ -rw-r--r-- 1 hito hito 0 2011-04-05 13:09 UTF-8_SHIFTJISマップ可能.txt -rw-r--r-- 1 hito hito 0 2011-04-05 13:08 UTF-8固有文字列_( ◕‿‿◕ ).txt
- expected:
- TODO: wavedash-tilde問題もサポートすべき……だがどうやってテストする?
SHIFT_JIS(CP932)
対象ファイル:解凍すると文字化けするかも.zip
- file-rollerの例
- expected:
unexpectd:
- unzipの例
- expected:
$ unzip 解凍すると文字化けするかも.zip Archive: 解凍すると文字化けするかも.zip extracting: ??????????????????????????.txt $ ls -altr -rw-r--r-- 1 hito hito 0 2008-09-13 01:10 解凍すると文字化けするかも.txt -rw-r--r-- 1 hito hito 158 2011-04-05 12:39 解凍すると文字化けするかも.zip
- unexpected:
$ unzip 解凍すると文字化けするかも.zip Archive: 解凍すると文字化けするかも.zip extracting: ??????????????????????????.txt $ ls -altr -rw-r--r-- 1 hito hito 0 2008-09-13 01:10 ??????ƕ??????????邩??.txt -rw-r--r-- 1 hito hito 158 2011-04-05 12:39 解凍すると文字化けするかも.zip
- expected:
EUC-JP
対象ファイル:unzip_EUC-JP_testfile.zip
- Solari10環境/EUC-JP設定の環境にzipを追加インストールして作成したもの。
ISO-2022-JP
(tbd)
- TODO: 要調査。そもそもISO-2022-JPでファイル名エンコーディングを行なうzip実装はあるのか?
動作テスト報告(Mocchi)2011/04/21
テストしたバージョン
file-roller 2.32.1-0ubuntu4 (archive.ubuntu.com/natty/main)
unzip 6.0-5~5.52~ja2 (LP-PPA-japaneseteam/natty)
テスト結果
file-roller
unzip
期待通りの結果。extractingのメッセージもちゃんと表示されている。
UTF-8
$ ls -l; 合計 8 -rw-rw-rw- 1 mocchi mocchi 428 2011-04-21 11:02 UTF8.zip $ unzip UTF8.zip; Archive: UTF8.zip creating: UTF8/ extracting: UTF8/UTF-8_SHIFTJISマップ可能.txt extracting: UTF8/UTF-8固有文字列_( ◕‿‿◕ ).txt $ ls -l; 合計 12 drwxr-xr-x 2 mocchi mocchi 4096 2011-04-05 13:09 UTF8 -rw-rw-rw- 1 mocchi mocchi 428 2011-04-21 11:02 UTF8.zip $ ls -l ./UTF8; 合計 0 -rw-r--r-- 1 mocchi mocchi 0 2011-04-05 13:09 UTF-8_SHIFTJISマップ可能.txt -rw-r--r-- 1 mocchi mocchi 0 2011-04-05 13:08 UTF-8固有文字列_( ◕‿‿◕ ).txt
SHIFT_JIS(CP932)
{{{$ ls -l; 合計 8 -rw-rw-rw- 1 mocchi mocchi 158 2011-04-21 11:01 解凍すると文字化けするかも.zip
$ unzip 解凍すると文字化けするかも.zip; Archive: 解凍すると文字化けするかも.zip
- extracting: 解凍すると文字化けするかも.txt
$ ls -l; 合計 12 -rw-r--r-- 1 mocchi mocchi 0 2008-09-13 01:10 解凍すると文字化けするかも.txt -rw-rw-rw- 1 mocchi mocchi 158 2011-04-21 11:01 解凍すると文字化けするかも.zip}}}
mixed
UTF-8エンコードしたファイルが含まれるzipファイルに、SHIFT_JISエンコードなファイルを追加するとUTF-8/SHIFT_JISが混在したファイルが生成される(はず)。
この場合何をどうデコードするのがそもそも正しいのかよく分からないが、全滅はなにかおかしい。