File Coverage

blib/lib/Data/ToruCa.pm
Criterion Covered Total %
statement 90 121 74.3
branch 46 62 74.1
condition 22 24 91.6
subroutine 20 25 80.0
pod 17 18 94.4
total 195 250 78.0


line stmt bran cond sub pod time code
1             package Data::ToruCa;
2              
3 4     4   576881 use strict;
  4         10  
  4         159  
4 4     4   100603 use MIME::Base64;
  4         3287  
  4         261  
5              
6 4     4   24 use vars qw(@ISA @EXPORT_OK);
  4         13  
  4         8387  
7              
8             require Exporter;
9             @ISA = qw(Exporter);
10             @EXPORT_OK = qw(cat2pict);
11              
12             our $VERSION = '0.06';
13             our $VERBOSE = 0;
14              
15             sub new {
16 3     3 1 33 my $class = shift;
17 3         6 my $opt = shift;
18              
19 3         9 my $self = bless {}, $class;
20 3 100 33     22 if (ref($opt) eq 'HASH') {
    50          
21 1         5 foreach (keys %$opt) {
22 7         17 $self->{$_} = $opt->{$_};
23             }
24             } elsif (ref($opt) eq '' && $opt) {
25 2         8 $self->parse($opt);
26             }
27              
28 3         8 return $self;
29             }
30              
31             sub _warn {
32 0 0   0   0 warn shift
33             if ($VERBOSE);
34             }
35              
36 0     0 1 0 sub ext {'trc'}
37 0     0 1 0 sub content_type {'application/x-toruca'}
38              
39             sub _accessor {
40 69     69   78 my $self = shift;
41 69         70 my $field = shift;
42 69         68 my $size = shift;
43 69         69 my $data = shift;
44 69 100       290 return $self->{$field} unless $data;
45 18 50       36 _warn "length of $field is too large($size bytes)."
46             if length($data) > $size;
47 18         53 $self->{$field} = $data;
48             }
49 6     6 1 29 sub version {shift->_accessor('version', 4, @_)}
50 9     9 1 20 sub type {shift->_accessor('type', 8, @_)}
51 8     8 1 19 sub url {shift->_accessor('url', 127, @_)}
52 6     6 1 15 sub data1 {shift->_accessor('data1', 40, @_)}
53 6     6 1 22 sub data2 {shift->_accessor('data2', 100, @_)}
54 6     6 1 13 sub data3 {shift->_accessor('data3', 20, @_)}
55 14     14 1 29 sub cat {shift->_accessor('cat', 4, @_)}
56 5 100   5 1 9 sub mime {my $self = shift;return $self->{mime} = @_ ? shift : $self->{mime}}
  5         34  
57 2     2 1 3 sub pict {my $self = shift;$self->cat2pict($self->cat);}
  2         3  
