File Coverage

lib/XML/Compile/WSS.pm
Criterion Covered Total %
statement 30 101 29.7
branch 0 42 0.0
condition 0 11 0.0
subroutine 10 24 41.6
pod 10 13 76.9
total 50 191 26.1


line stmt bran cond sub pod time code
1             # Copyrights 2011-2017 by [Mark Overmeer].
2             # For other contributors see ChangeLog.
3             # See the manual pages for details on the licensing terms.
4             # Pod stripped from pm file by OODoc 2.02.
5 1     1   1130 use warnings;
  1         2  
  1         30  
6 1     1   4 use strict;
  1         2  
  1         24  
7              
8             package XML::Compile::WSS;
9 1     1   5 use vars '$VERSION';
  1         1  
  1         41  
10             $VERSION = '1.14';
11              
12              
13 1     1   4 use Log::Report 'xml-compile-wss';
  1         1  
  1         5  
14              
15 1     1   205 use XML::Compile::WSS::Util qw/:wss11/;
  1         2  
  1         157  
16 1     1   377 use XML::Compile::Util qw/SCHEMA2001/;
  1         1501  
  1         51  
17 1     1   420 use XML::Compile::Schema::BuiltInTypes qw/builtin_type_info/;
  1         58657  
  1         93  
18              
19 1     1   13 use File::Basename qw/dirname/;
  1         3  
  1         84  
20 1     1   7 use POSIX qw/strftime/;
  1         2  
  1         5  
21 1     1   57 use Scalar::Util qw/weaken/;
  1         2  
  1         1117  
22              
23             my %prefixes10 =
24             ( ds => DSIG_NS, wsse => WSSE_10, wsu => WSU_10
25             );
26              
27             my %prefixes11 =
28             ( ds => DSIG_NS, wsse => WSSE_10, wsu => WSU_10
29             , wss => WSS_11, xenc => XENC_NS
30             );
31              
32             my %versions =
33             ( '1.0' => { xsddir => 'wss10', prefixes => \%prefixes10 }
34             , '1.1' => { xsddir => 'wss11', prefixes => \%prefixes11 }
35             );
36              
37              
38             sub new(@)
39 0     0 1   { my $class = shift;
40 0 0         my $args = @_==1 ? shift : {@_};
41 0           my $self = (bless {}, $class)->init($args);
42 0   0       $self->prepare($args->{prepare} || 'ALL');
43 0           $self;
44             }
45              
46             sub init($)
47 0     0 0   { my ($self, $args) = @_;
48             my $version = $args->{wss_version} || $args->{version}
49 0 0 0       or error __x"explicit wss_version required";
50 0           trace "initializing wss $version";
51              
52 0 0         $version = '1.1'
53             if $version eq WSS11MODULE;
54              
55 0 0         $versions{$version}
56             or error __x"unknown wss version {v}, pick from {vs}"
57             , v => $version, vs => [keys %versions];
58 0           $self->{XCW_version} = $version;
59              
60 0 0         if(my $schema = $self->{XCW_schema} = $args->{schema})
61 0           { weaken $self->{XCW_schema};
62 0           $self->loadSchemas($schema, $version);
63             }
64              
65 0           $self;
66             }
67              
68             sub prepare($)
69 0     0 1   { my ($self, $how) = @_;
70 0           my $schema = $self->schema;
71              
72 0 0         my ($r, $w)
    0          
    0          
    0          
73             = $how eq 'ALL' ? (1, 1)
74             : $how eq 'READER' ? (1, 0)
75             : $how eq 'WRITER' ? (0, 1)
76             : $how eq 'NONE' ? (0, 0)
77             : panic $how;
78              
79 0 0         $self->prepareWriting($schema) if $w;
80 0 0         $self->prepareReading($schema) if $r;
81 0           $self;
82             }
83 0     0 0   sub prepareWriting($) { $_[0]->{XCW_prepare_w}++; $_[0] }
  0            
84 0     0 0   sub prepareReading($) { $_[0]->{XCW_prepare_r}++; $_[0] }
  0            
