File Coverage

blib/lib/EBook/Ishmael/EBook/PalmDoc.pm
Criterion Covered Total %
statement 83 99 83.8
branch 14 28 50.0
condition 4 8 50.0
subroutine 19 19 100.0
pod 0 9 0.0
total 120 163 73.6


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