File Coverage

blib/lib/EBook/Ishmael/EBook/PalmDoc.pm
Criterion Covered Total %
statement 78 94 82.9
branch 12 26 46.1
condition 5 8 62.5
subroutine 18 18 100.0
pod 0 9 0.0
total 113 155 72.9


line stmt bran cond sub pod time code
1             package EBook::Ishmael::EBook::PalmDoc;
2 17     17   356 use 5.016;
  17         73  
3             our $VERSION = '2.01';
4 17     17   162 use strict;
  17         56  
  17         701  
5 17     17   115 use warnings;
  17         62  
  17         1353  
6              
7 17     17   122 use Encode qw(decode);
  17         40  
  17         1443  
8              
9 17     17   117 use EBook::Ishmael::Decode qw(palmdoc_decode);
  17         34  
  17         1057  
10 17     17   130 use EBook::Ishmael::EBook::Metadata;
  17         34  
  17         503  
11 17     17   86 use EBook::Ishmael::PDB;
  17         33  
  17         460  
12 17     17   8889 use EBook::Ishmael::TextToHtml;
  17         57  
  17         22087  
13              
14             my $TYPE = 'TEXt';
15             my $CREATOR = 'REAd';
16              
17             my $RECSIZE = 4096;
18              
19             sub heuristic {
20              
21 59     59 0 217 my $class = shift;
22 59         121 my $file = shift;
23 59         118 my $fh = shift;
24              
25 59 50       951 return 0 unless -s $file >= 68;
26              
27 59         319 seek $fh, 32, 0;
28 59         528 read $fh, my ($null), 1;
29              
30             # Last byte in title must be null
31 59 100       220 unless ($null eq "\0") {
32 35         163 return 0;
33             }
34              
35 24         169 seek $fh, 60, 0;
36 24         135 read $fh, my ($type), 4;
37 24         72 read $fh, my ($creator), 4;
38              
39 24   66     169 return $type eq $TYPE && $creator eq $CREATOR;
40              
41             }
42              
43             sub _decode_record {
44              
45 63     63   15182 my $self = shift;
46 63         96 my $rec = shift;
47              
48 63         108 $rec++;
49              
50 63         212 my $encode = $self->{_pdb}->record($rec)->data;
51              
52 63 50       349 if ($self->{_compression} == 1) {
    50          
53 0         0 return $encode;
54             } elsif ($self->{_compression} == 2) {
55 63         182 return palmdoc_decode($encode);
56             }
57              
58             }
59              
60             sub new {
61              
62 11     11 0 54 my $class = shift;
63 11         24 my $file = shift;
64 11   100     51 my $enc = shift // 'UTF-8';
65              
66 11         107 my $self = {
67             Source => undef,
68             Metadata => EBook::Ishmael::EBook::Metadata->new,
69             Encoding => $enc,
70             _pdb => undef,
71             _compression => undef,
72             _textlen => undef,
73             _recnum => undef,
74             _recsize => undef,
75             _curpos => undef,
76             };
77              
78 11         28 bless $self, $class;
79              
80 11         482 $self->{Source} = File::Spec->rel2abs($file);
81              
82 11         98 $self->{_pdb} = EBook::Ishmael::PDB->new($file);
83              
84 11         63 my $hdr = $self->{_pdb}->record(0)->data;
85              
86             (
87             $self->{_compression},
88             undef,
89             $self->{_textlen},
90             $self->{_recnum},
91             $self->{_recsize},
92             $self->{_curpos},
93 11         76 ) = unpack "n n N n n N", $hdr;
94              
95 11 50 33     86 if ($self->{_compression} != 1 and $self->{_compression} != 2) {
96 0         0 die "$self->{Source} is not a PalmDoc file\n";
97             }
98              
99 11 50       36 if ($self->{_recsize} != 4096) {
100 0         0 die "$self->{Source} is not a PalmDoc file\n";
101             }
102              
103 11         51 $self->{Metadata}->set_title($self->{_pdb}->name);
104              
105 11 50       43 if ($self->{_pdb}->cdate) {
106 11         32 $self->{Metadata}->set_created($self->{_pdb}->cdate);
107             }
108 11 50       42 if ($self->{_pdb}->mdate) {
109 11         32 $self->{Metadata}->set_modified($self->{_pdb}->mdate);
110             }
111              
112 11 50       41 if ($self->{_pdb}->version) {
113             $self->{Metadata}->set_format(
114             sprintf(
115             "PalmDOC %s.%s",
116             ($self->{_pdb}->version >> 8) & 0xff,
117 0         0 $self->{_pdb}->version & 0xff
118             )
119             );
120             } else {
121 11         42 $self->{Metadata}->set_format('PalmDOC');
122             }
123              
124 11         49 return $self;
125              
126             }
127              
128             sub html {
129              
130 3     3 0 10 my $self = shift;
131 3         8 my $out = shift;
132              
133             my $html = decode(
134             $self->{Encoding},
135             text2html(
136 3         26 join('', map { $self->_decode_record($_) } 0 .. $self->{_recnum} - 1)
  27         122  
137             ),
138             );
139              
140 3 50       1474 if (defined $out) {
141 0 0       0 open my $fh, '>', $out
142             or die "Failed to open $out for writing: $!\n";
143 0         0 binmode $fh, ':utf8';
144 0         0 print { $fh } $html;
  0         0  
145 0         0 close $fh;
146 0         0 return $out;
147             } else {
148 3         28 return $html;
149             }
150              
151             }
152              
153             sub raw {
154              
155 3     3 0 8 my $self = shift;
156 3         8 my $out = shift;
157              
158             my $raw = decode(
159             $self->{Encoding},
160 3         20 join('', map { $self->_decode_record($_) } 0 .. $self->{_recnum} - 1)
  27         110  
161             );
162              
163 3 50       842 if (defined $out) {
164 0 0       0 open my $fh, '>', $out
165             or die "Failed to open $out for writing: $!\n";
166 0         0 binmode $fh, ':utf8';
167 0         0 print { $fh } $raw;
  0         0  
168 0         0 close $fh;
169 0         0 return $out;
170             } else {
171 3         19 return $raw;
172             }
173              
174             }
175              
176             sub metadata {
177              
178 4     4 0 11 my $self = shift;
179              
180 4         25 return $self->{Metadata};
181              
182             }
183              
184 2     2 0 12 sub has_cover { 0 }
185              
186 1     1 0 6 sub cover { undef }
187              
188 2     2 0 11 sub image_num { 0 }
189              
190 1     1 0 6 sub image { undef }
191              
192             1;