aws.pl@MovableType3.3b1で文字化け

| コメント(0) | トラックバック(0)

以前、MT3.2にバージョンアップした際に発生した、MovableTypeのプラグインaws.plが生成するAmazon.co.jp商品情報の文字化けが再発してしまいました。

前回の「aws.pl@MovableType3.2で文字化け」「MT3.2での文字化け修正版aws.pl」、あたりでやったことを思い出しながら、試行錯誤すること数時間。 「JcodeでもEncodeでもダメならそうすりゃいいってのよ!」と一度はさじを投げかけましたが、同様のプラグインであるMT-MyAmazonList v1.00のソースを眺めたりした結果、無事問題を解決することができました。
結論から言うと、Encode.pmやJcode.pmではなく、MTが提供するMT::I18Nを使えばいいようです。

例によって以下に修正したソースコードを載せておきますが、MT-MyAmazonList使えばいいんじゃねぇかという気が沸々と湧いてきたのでした。

aws_MT33.zip

# aws.pl
# (C) 2003 Daiji Hirata
#  All Right Reserved.

#use Data::Dumper;
use MT;
use MT::ConfigMgr;
use MT::Template::Context;
use LWP::UserAgent;
use XML::Simple;
##use Jcode;
#use Encode;
use MT::I18N;
use strict;

my $VERSION = '1.0a';

my %config;
$config{"dev-t"} = 'InputYourDevelopersToken';
$config{associate_id} = 'sanzairyusei-22/ref=nosim';
$config{locale} = 'jp';

my @aws_tags = (
    # lite
    'url', 'ImageUrlSmall', 'ImageUrlMedium', 'ImageUrlLarge', 'ProductName', 'Asin',
    'Manufacturer', 'Availability', 'ListPrice', 'OurPrice', 'UsedPrice', 'Catalog',
    # heavy
    'Media', 'Isbn', 'ReleaseDate', 'SalesRank', 'Upc', 'ThirdPartyNewPrice',
);

my $elements = {
    'ActorSearch' => [ "dev-t", "t", "type", "f", "locale", "mode", "page" ],
    'ArtistSearch' => [ "dev-t", "t", "type", "f", "locale", "mode", "page" ],
    'AsinSearch' => [ "dev-t", "t", "type", "f", "locale" ],
    'AuthorSearch' => [ "dev-t", "t", "type", "f", "locale", "mode", "page"],
    # 'BlendedSearch' => [ "dev-t", "t", "type", "f", "locale" ],
    'BrowseNodeSearch' => [ "dev-t", "t", "type", "f", "locale" ,"mode", "sort"],
    'DirectorSearch' => [ "dev-t", "t", "type", "f", "locale", "mode", "page"],
    'KeywordSearch' => [ "dev-t", "t", "type", "f", "locale", "mode", "page"] ,
    'ListManiaSearch' => [ "dev-t", "t", "type", "f", "locale"],
    'ManufacturerSearch' => [ "dev-t", "t", "type", "f", "locale", "mode", "page"] ,
    'PowerSearch' => [ "dev-t", "t", "type", "f", "locale", "mode", "page"] ,
    'SemilaritiesSearch' => [ "dev-t", "t", "type", "f", "locale" ],
    'UpcSearch' => [ "dev-t", "t", "type", "f", "locale", "mode" ],
    'WishListSearch' => [ "dev-t", "t", "type", "f", "locale" ],
};

MT::Template::Context->add_container_tag(Aws => \&aws);

MT::Template::Context->add_tag(AwsAddCart => \&aws_addcart);

MT::Template::Context->add_tag(AwsAuthors => \&aws_authors );
MT::Template::Context->add_tag(AwsArtists => \&aws_artists );
MT::Template::Context->add_tag(AwsTracks => \&aws_tracks );
MT::Template::Context->add_tag(AwsXML => \&aws_xml );
MT::Template::Context->add_tag(AwsRequestUrl => \&aws_requesturl );
MT::Template::Context->add_tag(AwsTotalPages => \&aws_totalpages );
MT::Template::Context->add_tag(AwsTotalResults => \&aws_totalresults );
MT::Template::Context->add_tag(AwsAvgCustomerRating => \&aws_avgcustomerrating );
MT::Template::Context->add_tag(AwsTotalCustomerReviews => \&aws_totalcustomerreviews );
MT::Template::Context->add_tag(AwsVersion => \&aws_version );
MT::Template::Context->add_tag(AwsDirectors => \&aws_directors );
MT::Template::Context->add_tag(AwsStarring => \&aws_starring );

foreach my $tag (@aws_tags) {
    MT::Template::Context->add_tag('Aws'.$tag => sub { my $ctx = shift; aws_detail($ctx, $tag)});
}

