Firefox等のMozilla系ブラウザの履歴(= history.dat)を読み込むモジュールにFile::Morkがある。なかなか便利に使えそうなんだけど、マルチバイト対応しておらず、日本語が扱えない。なんで、File::Morkを日本語対応するようなパッチを書いた。
--- Mork_original.pm 2006-10-23 22:46:41.000000000 +0900 +++ Mork.pm 2006-10-23 22:46:07.000000000 +0900 @@ -3,6 +3,7 @@ use strict; use vars qw($VERSION $ERROR); use POSIX qw(strftime); +use Encode; $VERSION = "0.2"; @@ -331,12 +332,24 @@ next; } + # recognize the byte order of UTF-16 encoding + if (! defined ($self->{byte_order}) && $val =~ m/(?:BE|LE)/) { + $self->{byte_order} = $val; + } + # Assume that URLs and LastVisited are never hexilated; so # don't bother unhexilating if we won't be using Name, etc. if($val =~ m/\$/) { - # Approximate wchar_t -> ASCII and remove NULs - $val =~ s/\$00//g; # faster if we remove these first - $val =~ s/\$([\dA-F]{2})/chr(hex($1))/ge; + if ( defined $self->{byte_order} ) { + my $encoding = 'UTF-16' . $self->{byte_order}; + $val =~ s/\$([\dA-F]{2})/chr(hex($1))/ge; + $val = encode_utf8(decode($encoding, $val)); + } + else { + # Approximate wchar_t -> ASCII and remove NULs + $val =~ s/\$00//g; # faster if we remove these first + $val =~ s/\$([\dA-F]{2})/chr(hex($1))/ge; + } } $self->{val_table}->{$key} = $val;
history.datないではマルチバイト文字が現れるような場所では、文字列はUTF-16でエンコードされて記録されている。もともとのFile::MorkではUTF-16の2byte文字を強引に1byteに変更するような実装だったので、きちんとUTF-16として読み込んでUTF-8の普通の文字列で返すようにした。
ただし、UTF-16といっても環境に寄ってLitteEndianだったり、BigEndianだったりするらしい。幸い、history.datにはバイトオーダーが記録されていたので、バイトオーダーがわかれば、それにしたがってデコードするようにした。
File::MorkにはPlagger::Plugin::Subscription::Browserを手軽に利用するためにもマルチバイト対応してもらいたい。なんで、このパッチを作者の方にメールしたいところだ。しかし、英語のメールとかまともに送れるかはなはだ不安というか、そもそも、パッチ送るとかもはじめてなんだよね。不安。