Catalyst::Plugin::Charsets::Japanese::Mobileのその後。

以前、Catalyst::Plugin::Charsets::Japaneseが絵文字化けたので取り急ぎでCatalyst::Plugin::Charsets::Japanese::Mobileというのを作ったのですが・・・

Catalyst::Plugin::Charsets::Japaneseで絵文字が化ける - Unknown::Programming

Unicode::Japanese使って絵文字をsjis→utf8変換すると今度はMySQLなど、DBへ突っ込んだ時に文字化けを起こしてしまいます。

なので結局cp932→utf8変換することにしました。

package Catalyst::Plugin::Charsets::Japanese::Mobile;
use strict;

use Catalyst::Plugin::Charsets::Japanese;
use base qw/Class::Data::Inheritable/;
use Jcode;
use Unicode::Japanese;
use NEXT;

__PACKAGE__->mk_classdata('charsets');
__PACKAGE__->charsets( Catalyst::Plugin::Charsets::Japanese::Mobile::Handler->new );

our $VERSION = '0.02';

sub finalize {
    my $c = shift;
    unless ( $c->response->body and not ref $c->response->body ) {
        return $c->NEXT::finalize;
    }
    unless ( $c->response->content_type =~ /^text|xml$|javascript$/ ) {
        return $c->NEXT::finalize;
    }

    my $content_type = $c->response->content_type;
    $content_type =~ s/\;\s*$//;
    $content_type =~ s/\;*\s*charset\s*\=.*$//i;
    $content_type .= sprintf("; charset=%s", $c->charsets->out->name );
    $c->response->content_type($content_type);

    my $body = $c->response->body;

    if( $c->charsets->in->name eq 'UTF-8' && utf8::is_utf8($body) ) {
        utf8::encode($body);
    }

    my $in  = $c->charsets->in->abbreviation;
    my $out = $c->charsets->out->method;
    
    $in  = 'cp932' if $in  eq 'sjis';
    $out = 'cp932' if $out eq 'sjis';
    
    $body = Jcode->new($body, $in)->$out;

    $c->response->body($body);

    $c->NEXT::finalize;
}

sub prepare_parameters {
    my $c = shift;
    $c->NEXT::prepare_parameters;

    my $in  = $c->charsets->in->method;
    my $out = $c->charsets->out->abbreviation;
    
    $in  = 'cp932' if $in  eq 'sjis';
    $out = 'cp932' if $out eq 'sjis';
    
    my $sjis_in  = $c->charsets->sjis_in($c,$out);
    my $sjis_out = $c->charsets->sjis_out($c,$out);

    for my $value ( values %{ $c->request->{parameters} } ) {
        if( ref $value && ref $value ne 'ARRAY' ) {
            next;
        }
        for ( ref($value) ? @{$value} : $value ) {
            if ( $out eq 'cp932' ) {
                $_ = Unicode::Japanese->new($_,$sjis_in)->h2zKana->$sjis_out;
                $_ = Jcode->new($_, $out)->$in;
            }
            else {
                $_ = Jcode->new($_, $out)->h2z->$in;
            }
            utf8::decode($_) if $c->charsets->in->name eq 'UTF-8';
        }
    }
}

sub setup {
    my $self = shift;
    $self->NEXT::setup(@_);
    my $setting = $self->config->{charsets} || 'UTF-8' ;
    if(ref $setting eq 'HASH') {
        $self->charsets->set_inner($setting->{in});
        $self->charsets->set_outer($setting->{out})
    } else {
        $self->charsets->set_inner($setting);
        $self->charsets->set_outer($setting);
    }
    if($self->debug){    
    $self->log->debug($self->charsets->in->name." is selected for inner code.");
    $self->log->debug($self->charsets->out->name." is selected for outer code.");
    }
}

package Catalyst::Plugin::Charsets::Japanese::Mobile::Handler;
use base qw/Catalyst::Plugin::Charsets::Japanese::Handler/;

sub sjis_out {
    my $self = shift;
    my $c    = shift;
    my $code = shift;
    if ( $code eq 'cp932' ) {
        # Catalyst::Plugin::MobileAgent
        $code =
            ( $c->req->mobile_agent->is_docomo )   ? 'sjis_imode'   :
            ( $c->req->mobile_agent->is_vodafone ) ? 'sjis_jsky'    :
            ( $c->req->mobile_agent->is_ezweb )    ? 'sjis_icon_au' :
                                                     'sjis_imode'   ;
    }
    return $code;
}

sub sjis_in {
    my $self = shift;
    my $c    = shift;
    my $code = shift;
    my $out  = $self->sjis_out($c,$code);
    if ( $code eq 'cp932' ) {
        $out =~ s/_/-/g;
    }
    return $out;
}

1;

sjisだった場合のみcp932としてエンコードするような実装になってます。

ただそれでもまだUnicode::Japaneseを使ってる部分がありますが、これは前にも書いた通り(Jcode->new($s,'cp932')->z2hで絵文字が化ける件 - Unknown::Programming)Jcodeでh2z使うと携帯絵文字が化けてしまうので仕方なく使っています。なのでCatalyst::Plugin::MobileAgentも必要です。

Jcodeのみでh2zできればもっとソースがスッキリするのですが・・・。

そろそろ一連のCatalystの話のまとめをしないと自分でもよくわかんなくなってくるな。今度まとめよう。