File Coverage

blib/lib/Dancer/Serializer/XML.pm
Criterion Covered Total %
statement 24 58 41.3
branch 0 10 0.0
condition 0 10 0.0
subroutine 8 18 44.4
pod 4 8 50.0
total 36 104 34.6


line stmt bran cond sub pod time code
1             package Dancer::Serializer::XML;
2             our $AUTHORITY = 'cpan:SUKRIA';
3             #ABSTRACT: serializer for handling XML data
4             $Dancer::Serializer::XML::VERSION = '1.3520';
5 165     165   1221 use strict;
  165         382  
  165         5044  
6 165     165   907 use warnings;
  165         423  
  165         4097  
7 165     165   997 use Carp;
  165         492  
  165         9616  
8 165     165   1218 use Dancer::ModuleLoader;
  165         494  
  165         4932  
9 165     165   1122 use Dancer::Config 'setting';
  165         425  
  165         8293  
10 165     165   1073 use base 'Dancer::Serializer::Abstract';
  165         502  
  165         87778  
11              
12             # singleton for the XML::Simple object
13             my $_xs;
14              
15             # helpers
16              
17             sub from_xml {
18 0     0 0   my $s = Dancer::Serializer::XML->new;
19 0           $s->deserialize(@_);
20             }
21              
22             sub to_xml {
23 0     0 0   my $s = Dancer::Serializer::XML->new;
24 0           $s->serialize(@_);
25             }
26              
27             # class definition
28              
29             sub loaded_xmlsimple {
30 0     0 0   Dancer::ModuleLoader->load('XML::Simple');
31             }
32              
33             sub loaded_xmlbackends {
34             # we need either XML::Parser or XML::SAX too
35 0 0   0 0   Dancer::ModuleLoader->load('XML::Parser') or
36             Dancer::ModuleLoader->load('XML::SAX');
37             }
38              
39             sub init {
40 0     0 1   my ($self) = @_;
41 0 0         die 'XML::Simple is needed and is not installed'
42             unless $self->loaded_xmlsimple;
43 0 0         die 'XML::Simple needs XML::Parser or XML::SAX and neither is installed'
44             unless $self->loaded_xmlbackends;
45             # Disable fetching external entities, as that's a security hole: this allows
46             # someone to fetch remote websites from the server, or to read local files.
47             # This only works for XML::Parser when called directly from XML::Simple;
48             # for XML::SAX we'll need to do some even *more* horrible stuff later on.
49             $_xs = XML::Simple->new(
50             ParserOpts => [
51             Handlers => {
52             ExternEnt => sub {
53 0     0     return '';
54             }
55             }
56 0           ],
57             );
58             }
59              
60             sub serialize {
61 0     0 1   my $self = shift;
62 0           my $entity = shift;
63 0           my %options = (RootName => 'data');
64              
65 0   0       my $s = setting('engines') || {};
66 0 0 0       if (exists($s->{XMLSerializer}) && exists($s->{XMLSerializer}{serialize})) {
67 0           %options = (%options, %{$s->{XMLSerializer}{serialize}});
  0            
68             }
69              
70 0           %options = (%options, @_);
71              
72              
73 0           $_xs->XMLout($entity, %options);
74             }
75              
76 0           sub deserialize {
77 0     0 1   my $self = shift;
78 0           my $xml = shift;
79 0           my %options = ();
80              
81 0   0       my $s = setting('engines') || {};
82 0 0 0       if (exists($s->{XMLSerializer}) && exists($s->{XMLSerializer}{deserialize})) {
83 0           %options = (%options, %{$s->{XMLSerializer}{deserialize}});
  0            
84             }
85              
86 0           %options = (%options, @_);
87             # This is the promised terrible hack: claim that the LWP-talking code has
88             # already been loaded, and make sure that the handler that's called when
89             # we're dealing with an external entity does nothing.
90             # For whichever reason, this handler is called despite XML::Parser
91             # (which on my machine is the only XML::SAX backend that can handle
92             # external entities) having a ParseParamEnt option which is off by default,
93             # but appears to only be used deep in the XML::Parser XS guts.
94 165     165   1532 no warnings 'redefine';
  165         561  
  165         16472  
95 0     0     local *XML::Parser::lwp_ext_ent_handler = sub { return };
  0            
96 0           local $INC{'XML/Parser/LWPExternEnt.pl'}
97             = 'Dancer::Serializer::XML disabled loading this to patch around '
98             . 'XXE vulnerabilities';
99 0           $_xs->XMLin($xml, %options);
100 165     165   1295 use warnings 'redefine';
  165         556  
  165         16986  
101             }
102              
103 0     0 1   sub content_type {'text/xml'}
104              
105             1;
106              
107             __END__