File Coverage

blib/lib/XML/Atom/Content.pm
Criterion Covered Total %
statement 83 85 97.6
branch 45 54 83.3
condition 13 17 76.4
subroutine 10 10 100.0
pod 0 3 0.0
total 151 169 89.3


line stmt bran cond sub pod time code
1             # $Id$
2              
3             package XML::Atom::Content;
4 21     21   221032 use strict;
  21         1480  
  21         1931  
5 21     21   115 use base qw( XML::Atom::Base );
  21         42  
  21         2582  
6              
7             __PACKAGE__->mk_attr_accessors(qw( type mode ));
8             __PACKAGE__->mk_xml_attr_accessors(qw( lang base ));
9              
10 21     21   137 use Encode;
  21         44  
  21         1652  
11 21     21   134 use XML::Atom;
  21         55  
  21         1027  
12 21     21   1400 use MIME::Base64 qw( encode_base64 decode_base64 );
  21         1568  
  21         24348  
13              
14 24     24 0 233 sub element_name { 'content' }
15              
16             sub init {
17 47     47 0 86 my $content = shift;
18 47 100       208 my %param = @_ == 1 ? (Body => $_[0]) : @_;
19 47         229 $content->SUPER::init(%param);
20 47 100       132 if ($param{Body}) {
21 12         43 $content->body($param{Body});
22             }
23 47 100       117 if ($param{Type}) {
24 1         6 $content->type($param{Type});
25             }
26 47         162 return $content;
27             }
28              
29             sub body {
30 48     48 0 314 my $content = shift;
31 48         216 my $elem = $content->elem;
32 48 100       127 if (@_) {
33 23         48 my $data = shift;
34 23         32 if (LIBXML) {
35 23         114 $elem->removeChildNodes;
36             } else {
37             $elem->removeChild($_) for $elem->getChildNodes;
38             }
39 23 100       63 if (!_is_printable($data)) {
40 5         41 Encode::_utf8_off($data);
41 5         10 if (LIBXML) {
42 5         162 $elem->appendChild(XML::LibXML::Text->new(encode_base64($data, '')));
43             } else {
44             $elem->appendChild(XML::XPath::Node::Text->new(encode_base64($data, '')));
45             }
46              
47 5 100       45 if ($content->version == 0.3) {
48 4         22 $content->mode('base64');
49             }
50             } else {
51 18         124 my $copy = '<div xmlns="http://www.w3.org/1999/xhtml">' .
52             $data .
53             '</div>';
54 18         34 my $node;
55 18         30 eval {
56 18         32 if (LIBXML) {
57 18         81 my $parser = XML::Atom->libxml_parser;
58 18         1783 my $tree = $parser->parse_string($copy);
59 15         3445 $node = $tree->getDocumentElement;
60             } else {
61             my $parser = XML::Atom->expat_parser;
62             my $xp = XML::XPath->new(xml => $copy, parser => $parser);
63             $node = (($xp->find('/')->get_nodelist)[0]->getChildNodes)[0]
64             if $xp;
65             }
66             };
67 18 100 66     2250 if (!$@ && $node) {
68 15         263 $elem->appendChild($node);
69 15 100       51 if ($content->version == 0.3) {
70 11         38 $content->mode('xml');
71             } else {
72 4         15 $content->type('xhtml');
73             }
74             } else {
75 3         556 if (LIBXML) {
76 3         38 $elem->appendChild(XML::LibXML::Text->new($data));
77             } else {
78             $elem->appendChild(XML::XPath::Node::Text->new($data));
79             }
80              
81 3 100       21 if ($content->version == 0.3) {
82 2         9 $content->mode('escaped');
83             } else {
84 1 50       11 $content->type($data =~ /^\s*</ ? 'html' : 'text');
85             }
86             }
87             }
88             } else {
89 25 50       160 unless (exists $content->{__body}) {
90 25         47 my $mode;
91              
92 25 100       72 if ($content->version == 0.3) {
93 20   100     68 $mode = $content->mode || 'xml';
94             } else {
95 5 50       19 $mode =
    100          
    100          
    50          
    100          
96             $content->type eq 'xhtml' ? 'xml'
97             : $content->type =~ m![/\+]xml$! ? 'xml'
98             : $content->type eq 'html' ? 'escaped'
99             : $content->type eq 'text' ? 'escaped'
100             : $content->type =~ m!^text/! ? 'escaped'
101             : 'base64';
102             }
103              
104 25 100       162 if ($mode eq 'xml') {
    100          
    50          
105 13         98 my @children = grep ref($_) =~ /Element/,
106             LIBXML ? $elem->childNodes : $elem->getChildNodes;
107 13 50       307 if (@children) {
108 13 100 66     129 if (@children == 1 && $children[0]->getLocalName eq 'div') {
109 12         40 @children =
110             LIBXML ? $children[0]->childNodes :
111             $children[0]->getChildNodes
112             }
113 13         288 $content->{__body} = '';
114 13         33 for my $n (@children) {
115 17         392 $content->{__body} .= $n->toString(LIBXML ? 1 : 0);
116             }
117             } else {
118 0         0 $content->{__body} = LIBXML ? $elem->textContent : $elem->string_value;
119             }
120 13 50       54 if ($] >= 5.008) {
121 13 50       72 Encode::_utf8_off($content->{__body}) unless $XML::Atom::ForceUnicode;
122             }
123             } elsif ($mode eq 'base64') {
124 7         222 my $raw = decode_base64(LIBXML ? $elem->textContent : $elem->string_value);
125 7 100 100     31 if ($content->type && $content->type =~ m!^text/!) {
126 2   33     6 $content->{__body} = eval { Encode::decode("utf-8", $raw) } || $raw;
127 2 50       108 Encode::_utf8_off($content->{__body}) unless $XML::Atom::ForceUnicode;
128             } else {
129 5         20 $content->{__body} = $raw;
130             }
131             } elsif ($mode eq 'escaped') {
132 5         61 $content->{__body} = LIBXML ? $elem->textContent : $elem->string_value;
133             } else {
134 0         0 $content->{__body} = undef;
135             }
136             }
137             }
138 48         736 $content->{__body};
139             }
140              
141             sub _is_printable {
142 23     23   40 my $data = shift;
143              
144 23         42 local $@;
145             # try decoding this $data with UTF-8
146             my $decoded =
147             ( Encode::is_utf8($data)
148             ? $data
149 23 100       93 : eval { Encode::decode("utf-8", $data, Encode::FB_CROAK) } );
  20         238  
150              
151 20   100 20   13262 return ! $@ && $decoded =~ /^[\p{IsPrint}\s]*$/;
  20         308  
  20         354  
  23         2426  
152             }
153              
154             1;