sub aws {
    my ($ctx, $arg) = @_;
    my $builder = $ctx->stash('builder');
    my $tokens = $ctx->stash('tokens');
    my $res;
    my %q;

    use MT::ConfigMgr;
    my $cfg = MT::ConfigMgr->instance;
    my $charset = {'Shift_JIS'=>'sjis','ISO-2022-JP'=>'jis','EUC-JP'=> 'euc',
                   'UTF-8'=>'utf8'}->{$cfg->PublishCharset} || 'utf8';

    $q{f} = 'xml';
    $q{"dev-t"} = ($arg->{dev_token}) ? $arg->{dev_token} : $config{"dev-t"};
    if (!($q{"dev-t"})) { return $ctx->error("MTAWS needs your developer token: $q{'dev-t'}."); }
    $q{t} = ($arg->{associate_id}) ? $arg->{associate_id} : $config{associate_id};
    if (!($q{t})) { $q{t} = 'dh0dc-22'; }
    $q{type} = ($arg->{type}) ? $arg->{type} : 'lite';
    $q{mode} = ($arg->{mode}) ? $arg->{mode} : '';
    $q{page} = ($arg->{page}) ? $arg->{page} : 1;
    $q{lastn} = ($arg->{lastn}) ? $arg->{lastn} : -1;
    $q{offset} = ($arg->{offset}) ? $arg->{offset} : -1;
    $q{locale} = ($arg->{locale}) ? $arg->{locale} : $config{locale};
    $q{sort} = ($arg->{sort}) ? $arg->{sort} : '';
    if ($arg->{search} && $arg->{query}) {
        $q{search} = $arg->{search};
##       $q{query} = ($charset ne 'utf8') ? Jcode->new($arg->{query}, $charset)->utf8 : $arg->{query};
#       $q{query} = Encode::encode('utf8', $arg->{query});
        $q{query} = MT::I18N::encode_text( $arg->{query}, $charset, 'utf8' );
        $q{$arg->{search}} = utf2entity($q{query},1);
    } else {
        return $ctx->error("No search method and/or query");
    }
# my $url = 'http://xml.amazon.com/onca/xml3?';
    my $url = 'http://xml.amazon.co.jp/onca/xml3?';

    my @query;

    push @query, "$q{search}=$q{$q{search}}";
    foreach my $key (@{$elements->{$q{search}}}) {
        if (defined $q{$key}) {
            push @query, "$key=$q{$key}";
        }
    }

    $url .= join "&", @query;
    # $url .= '&__mk_ja_JP=%E3%82%AB%E3%82%BF%E3%82%AB%E3%83%8A';

    $ctx->stash('RequestUrl', $url );
    $ctx->stash('Associate_Id', $q{t} );

    my $ua = new LWP::UserAgent;
    $ua->agent("MTAWS");
    my $http_request = new HTTP::Request('GET', $url);
    my $http_response = $ua->request($http_request);
    my $content = $http_response->{'_content'};

    if ( $q{type} eq 'heavy') {
        my @content = split "\n", $content;
        $content = '';
        foreach my $line (@content) {
            if ($line) {
##               $content .= Jcode->new($line,'utf8')->utf8;
#               $content .= Encode::decode('utf8', $line);
                $content .= MT::I18N::encode_text( $line, $charset, 'utf8' );
                $content .= "\n";
            }
        }
    }

#die $q{query};

    # AWSからのレスポンスはここでUTF8フラグが立てられるっぽい
    my $tree;
    $tree = XMLin($content);
    if (!($tree)) { return $ctx->error("XML incorrect:\n"); }
    $ctx->stash('XML', $content );
    my @details;

    if (ref $tree->{Details} eq 'ARRAY') {
        push @details, @{$tree->{Details}};
    } else {
        push @details, $tree->{Details};
    }

    $ctx->stash("TotalResults", $tree->{TotalResults});
    $ctx->stash("TotalPages", $tree->{TotalPages});

    # トークンはDBにあるままなので、UTF8フラグが立っていない
    # なので、文字コードをUTF8に変換し、UTF8フラグを立てる
    for my $t (@$tokens)
    {
        if( $t->[0] eq 'TEXT' ) {
##            $t->[1] = Jcode->new($t->[1])->utf8;
##            $t->[1] = decode_utf8( $t->[1] );
#            $t->[1] = Encode::decode( $charset, $t->[1] );
             $t->[1] = MT::I18N::encode_text( $t->[1], $charset, 'utf8' );
        }
    }

    for my $detail (@details) {
    next if (($q{offset}--) > 0);
        $ctx->stash("Detail", $detail);
        defined(my $out = $builder->build($ctx, $tokens))
        or return $ctx->error($ctx->errstr);
        # $res .= sprintf($out);

        $res .= $out;
        if ($q{lastn}>0) { $q{lastn}--; }
        last if ($q{lastn} == 0);
    }

    # UTF8フラグをおろし、PublishCarsetの文字コードに変換する
##   $res = encode_utf8($res);
##   return Jcode->new($res, 'utf8')->$charset();
#   return Encode::encode( $charset, $res );
    return MT::I18N::encode_text($res, 'utf8', $charset );
}

sub utf2entity {
    my ($str, $amazon) = @_;
##     $str = Jcode->new($str)->utf8;
    $str =~ s/([^\w,])/'%'.unpack("H2", $1)/ego;

    if ($amazon ) {
      $str =~ s/%/%25/g;
    }
    $str;
}

