File-Roller Dirty Hacking.

書庫マネージャって、GNOME 最新版でも、未だ Windows の SJIS エンコーディングを含んだ zip ファイルをまともに扱えないんだねぇ…:|。未だに文字化けする:
ちょっと仕事でそういう書庫ファイルを扱うことが多くなってきて、それを毎回手動で変換するのがだんだんと面倒になってきたので Web で調べてみたんだけど、上位にあがってくる検索結果としては、例えば “p7zip-full” をインストールしていると文字化けするとか、”unzip” を日本語対応のパッチ付きのもので置き換えるとか、古くて信ぴょう性の低い情報ばかり (例えば、前者のパッケージをインストールしていない環境でも文字化けは発生しているとか)。
で、一体正解は何なのだろうかと :$。ちなみに、今の環境はと言うと:

$ dpkg -l file-roller  unzip
ii  file-roller    amd64            archive manager for GNOME
ii  unzip                   6.0-9ubuntu1        amd64            De-archiver for .zip files

おそらくは “unzip” 側が怪しいだろうということで、その deb-src をダウンロードしてみると、changelog に以下のような記述が:

unzip (6.0-9ubuntu1) saucy; urgency=low
* Resynchronise with Debian.  Remaining changes:
- Add patch from archlinux which adds the -O option, allowing a charset
to be specified for the proper unzipping of non-Latin and non-Unicode
-- Colin Watson   Mon, 13 May 2013 13:00:12 +0100

この -O オプションに対するパッチファイルは:



$ unzip -h
UnZip 6.00 of 20 April 2009, by Debian. Original by Info-ZIP.
Usage: unzip [-Z] [-opts[modifiers]] file[.zip] [list] [-x xlist] [-d exdir]
Default action is to extract files in list, except those in xlist, to exdir;
file[.zip] may be a wildcard.  -Z => ZipInfo mode ("unzip -Z" for usage).
-p  extract files to pipe, no messages     -l  list files (short format)
-f  freshen existing files, create none    -t  test compressed archive data
-u  update files, create if necessary      -z  display archive comment only
-v  list verbosely/show version info       -T  timestamp archive to latest
-x  exclude files that follow (in xlist)   -d  extract files into exdir
-n  never overwrite existing files         -q  quiet mode (-qq => quieter)
-o  overwrite files WITHOUT prompting      -a  auto-convert any text files
-j  junk paths (do not make directories)   -aa treat ALL files as text
-U  use escapes for all non-ASCII Unicode  -UU ignore any Unicode fields
-C  match filenames case-insensitively     -L  make (some) names lowercase
-X  restore UID/GID info                   -V  retain VMS version numbers
-K  keep setuid/setgid/tacky permissions   -M  pipe through "more" pager
-O CHARSET  specify a character encoding for DOS, Windows and OS/2 archives
-I CHARSET  specify a character encoding for UNIX and other archives
See "unzip -hh" or unzip.txt for more help.  Examples:
unzip data1 -x joe   => extract all files except joe from zipfile
unzip -p foo | more  => send contents of via pipe into program more
unzip -fo foo ReadMe => quietly replace existing ReadMe if archive file newer


$ uznip -l
Length      Date    Time    Name
---------  ---------- -----   ----
0  2013-12-30 15:45   test-zip-from-winxp/ГEГBГУГhГEГYВ┼НьРмВ╡В╜ГtГ@ГCГЛ.txt
277040  2013-12-28 13:38   test-zip-from-winxp/У·Ц{МъВ╠ZIPГtГHГЛГ
0  2013-12-30 15:45   test-zip-from-winxp/У·Ц{МъВ╠ГtГHГЛГ_/
---------                     -------
277040                     3 files
$ unzip -l -O shift-jis
Length      Date    Time    Name
---------  ---------- -----   ----
0  2013-12-30 15:45   test-zip-from-winxp/ウィンドウズで作成したファイル.txt
277040  2013-12-28 13:38   test-zip-from-winxp/日本語のZIPフォルダ.zip
0  2013-12-30 15:45   test-zip-from-winxp/日本語のフォルダ/
---------                     -------
277040                     3 files

ということで、このオプションは利用できるっぽいので試しに書庫マネージャの zip コマンドクラスにオプションを追加してみる:

diff -uNrdp file-roller- file-roller-
--- file-roller-  2013-10-27 21:28:46.000000000 +0900
+++ file-roller-   2013-12-30 09:35:10.193504249 +0900
@@ -182,6 +182,10 @@ fr_command_zip_list (FrCommand  *comm)
fr_process_begin_command (comm->process, "unzip");
fr_process_set_begin_func (comm->process, list__begin, comm);
fr_process_add_arg (comm->process, "-ZTs");
+       fr_process_add_arg (comm->process, "-O");
+       fr_process_add_arg (comm->process, "shift-jis");
fr_process_add_arg (comm->process, "--");
fr_process_add_arg (comm->process, comm->filename);
fr_process_end_command (comm->process);
@@ -315,6 +319,9 @@ fr_command_zip_extract (FrCommand  *comm
fr_process_add_arg (comm->process, "-j");
add_password_arg (comm, FR_ARCHIVE (comm)->password);
+       fr_process_add_arg (comm->process, "-O");
+       fr_process_add_arg (comm->process, "shift-jis");
fr_process_add_arg (comm->process, "--");
fr_process_add_arg (comm->process, comm->filename);

ちなみに、Linux (UTF-8) と WindowsXP (Shift-JIS) の双方で作成した書庫の閲覧や展開も問題なかった。iconv で実装されたパッチなので Shift-JIS 以外のエンコーディングもちゃんと処理してくれているようだ。こんな Dirty なパッチに対して、Dirty なハックで対応してみたけれど、当分このまま使ってみることにする。