85              
86             #-----------
87              
88 0     0 1   sub version() {shift->{XCW_version}} # deprecated
89 0     0 1   sub wssVersion() {shift->{XCW_version}}
90 0     0 1   sub schema() {shift->{XCW_schema}}
91              
92             #-----------
93              
94             sub create($$)
95 0     0 1   { my $self = shift;
96             panic __x"WSS plugin {name} is not prepared for writing", name => ref $self
97 0 0         unless $self->{XCW_prepare_w};
98 0           $self;
99             }
100              
101              
102             sub check($)
103 0     0 1   { my $self = shift;
104             panic __x"WSS plugin {name} is not prepared for reading", name => ref $self
105 0 0         unless $self->{XCW_prepare_r};
106 0           $self;
107             }
108              
109             #-----------
110              
111             # wsu had "allow anything" date fields, not type dateTime
112             sub dateTime($)
113 0     0 1   { my ($self, $time) = @_;
114 0 0 0       return $time if !defined $time || ref $time;
115              
116 0           my $dateTime = builtin_type_info 'dateTime';
117 0 0         if($time !~ m/[^0-9.]/) { $time = $dateTime->{format}->($time) }
  0 0          
118             elsif($dateTime->{check}->($time)) {}
119 0           else {return $time}
120              
121 0           +{ _ => $time
122             , ValueType => SCHEMA2001.'/dateTime'
123             };
124             }
125              
126             #-----------
127              
128             sub loadSchemas($$)
129 0     0 1   { my ($thing, $schema, $version) = @_;
130 0 0         return if $schema->{XCW_wss_loaded}++;
131              
132 0 0         $schema->isa('XML::Compile::Cache')
133             or error __x"loadSchemas() requires a XML::Compile::Cache object";
134              
135 0           my $def = $versions{$version};
136 0           my $prefixes = $def->{prefixes};
137 0           $schema->addPrefixes($prefixes);
138              
139 0           my $rewrite = join ',', sort keys %$prefixes;
140 0           $schema->addKeyRewrite("PREFIXED($rewrite)");
141              
142 0           (my $xsddir = __FILE__) =~ s! \.pm$ !/$def->{xsddir}!x;
143 0           my @xsd = glob "$xsddir/*.xsd";
144              
145 0           trace "loading wss schemas $version";
146              
147 0           $schema->importDefinitions
148             ( \@xsd
149              
150             # Missing from wss-secext-1.1.xsd (schema BUG) Gladly, all
151             # provided schemas have element_form qualified.
152             , element_form_default => 'qualified'
153             );
154              
155             # Another schema bug; attribute wsu:Id not declared qualified
156             # Besides, ValueType is often used on timestamps, which are declared
157             # as free-format fields (@*!&$#!&^ design committees!)
158 0           my ($wsu10, $xsd) = (WSU_10, SCHEMA2001);
159 0           $schema->importDefinitions( <<__PATCH );
160            
161             xmlns="$xsd"
162             xmlns:wsu="$wsu10"
163             targetNamespace="$wsu10"
164             elementFormDefault="qualified"
165             attributeFormDefault="unqualified">
166            
167              
168            
169            
170            
171            
172            
173            
174            
175            
176              
177            
178             __PATCH
179              
180 0           $schema->allowUndeclared(1);
181 0           $schema->addCompileOptions('RW'
182             , mixed_elements => 'STRUCTURAL'
183             , ignore_unused_tags => qr/^wsu_Id$/
184             );
185              
186 0           $schema->anyElement('ATTEMPT');
187 0           $schema;
188             }
189              
190              
191             sub writerHookWsuId($)
192 0     0 1   { my ($self, $type) = @_;
193              
194             my $after = sub
195 0     0     { my ($doc, $node, $path, $val) = @_;
196              
197 0           my $id = $val->{wsu_Id};
198 0 0         defined $id or return $node;
199              
200             # Some schema explicitly list wsu:Id attributes, we shouldn't add
201             # the attribute again.
202 0 0 0       if(my $has = $node->getAttributeNS(WSU_10, 'Id')
203             || $node->getAttribute('wsu:Id'))
204 0 0         { $has eq $id or warning __x"two wsu:Id attributes: {one} and {two}"
205             , one => $id, two => $has;
206              
207 0           return $node;
208             }
209              
210 0           $node->setNamespace(WSU_10, 'wsu', 0);
211 0           $node->setAttributeNS(WSU_10, 'Id', $id);
212 0           $node;
213 0           };
214              
215 0           +{ action => 'WRITER', type => $type, after => $after };
216             }
217              
218             #---------------------------
219              
220              
221             1;