package Data::ToruCa;
use strict;
use MIME::Base64;
use vars qw(@ISA @EXPORT_OK);
require Exporter;
@ISA = qw(Exporter);
@EXPORT_OK = qw(cat2pict);
our $VERSION = '0.06';
our $VERBOSE = 0;
sub new {
my $class = shift;
my $opt = shift;
my $self = bless {}, $class;
if (ref($opt) eq 'HASH') {
foreach (keys %$opt) {
$self->{$_} = $opt->{$_};
}
} elsif (ref($opt) eq '' && $opt) {
$self->parse($opt);
}
return $self;
}
sub _warn {
warn shift
if ($VERBOSE);
}
sub ext {'trc'}
sub content_type {'application/x-toruca'}
sub _accessor {
my $self = shift;
my $field = shift;
my $size = shift;
my $data = shift;
return $self->{$field} unless $data;
_warn "length of $field is too large($size bytes)."
if length($data) > $size;
$self->{$field} = $data;
}
sub version {shift->_accessor('version', 4, @_)}
sub type {shift->_accessor('type', 8, @_)}
sub url {shift->_accessor('url', 127, @_)}
sub data1 {shift->_accessor('data1', 40, @_)}
sub data2 {shift->_accessor('data2', 100, @_)}
sub data3 {shift->_accessor('data3', 20, @_)}
sub cat {shift->_accessor('cat', 4, @_)}
sub mime {my $self = shift;return $self->{mime} = @_ ? shift : $self->{mime}}
sub pict {my $self = shift;$self->cat2pict($self->cat);}
sub parse {
my $self = shift;
my $trc = shift;
unless ($trc =~ /^ToruCa\r\n/) {
_warn 'toruca format error.';
return 0;
}
my $mime;
my $c = 0;
foreach (split(/\r\n/, $trc)) {
if ($c < 2) {
if (/^([^:]+): (.+)$/) {
my ($field, $data) = (lc($1), $2);
$data = decode_base64($data)
if ($field =~ /^data/);
$self->_accessor($field, 200, $data);
} elsif ($_ eq '') {
$c++;
}
} else {
$mime .= "$_\r\n";
}
}
if ($mime) {
$mime =~ s/^\r\n//;
$mime =~ s/\r\n$//;
$self->mime($mime);
}
return 1;
}
sub _build {
my $self = shift;
_warn 'length of (url & data1 & data2 & data3) is too large(173 bytes).'
if length($self->url.$self->data1.$self->data2.$self->data3) > 173;
_warn 'url schme error (http only).'
unless $self->url =~ m|^http://|i;
$self->version('1.0') unless $self->version;
$self->type('SNIP') unless $self->type;
$self->cat('0000') unless $self->cat =~ m|^[0-9a-fA-F]{4,4}$|;
$self->cat('0000') unless $self->cat;
$self->cat(uc($self->cat));
}
sub build {
my $self = shift;
$self->_build;
return "ToruCa\r\n" .
'Version: ' . $self->version. "\r\n" .
'Type: ' . $self->type . "\r\n" .
"\r\n" .
'URL: '. $self->url . "\r\n" .
'Data1: ' . $self->_base64($self->data1) . "\r\n" .
'Data2: ' . $self->_base64($self->data2) . "\r\n" .
'Data3: ' . $self->_base64($self->data3) . "\r\n" .
'Cat: ' . $self->cat. "\r\n" .
"\r\n";
}
sub detail_build {
my $self = shift;
my $type = $self->type;
$self->type('CARD');
my $toruca = $self->build;
$self->type($type);
return $toruca . $self->mime;
}
sub html_build {
my $self = shift;
my $html = shift;
my $boundary;
my $i = 0;
while (1) {
$i++;
return if $i > 100;
$boundary = sprintf("%010d", rand(1000000000));
last unless $html =~ /$boundary/;
}
my $mime = $self->mime;
$self->mime("MIME-Version: 1.0\r\n" .
"Content-Type: multipart/mixed;boundary=\"$boundary\"\r\n" .
"\r\n" .
"--$boundary\r\n" .
"Content-Type: text/html; charset=Shift_JIS\r\n" .
"Content-Transfer-Encoding: 8bit\r\n" .
"\r\n" .
"$html\r\n" .
"--$boundary--\r\n");
my $toruca = $self->detail_build;
$self->mime($mime);
return $toruca;
}
sub rw_build {
my $self = shift;
$self->_build;
my $subprm = "\x01\x31\x30" .
pack("v", length($self->url)) . $self->url .
pack("v", length($self->data1)) . $self->data1 .
pack("v", length($self->data2)) . $self->data2 .
pack("v", length($self->data3)) . $self->data3;
$self->cat =~ /^(..)(..)$/;
my ($catb, $catl) = ($1, $2);
eval "\$subprm .= \"\\x$catb\\x$catl\";";
my $data = "\x01\x20" . pack("v", length($subprm)) . $subprm;
my $sum = 0;
foreach (split(//, $data)) {
$sum += unpack("C", $_);
}
$data .= pack("n", 65536 - ($sum % 65536));
return $data;
}
sub _base64 {
my $self = shift;
my $data = encode_base64(shift);
$data =~ s/\s//g;
return $data;
}
sub cat2pict {
my $cat = ref($_[0]) eq __PACKAGE__ ? $_[1] : $_[0];
return '' unless $cat =~ /^[0-9A-F]{1,4}$/io;
$cat =~ s/^0+//o;
my $base = hex($cat);
my $pad = 63646;
if ($base > 94 && $base < 105) {
$pad = 63808 - 95;
} elsif ($base > 104 && $base < 118) {
$pad = 63858 - 105;
} elsif ($base > 117 && $base < 135) {
$pad = 63872 - 118;
} elsif ($base eq 135) {
$pad = 63920 - 135;
} elsif ($base > 135 && $base < 167) {
$pad = 63889 - 136;
} elsif ($base > 166 && $base < 170) {
$pad = 63824 - 167;
} elsif ($base > 169 && $base < 173) {
$pad = 63829 - 170;
} elsif ($base > 172 && $base < 177) {
$pad = 63835 - 173;
} elsif ($base > 176) {
$pad = 63921 - 177;
}
return pack('n', $pad + $base);
}
1;
__END__
=head1 NAME
Data::ToruCa - ToruCa of NTT DoCoMo for treated.
=head1 SYNOPSIS
use Data::ToruCa;
$Data::ToruCa::VERBOSE = 1;#Warning is output by the favorite.
my $trc = Data::ToruCa->new($toruca_data);#making from ToruCa data.
my $trc = Data::ToruCa->new({
url => 'http://example.jp/toruca_detail.trc',
data1 => 'title',
data2 => 'description.',
data3 => 'Tokyo',
cat => '0001',
});#making from HASH.
$trc->data1('change title');
print $trc->url;
print $trc->build;
$trc->type('CARD');
$trc->html_build('top page');
$trc->mime($mime_parts);
print $trc->detail_build;
use Data::ToruCa qw(cat2pict);
print cat2pict('0001');#print 'sun' pict of imode.
=head1 DESCRIPTION
ToruCa that the cellular phone of NTT DoCoMo in Japan uses is treated.
=head1 Export
=over 4
=item cat2pic($category_code)
convert to imode pict from category code of toruca.
=back
=head1 Methods
=over 4
=item new($toruca_object)
making from ToruCa data.
=item new(%toruca_data)
making from HASH.
=item ext
get of ext type of ToruCa.
=item content_type
get of Content-Type of ToruCa.
=item version([$set_data])
getter/setter of ToruCa Version.
=item type([$set_data])
getter/setter of ToruCa Type.
=item url([$set_data])
getter/setter of ToruCa URL.
=item data1([$set_data])
getter/setter of ToruCa Data1.
=item data2([$set_data])
getter/setter of ToruCa Data2.
=item data3([$set_data])
getter/setter of ToruCa Data3.
=item cat([$set_data])
getter/setter of ToruCa category.
=item pict
convert to imode pict from category code of toruca of this object.
=item mime([$set_data])
getter/setter of MIME data of ToruCa Detail data.
=item parse($toruca_object)
The ToruCa data is anakyzed.
=item build
The ToruCa data is made.
=item detail_build
The ToruCa data of detail is made.
use mime data.
=item html_build
The detailed data of ToruCa is made.
=item rw_build($html)
The ToruCa data for Felica is made.
Onlu one html file can be appended.
=back
=head1 SEE ALSO
japanese site.
http://www.nttdocomo.co.jp/p_s/imode/make/toruca/index.html
=head1 AUTHOR
Kazuhiro, Osawako@yappo.ne.jpE
=head1 COPYRIGHT AND LICENSE
Copyright (C) 2005 by Kazuhiro, Osawa
This library is free software; you can redistribute it and/or modify
it under the same terms as Perl itself, either Perl version 5.8.5 or,
at your option, any later version of Perl 5 you may have available.
=cut