zip-rs
"OPS/ルートファイル.opf"といった日本語文字の入ったファイルをZipArchive.by_name()で取り出そうとするとFileNotFoundになる
ファイル名のUTF-8フラグについて調べる
is_utf8はそれに基づいているのかも知れない
そうだとしたら、ユーザー側で勝手にファイル名の型を変えないようにしないといけない
file_name_rawを使うのでもいいかも知れない
仕様の「4.6.9 -Info-ZIP Unicode Path Extra Field (0x7075)」で定義されていた 間違い
「4.4.4 general purpose bit flag: (2 bytes) 」の11ビット目として定義されていた
よってzip-rsの実装は妥当
by_nameの引数の型が上手くない気がする
やっぱりfrom_cp437がよくない
UTF-8のビットが立ってない時はこのメソッドが呼ばれるが、各バイトをString(UTF-8)に変換するのでおかしくなる。
おかしくなったのとby_name()の引数とを比較してもファイルを見つけられない
バイト列として扱ってくれればいいのだけど
code:read.rs
names_map: HashMap<String, usize>,
/// ...
pub fn by_name<'a>(&'a mut self, name: &str) -> ZipResult<ZipFile<'a>>
names_map.get()の引数がバイトだったらいいのでは
code:read.rs
let file = try!(central_header_to_zip_file(&mut reader, archive_offset));
names_map.insert(file.file_name.clone(), files.len());
files.push(file);
insertの時に名前をなんとかすればいい?
そのためにfileにis_utf8をつけとけばいい?
そもそも、cp437の文字の中に、UTF-8で表現できない物がある?
ないなら、names_mapのキーは全部UTF-8にしてしまえばいい
バイト列の方がいいか。その場合はfile_nameじゃなくてfile_name_rawでやりたい
éは・・・
UTF-8では[101, 204, 129]
code:read.rs
pub struct ZipArchive<R: Read + io::Seek>
{
reader: R,
files: Vec<ZipFileData>,
names_map: HashMap<&str, usize>,
offset: u64,
}
基本的にはバイト列で比較したいが、NFDとNFCは同一視したい
色々考えたが、zip-rsの実装は正しい。UTF-8ビットを立てずにアーカイブするのが悪い。