sub aws_requesturl {
    my $ctx = shift;
    $ctx->stash("RequestUrl") || '';
}

sub aws_xml {
    my $ctx = shift;
    $ctx->stash("XML") || '';
}

sub aws_totalresults {
    my $ctx = shift;
    $ctx->stash("TotalResults") || '';
}

sub aws_totalpages {
    my $ctx = shift;
    $ctx->stash("TotalPages") || '';
}

sub aws_authors {
    my $ctx = shift;
    defined (my $detail = $ctx->stash("Detail")) or return '';
    if (ref $detail->{Authors}->{Author} eq 'ARRAY') {
        return join ", ", @{$detail->{Authors}->{Author}};
    } else {
        $detail->{Authors}->{Author} || '';
    }
}

sub aws_directors {
    my $ctx = shift;
    defined (my $detail = $ctx->stash("Detail")) or return '';
    if (ref $detail->{Directors}->{Director} eq 'ARRAY') {
        return join ", ", @{$detail->{Directors}->{Director}};
    } else {
        $detail->{Directors}->{Director} || '';
    }
}

sub aws_starring {
    my $ctx = shift;
    defined (my $detail = $ctx->stash("Detail")) or return '';
    if (ref $detail->{Starring}->{Actor} eq 'ARRAY') {
        return join ", ", @{$detail->{Starring}->{Actor}};
    } else {
        $detail->{Starring}->{Actor} || '';
    }
}

sub aws_detail {
    my ($ctx, $e) = @_;
    defined (my $detail = $ctx->stash("Detail")) or return '';
    if (ref $detail->{$e} eq 'ARRAY') {
        return join ", ", @{$detail->{$e}};
    } else {
        return $detail->{$e} || '';
    }
}

sub aws_avgcustomerrating {
    my $ctx = shift;
    defined (my $detail = $ctx->stash("Detail")) or return '';
    $detail->{Review}->{AvgCustomerRating} || '';
}

sub aws_totalcustomerreviews {
    my $ctx = shift;
    defined (my $detail = $ctx->stash("Detail")) or return '';
    $detail->{Review}->{TotalCustomerReviews} || '';
}

sub aws_artists {
    my $ctx = shift;
    defined (my $detail = $ctx->stash("Detail")) or return '';
    if (ref $detail->{Artists}->{Artist} eq 'ARRAY') {
        return join ", ", @{$detail->{Artists}->{Artist}};
    } else {
        $detail->{Artists}->{Artist} || '';
    }
}

sub aws_tracks {
    my $ctx = shift;
    defined (my $detail = $ctx->stash("Detail")) or return '';
    if (ref $detail->{Tracks}->{Track} eq 'ARRAY') {
        return join ", ", @{$detail->{Tracks}->{Track}};
    } else {
        $detail->{Tracks}->{Track} || '';
    }
}

sub aws_addcart {
    my ($ctx, $args) = @_;

    my $res;
    defined (my $detail = $ctx->stash("Detail")) or return '';
    my $button = ($args->{label}) ? $args->{label} : "Buy";

    $res = sprintf( "<form method=\"POST\" action=\"http://www.amazon.co.jp/o/dt/assoc/handle-buy-box=%s\">\n", $detail->{Asin} );
    $res .= sprintf( "<input type=\"hidden\" name=\"asin.%s\" value=\"1\">\n", $detail->{Asin} );
    $res .= sprintf( "<input type=\"hidden\" name=\"tag-value\" value=\"%s\">\n", $ctx->stash("Associate_Id") );
    $res .= sprintf( "<input type=\"hidden\" name=\"tag_value\" value=\"%s\">\n", $ctx->stash("Associate_Id") );
    $res .= sprintf( "<input type=\"submit\" name=\"submit.add-to-cart\" value=\"%s\">\n", $button);
    $res .= "</form></span>\n";

    $res;
}

sub aws_version {
    $VERSION;
}

1;
__END__

=head1 NAME

aws.pl - Movable Type Plugin of Amazon Webservices

=head1 SYNOPUS

    <MTAws dev-t="developer-token" associate_id="dh0dc-22" search="KeywordSearch" mode="books-jp" query="weblog" locale="jp">
    <$MTAwsurl$>
    <$MTAwsAuthors$>
    <img src="<$MTAwsImageUrlSmall$>">
    <$MTAwsAddCart label="Buy from Amazon!"$>
    </MTAws>

=head1 LICENSE

Please see the file F<README> in the package.

=head1 AUTHOR

Daiji Hirata, dh@uva.jp

=cut

トラックバック(0)

トラックバックURL: http://www.sanzai.net/mt/mt-tb.cgi/1048

コメントする

ウェブページ

2014年6月

1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30          

アーカイブ

Powered by Movable Type 5.17-ja

このブログ記事について

このページは、散財人が2006年6月 4日 23:12に書いたブログ記事です。

ひとつ前のブログ記事は「THE DA VINCI CODE」です。

次のブログ記事は「Colors of the Heart」です。

最近のコンテンツはインデックスページで見られます。過去に書かれたものはアーカイブのページで見られます。