58              
59             sub parse {
60 2     2 1 4 my $self = shift;
61 2         2 my $trc = shift;
62              
63 2 50       12 unless ($trc =~ /^ToruCa\r\n/) {
64 0         0 _warn 'toruca format error.';
65 0         0 return 0;
66             }
67              
68 2         3 my $mime;
69 2         4 my $c = 0;
70 2         15 foreach (split(/\r\n/, $trc)) {
71 28 100       38 if ($c < 2) {
72 19 100       62 if (/^([^:]+): (.+)$/) {
    100          
73 14         39 my ($field, $data) = (lc($1), $2);
74 14 100       62 $data = decode_base64($data)
75             if ($field =~ /^data/);
76 14         29 $self->_accessor($field, 200, $data);
77             } elsif ($_ eq '') {
78 3         4 $c++;
79             }
80             } else {
81 9         13 $mime .= "$_\r\n";
82             }
83             }
84 2 100       8 if ($mime) {
85 1         2 $mime =~ s/^\r\n//;
86 1         4 $mime =~ s/\r\n$//;
87 1         3 $self->mime($mime);
88             }
89 2         3 return 1;
90             }
91              
92             sub _build {
93 2     2   3 my $self = shift;
94              
95 2 50       5 _warn 'length of (url & data1 & data2 & data3) is too large(173 bytes).'
96             if length($self->url.$self->data1.$self->data2.$self->data3) > 173;
97              
98 2 50       7 _warn 'url schme error (http only).'
99             unless $self->url =~ m|^http://|i;
100              
101 2 50       6 $self->version('1.0') unless $self->version;
102 2 50       4 $self->type('SNIP') unless $self->type;
103 2 50       5 $self->cat('0000') unless $self->cat =~ m|^[0-9a-fA-F]{4,4}$|;
104 2 50       5 $self->cat('0000') unless $self->cat;
105 2         5 $self->cat(uc($self->cat));
106             }
107              
108             sub build {
109 2     2 1 9 my $self = shift;
110              
111 2         5 $self->_build;
112              
113 2         4 return "ToruCa\r\n" .
114             'Version: ' . $self->version. "\r\n" .
115             'Type: ' . $self->type . "\r\n" .
116             "\r\n" .
117             'URL: '. $self->url . "\r\n" .
118             'Data1: ' . $self->_base64($self->data1) . "\r\n" .
119             'Data2: ' . $self->_base64($self->data2) . "\r\n" .
120             'Data3: ' . $self->_base64($self->data3) . "\r\n" .
121             'Cat: ' . $self->cat. "\r\n" .
122             "\r\n";
123             }
124              
125             sub detail_build {
126 1     1 1 2 my $self = shift;
127              
128 1         2 my $type = $self->type;
129 1         24 $self->type('CARD');
130 1         7 my $toruca = $self->build;
131 1         4 $self->type($type);
132              
133 1         3 return $toruca . $self->mime;
134             }
135              
136             sub html_build {
137 0     0 1 0 my $self = shift;
138 0         0 my $html = shift;
139              
140 0         0 my $boundary;
141 0         0 my $i = 0;
142 0         0 while (1) {
143 0         0 $i++;
144 0 0       0 return if $i > 100;
145 0         0 $boundary = sprintf("%010d", rand(1000000000));
146 0 0       0 last unless $html =~ /$boundary/;
147             }
148              
149 0         0 my $mime = $self->mime;
150 0         0 $self->mime("MIME-Version: 1.0\r\n" .
151             "Content-Type: multipart/mixed;boundary=\"$boundary\"\r\n" .
152             "\r\n" .
153             "--$boundary\r\n" .
154             "Content-Type: text/html; charset=Shift_JIS\r\n" .
155             "Content-Transfer-Encoding: 8bit\r\n" .
156             "\r\n" .
157             "$html\r\n" .
158             "--$boundary--\r\n");
159 0         0 my $toruca = $self->detail_build;
160 0         0 $self->mime($mime);
161              
162 0         0 return $toruca;
163             }
164              
165             sub rw_build {
166 0     0 1 0 my $self = shift;
167              
168 0         0 $self->_build;
169              
170 0         0 my $subprm = "\x01\x31\x30" .
171             pack("v", length($self->url)) . $self->url .
172             pack("v", length($self->data1)) . $self->data1 .
173             pack("v", length($self->data2)) . $self->data2 .
174             pack("v", length($self->data3)) . $self->data3;
175 0         0 $self->cat =~ /^(..)(..)$/;
176 0         0 my ($catb, $catl) = ($1, $2);
177 0         0 eval "\$subprm .= \"\\x$catb\\x$catl\";";
178              
179 0         0 my $data = "\x01\x20" . pack("v", length($subprm)) . $subprm;
180              
181 0         0 my $sum = 0;
182 0         0 foreach (split(//, $data)) {
183 0         0 $sum += unpack("C", $_);
184             }
185 0         0 $data .= pack("n", 65536 - ($sum % 65536));
186              
187 0         0 return $data;
188             }
189              
190             sub _base64 {
191 6     6   10 my $self = shift;
192 6         27 my $data = encode_base64(shift);
193 6         17 $data =~ s/\s//g;
194 6         20 return $data;
195             }
196              
197             sub cat2pict {
198 31 100   31 0 141 my $cat = ref($_[0]) eq __PACKAGE__ ? $_[1] : $_[0];
199 31 50       253 return '' unless $cat =~ /^[0-9A-F]{1,4}$/io;
200 31         143 $cat =~ s/^0+//o;
201              
202 31         79 my $base = hex($cat);
203 31         48 my $pad = 63646;
204 31 100 100     553 if ($base > 94 && $base < 105) {
    100 100        
    100 100        
    100 100        
    100 100        
    100 100        
    100 100        
    100          
    100          
205 3         7 $pad = 63808 - 95;
206             } elsif ($base > 104 && $base < 118) {
207 3         5 $pad = 63858 - 105;
208             } elsif ($base > 117 && $base < 135) {
209 3         4 $pad = 63872 - 118;
210             } elsif ($base eq 135) {
211 1         4 $pad = 63920 - 135;
212             } elsif ($base > 135 && $base < 167) {
213 4         6 $pad = 63889 - 136;
214             } elsif ($base > 166 && $base < 170) {
215 2         6 $pad = 63824 - 167;
216             } elsif ($base > 169 && $base < 173) {
217 2         5 $pad = 63829 - 170;
218             } elsif ($base > 172 && $base < 177) {
219 2         6 $pad = 63835 - 173;
220             } elsif ($base > 176) {
221 2         7 $pad = 63921 - 177;
222             }
223 31         231 return pack('n', $pad + $base);
224             }
225              
226             1;
227             __END__