| line | stmt | bran | cond | sub | pod | time | code | 
| 1 |  |  |  |  |  |  | # Copyrights 2007-2022 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.03. | 
| 5 |  |  |  |  |  |  | # This code is part of distribution XML-Compile-SOAP-Daemon.  Meta-POD | 
| 6 |  |  |  |  |  |  | # processed with OODoc into POD and HTML manual-pages.  See README.md | 
| 7 |  |  |  |  |  |  | # Copyright Mark Overmeer.  Licensed under the same terms as Perl itself. | 
| 8 |  |  |  |  |  |  |  | 
| 9 |  |  |  |  |  |  | package XML::Compile::SOAP::Daemon; | 
| 10 | 2 |  |  | 2 |  | 362094 | use vars '$VERSION'; | 
|  | 2 |  |  |  |  | 6 |  | 
|  | 2 |  |  |  |  | 133 |  | 
| 11 |  |  |  |  |  |  | $VERSION = '3.15'; | 
| 12 |  |  |  |  |  |  |  | 
| 13 |  |  |  |  |  |  |  | 
| 14 | 2 |  |  | 2 |  | 14 | use warnings; | 
|  | 2 |  |  |  |  | 3 |  | 
|  | 2 |  |  |  |  | 51 |  | 
| 15 | 2 |  |  | 2 |  | 55 | use strict; | 
|  | 2 |  |  |  |  | 7 |  | 
|  | 2 |  |  |  |  | 75 |  | 
| 16 |  |  |  |  |  |  |  | 
| 17 | 2 |  |  | 2 |  | 11 | use Log::Report 'xml-compile-soap-daemon'; | 
|  | 2 |  |  |  |  | 6 |  | 
|  | 2 |  |  |  |  | 31 |  | 
| 18 |  |  |  |  |  |  |  | 
| 19 | 2 |  |  | 2 |  | 829 | use XML::LibXML        (); | 
|  | 2 |  |  |  |  | 6 |  | 
|  | 2 |  |  |  |  | 55 |  | 
| 20 | 2 |  |  | 2 |  | 18 | use XML::Compile::Util qw/type_of_node/; | 
|  | 2 |  |  |  |  | 4 |  | 
|  | 2 |  |  |  |  | 120 |  | 
| 21 | 2 |  |  | 2 |  | 14 | use XML::Compile::SOAP (); | 
|  | 2 |  |  |  |  | 11 |  | 
|  | 2 |  |  |  |  | 81 |  | 
| 22 |  |  |  |  |  |  |  | 
| 23 |  |  |  |  |  |  | # We use HTTP status definitions for each soap protocol, but HTTP::Status | 
| 24 |  |  |  |  |  |  | # may not be installed. | 
| 25 |  |  |  |  |  |  | use constant | 
| 26 | 2 |  |  |  |  | 4857 | { RC_SEE_OTHER            => 303 | 
| 27 |  |  |  |  |  |  | , RC_FORBIDDEN            => 403 | 
| 28 |  |  |  |  |  |  | , RC_NOT_FOUND            => 404 | 
| 29 |  |  |  |  |  |  | , RC_UNPROCESSABLE_ENTITY => 422 | 
| 30 |  |  |  |  |  |  | , RC_NOT_IMPLEMENTED      => 501 | 
| 31 | 2 |  |  | 2 |  | 12 | }; | 
|  | 2 |  |  |  |  | 4 |  | 
| 32 |  |  |  |  |  |  |  | 
| 33 |  |  |  |  |  |  | my $parser        = XML::LibXML->new; | 
| 34 |  |  |  |  |  |  |  | 
| 35 |  |  |  |  |  |  |  | 
| 36 |  |  |  |  |  |  | sub new(@) | 
| 37 | 1 |  |  | 1 | 1 | 426 | {   my $class = shift; | 
| 38 | 1 | 50 |  |  |  | 5 | $class ne __PACKAGE__ | 
| 39 |  |  |  |  |  |  | or error __x"you can only use extensions of {pkg}", pkg => __PACKAGE__; | 
| 40 | 1 |  |  |  |  | 6 | (bless {}, $class)->init( {@_} ); | 
| 41 |  |  |  |  |  |  | } | 
| 42 |  |  |  |  |  |  |  | 
| 43 |  |  |  |  |  |  | sub init($) | 
| 44 | 1 |  |  | 1 | 0 | 3 | {   my ($self, $args) = @_; | 
| 45 |  |  |  |  |  |  | $self->{accept_slow_select} | 
| 46 | 1 | 50 |  |  |  | 7 | = exists $args->{accept_slow_select} ? $args->{accept_slow_select} : 1; | 
| 47 |  |  |  |  |  |  |  | 
| 48 | 1 |  |  |  |  | 7 | $self->addWsaTable(INPUT  => $args->{wsa_action_input}); | 
| 49 | 1 |  |  |  |  | 5 | $self->addWsaTable(OUTPUT => $args->{wsa_action_output}); | 
| 50 | 1 |  |  |  |  | 8 | $self->addSoapAction($args->{soap_action_input}); | 
| 51 |  |  |  |  |  |  |  | 
| 52 | 1 | 50 |  |  |  | 3 | if(my $support = delete $args->{support_soap}) | 
| 53 |  |  |  |  |  |  | {   # simply only load the protocol versions you want to accept. | 
| 54 | 0 |  |  |  |  | 0 | error __x"new(support_soap} removed in 2.00"; | 
| 55 |  |  |  |  |  |  | } | 
| 56 |  |  |  |  |  |  |  | 
| 57 | 1 |  |  |  |  | 10 | my @classes = XML::Compile::SOAP->registered; | 
| 58 |  |  |  |  |  |  | @classes   # explicit load required since 2.00 | 
| 59 | 1 | 50 |  |  |  | 8 | or warning "No protocol modules loaded.  Need XML::Compile::SOAP11?"; | 
| 60 |  |  |  |  |  |  |  | 
| 61 | 1 |  | 50 |  |  | 6 | $self->{output_charset} = delete $args->{output_charset} || 'UTF-8'; | 
| 62 | 1 |  |  |  |  | 3 | $self->{handler}        = {}; | 
| 63 | 1 |  |  |  |  | 4 | $self; | 
| 64 |  |  |  |  |  |  | } | 
| 65 |  |  |  |  |  |  |  | 
| 66 |  |  |  |  |  |  | #----------- | 
| 67 |  |  |  |  |  |  |  | 
| 68 | 0 |  |  | 0 | 1 | 0 | sub outputCharset() {shift->{output_charset}} | 
| 69 |  |  |  |  |  |  |  | 
| 70 |  |  |  |  |  |  |  | 
| 71 |  |  |  |  |  |  | sub addWsaTable($@) | 
| 72 | 2 |  |  | 2 | 1 | 5 | {   my ($self, $dir) = (shift, shift); | 
| 73 | 2 | 50 |  |  |  | 7 | my $h = @_==1 ? shift : { @_ }; | 
| 74 |  |  |  |  |  |  | my $t = $dir eq 'INPUT'  ? ($self->{wsa_input}  ||= {}) | 
| 75 |  |  |  |  |  |  | : $dir eq 'OUTPUT' ? ($self->{wsa_output} ||= {}) | 
| 76 | 2 | 50 | 50 |  |  | 16 | : error __x("addWsaTable requires 'INPUT' or 'OUTPUT', not {got}" | 
|  |  | 100 | 50 |  |  |  |  | 
| 77 |  |  |  |  |  |  | , got => $dir); | 
| 78 |  |  |  |  |  |  |  | 
| 79 | 2 |  | 0 |  |  | 10 | while(my($op, $action) = each %$h) { $t->{$op} ||= $action } | 
|  | 0 |  |  |  |  | 0 |  | 
| 80 | 2 |  |  |  |  | 5 | $t; | 
| 81 |  |  |  |  |  |  | } | 
| 82 |  |  |  |  |  |  |  | 
| 83 |  |  |  |  |  |  |  | 
| 84 |  |  |  |  |  |  | sub addSoapAction(@) | 
| 85 | 1 |  |  | 1 | 1 | 2 | {   my $self = shift; | 
| 86 | 1 | 50 |  |  |  | 3 | my $h = @_==1 ? shift : { @_ }; | 
| 87 | 1 |  | 50 |  |  | 7 | my $t = $self->{sa_input}     ||= {}; | 
| 88 | 1 |  | 50 |  |  | 6 | my $r = $self->{sa_input_rev} ||= {}; | 
| 89 | 1 |  |  |  |  | 5 | while(my($op, $action) = each %$h) | 
| 90 | 0 |  | 0 |  |  | 0 | {   $t->{$op}     ||= $action; | 
| 91 | 0 |  | 0 |  |  | 0 | $r->{$action} ||= $op; | 
| 92 |  |  |  |  |  |  | } | 
| 93 | 1 |  |  |  |  | 3 | $t; | 
| 94 |  |  |  |  |  |  | } | 
| 95 |  |  |  |  |  |  |  | 
| 96 |  |  |  |  |  |  | #------------------ | 
| 97 |  |  |  |  |  |  |  | 
| 98 |  |  |  |  |  |  | sub run(@) | 
| 99 | 0 |  |  | 0 | 1 | 0 | {   my ($self, %args) = @_; | 
| 100 |  |  |  |  |  |  | notice __x"WSA module loaded, but not used" | 
| 101 | 0 | 0 | 0 |  |  | 0 | if XML::Compile::SOAP::WSA->can('new') && !keys %{$self->{wsa_input}}; | 
|  | 0 |  |  |  |  | 0 |  | 
| 102 |  |  |  |  |  |  |  | 
| 103 | 0 |  |  |  |  | 0 | $self->{wsa_input_rev}  = +{ reverse %{$self->{wsa_input}} }; | 
|  | 0 |  |  |  |  | 0 |  | 
| 104 | 0 |  |  |  |  | 0 | $self->_run(\%args); | 
| 105 |  |  |  |  |  |  | } | 
| 106 |  |  |  |  |  |  |  | 
| 107 |  |  |  |  |  |  |  | 
| 108 |  |  |  |  |  |  | # defined by Net::Server | 
| 109 | 0 |  |  | 0 | 0 | 0 | sub process_request(@) { panic "must be extended" } | 
| 110 |  |  |  |  |  |  |  | 
| 111 |  |  |  |  |  |  | sub process($) | 
| 112 | 4 |  |  | 4 | 1 | 15 | {   my ($self, $input, $req, $soapaction) = @_; | 
| 113 |  |  |  |  |  |  |  | 
| 114 | 4 |  |  |  |  | 7 | my $xmlin; | 
| 115 | 4 | 50 |  |  |  | 17 | if(! defined $input) | 
|  |  | 50 |  |  |  |  |  | 
| 116 | 0 |  |  |  |  | 0 | {  return $self->faultNotSoapMessage('No input'); | 
| 117 |  |  |  |  |  |  | } | 
| 118 |  |  |  |  |  |  | elsif(ref $input eq 'SCALAR') | 
| 119 | 4 |  |  | 4 |  | 23 | {   $xmlin = try { $parser->parse_string($$input) }; | 
|  | 4 |  |  |  |  | 1409 |  | 
| 120 | 4 | 100 |  |  |  | 1820 | return $self->faultInvalidXML($@->wasFatal) if $@; | 
| 121 |  |  |  |  |  |  | } | 
| 122 |  |  |  |  |  |  | else | 
| 123 | 0 |  |  |  |  | 0 | {   $xmlin = $input; | 
| 124 |  |  |  |  |  |  | } | 
| 125 |  |  |  |  |  |  |  | 
| 126 | 3 | 50 |  |  |  | 86 | $xmlin     = $xmlin->documentElement | 
| 127 |  |  |  |  |  |  | if $xmlin->isa('XML::LibXML::Document'); | 
| 128 |  |  |  |  |  |  |  | 
| 129 | 3 |  |  |  |  | 20 | my $local  = $xmlin->localName; | 
| 130 | 3 | 100 |  |  |  | 14 | $local eq 'Envelope' | 
| 131 |  |  |  |  |  |  | or return $self->faultNotSoapMessage(type_of_node $xmlin); | 
| 132 |  |  |  |  |  |  |  | 
| 133 | 2 |  | 50 |  |  | 9 | my $envns  = $xmlin->namespaceURI || ''; | 
| 134 | 2 | 100 |  |  |  | 16 | my $proto  = XML::Compile::SOAP->fromEnvelope($envns) | 
| 135 |  |  |  |  |  |  | or return $self->faultUnsupportedSoapVersion($envns); | 
| 136 |  |  |  |  |  |  | # proto is a XML::Compile::SOAP*::Operation | 
| 137 | 1 |  |  |  |  | 29 | my $server = $proto->serverClass; | 
| 138 |  |  |  |  |  |  |  | 
| 139 | 1 |  |  |  |  | 8 | my $info   = XML::Compile::SOAP->messageStructure($xmlin); | 
| 140 | 1 |  |  |  |  | 182 | my $version  = $info->{soap_version} = $proto->version; | 
| 141 | 1 |  | 50 |  |  | 7 | my $handlers = $self->{handler}{$version} || {}; | 
| 142 |  |  |  |  |  |  |  | 
| 143 |  |  |  |  |  |  | # Try to resolve operation via WSA | 
| 144 | 1 |  |  |  |  | 4 | my $wsa_in   = $self->{wsa_input_rev}; | 
| 145 | 1 | 50 |  |  |  | 4 | if(my $wsa_action = $info->{wsa_action}) | 
| 146 | 0 | 0 |  |  |  | 0 | {   if(my $name = $wsa_in->{$wsa_action}) | 
| 147 | 0 |  |  |  |  | 0 | {   my $handler = $handlers->{$name}; | 
| 148 | 0 |  |  |  |  | 0 | local $info->{selected_by} = 'wsa-action'; | 
| 149 | 0 |  |  |  |  | 0 | my ($rc, $msg, $xmlout) = $handler->($name, $xmlin, $info, $req); | 
| 150 | 0 | 0 |  |  |  | 0 | if($xmlout) | 
| 151 | 0 |  |  |  |  | 0 | {   trace "data ready for $version $name, via wsa $wsa_action"; | 
| 152 | 0 |  |  |  |  | 0 | return ($rc, $msg, $xmlout); | 
| 153 |  |  |  |  |  |  | } | 
| 154 |  |  |  |  |  |  | } | 
| 155 |  |  |  |  |  |  | } | 
| 156 |  |  |  |  |  |  |  | 
| 157 |  |  |  |  |  |  | # Try to resolve operation via soapAction | 
| 158 | 1 |  |  |  |  | 3 | my $sa = $self->{sa_input_rev}; | 
| 159 | 1 | 50 |  |  |  | 2 | if(defined $soapaction) | 
| 160 | 1 | 50 |  |  |  | 19 | {   if(my $name = $sa->{$soapaction}) | 
| 161 | 0 |  |  |  |  | 0 | {   my $handler = $handlers->{$name}; | 
| 162 | 0 |  |  |  |  | 0 | local $info->{selected_by} = 'soap-action'; | 
| 163 | 0 |  |  |  |  | 0 | my ($rc, $msg, $xmlout) = $handler->($name, $xmlin, $info, $req); | 
| 164 | 0 | 0 |  |  |  | 0 | if($xmlout) | 
| 165 | 0 |  |  |  |  | 0 | {   trace "data ready for $version $name, via sa '$soapaction'"; | 
| 166 | 0 |  |  |  |  | 0 | return ($rc, $msg, $xmlout); | 
| 167 |  |  |  |  |  |  | } | 
| 168 |  |  |  |  |  |  | } | 
| 169 |  |  |  |  |  |  | } | 
| 170 |  |  |  |  |  |  |  | 
| 171 |  |  |  |  |  |  | # Last resort, try each of the operations for the first which | 
| 172 |  |  |  |  |  |  | # can be parsed correctly. | 
| 173 | 1 | 50 |  |  |  | 5 | if($self->{accept_slow_select}) | 
| 174 | 1 |  |  |  |  | 2 | {   keys %$handlers;  # reset each() | 
| 175 | 1 |  |  |  |  | 7 | $info->{selected_by} = 'attempt all'; | 
| 176 | 1 |  |  |  |  | 4 | while(my ($name, $handler) = each %$handlers) | 
| 177 | 0 |  |  |  |  | 0 | {   my ($rc, $msg, $xmlout) = $handler->($name, $xmlin, $info, $req); | 
| 178 | 0 | 0 |  |  |  | 0 | defined $xmlout or next; | 
| 179 |  |  |  |  |  |  |  | 
| 180 | 0 |  |  |  |  | 0 | trace "data ready for $version $name"; | 
| 181 | 0 |  |  |  |  | 0 | return ($rc, $msg, $xmlout); | 
| 182 |  |  |  |  |  |  | } | 
| 183 |  |  |  |  |  |  | } | 
| 184 |  |  |  |  |  |  |  | 
| 185 | 1 |  | 50 |  |  | 5 | my $bodyel = $info->{body}[0] || '(none)'; | 
| 186 | 1 | 0 |  |  |  | 8 | my @other  = sort grep {$_ ne $version && keys %{$self->{$_}}} | 
|  | 0 |  |  |  |  | 0 |  | 
|  | 0 |  |  |  |  | 0 |  | 
| 187 |  |  |  |  |  |  | $self->soapVersions; | 
| 188 |  |  |  |  |  |  |  | 
| 189 | 1 | 50 |  |  |  | 4 | return (RC_SEE_OTHER, 'SOAP protocol not in use' | 
| 190 |  |  |  |  |  |  | , $server->faultTryOtherProtocol($bodyel, \@other)) | 
| 191 |  |  |  |  |  |  | if @other; | 
| 192 |  |  |  |  |  |  |  | 
| 193 |  |  |  |  |  |  | # we do not have the names of the request body elements here :( | 
| 194 | 1 |  |  |  |  | 2 | my @ports = sort keys %$handlers; | 
| 195 |  |  |  |  |  |  |  | 
| 196 | 1 |  |  |  |  | 14 | ( RC_NOT_FOUND, 'message not recognized' | 
| 197 |  |  |  |  |  |  | , $server->faultMessageNotRecognized($bodyel, $soapaction, \@ports) | 
| 198 |  |  |  |  |  |  | ); | 
| 199 |  |  |  |  |  |  | } | 
| 200 |  |  |  |  |  |  |  | 
| 201 |  |  |  |  |  |  | #------------------ | 
| 202 |  |  |  |  |  |  |  | 
| 203 |  |  |  |  |  |  | sub operationsFromWSDL($@) | 
| 204 | 0 |  |  | 0 | 1 | 0 | {   my ($self, $wsdl, %args) = @_; | 
| 205 | 0 |  | 0 |  |  | 0 | my $callbacks  = delete $args{callbacks} || {}; | 
| 206 | 0 |  |  |  |  | 0 | my %names; | 
| 207 |  |  |  |  |  |  |  | 
| 208 | 0 |  |  |  |  | 0 | my $default_cb = delete $args{default_callback}; | 
| 209 | 0 |  |  |  |  | 0 | my $wsa_input  = $self->{wsa_input}; | 
| 210 | 0 |  |  |  |  | 0 | my $wsa_output = $self->{wsa_output}; | 
| 211 |  |  |  |  |  |  |  | 
| 212 | 0 |  |  |  |  | 0 | my $ops = delete $args{operations}; | 
| 213 | 0 | 0 |  |  |  | 0 | my @ops = $ops ? @$ops : $wsdl->operations(%args); | 
| 214 | 0 | 0 |  |  |  | 0 | @ops or return;   # none selected | 
| 215 |  |  |  |  |  |  |  | 
| 216 | 0 |  |  |  |  | 0 | foreach my $op (@ops) | 
| 217 | 0 |  |  |  |  | 0 | {   my $name = $op->name; | 
| 218 |  |  |  |  |  |  | warning __x"multiple operations with name `{name}'", name => $name | 
| 219 | 0 | 0 |  |  |  | 0 | if $names{$name}++; | 
| 220 |  |  |  |  |  |  |  | 
| 221 | 0 |  |  |  |  | 0 | my $code; | 
| 222 | 0 | 0 |  |  |  | 0 | if(my $callback = $callbacks->{$name}) | 
| 223 | 0 | 0 |  |  |  | 0 | {   UNIVERSAL::isa($callback, 'CODE') | 
| 224 |  |  |  |  |  |  | or error __x"callback {name} must provide a CODE ref" | 
| 225 |  |  |  |  |  |  | , name => $name; | 
| 226 |  |  |  |  |  |  |  | 
| 227 | 0 |  |  |  |  | 0 | trace __x"add handler for operation `{name}'", name => $name; | 
| 228 | 0 |  |  |  |  | 0 | $code = $op->compileHandler(callback => $callback, %args); | 
| 229 |  |  |  |  |  |  | } | 
| 230 |  |  |  |  |  |  | else | 
| 231 | 0 |  |  |  |  | 0 | {   trace __x"add stub handler for operation `{name}'", name => $name; | 
| 232 | 0 |  | 0 | 0 |  | 0 | my $handler = $default_cb || sub { $_[0]->faultNotImplemented($name) }; | 
|  | 0 |  |  |  |  | 0 |  | 
| 233 | 0 |  |  |  |  | 0 | $code = $op->compileHandler(callback => $handler, %args); | 
| 234 |  |  |  |  |  |  | } | 
| 235 |  |  |  |  |  |  |  | 
| 236 | 0 |  |  |  |  | 0 | $self->addHandler($name, $op, $code); | 
| 237 |  |  |  |  |  |  |  | 
| 238 | 0 | 0 |  |  |  | 0 | if($op->can('wsaAction')) | 
| 239 | 0 |  |  |  |  | 0 | {   my $in  = $op->wsaAction('INPUT'); | 
| 240 | 0 | 0 |  |  |  | 0 | $wsa_input->{$name}  = $in if defined $in; | 
| 241 |  |  |  |  |  |  |  | 
| 242 | 0 |  |  |  |  | 0 | my $out = $op->wsaAction('OUTPUT'); | 
| 243 | 0 | 0 |  |  |  | 0 | $wsa_output->{$name} = $out if defined $out; | 
| 244 |  |  |  |  |  |  | } | 
| 245 | 0 |  |  |  |  | 0 | $self->addSoapAction($name, $op->soapAction); | 
| 246 |  |  |  |  |  |  | } | 
| 247 |  |  |  |  |  |  |  | 
| 248 | 0 |  |  |  |  | 0 | info __x"added {nr} operations from WSDL", nr => (scalar @ops); | 
| 249 |  |  |  |  |  |  |  | 
| 250 |  |  |  |  |  |  | warning __x"no operation for callback handler `{name}'", name=> $_ | 
| 251 | 0 |  |  |  |  | 0 | for sort grep ! $names{$_}, keys %$callbacks; | 
| 252 |  |  |  |  |  |  |  | 
| 253 | 0 |  |  |  |  | 0 | $self; | 
| 254 |  |  |  |  |  |  | } | 
| 255 |  |  |  |  |  |  |  | 
| 256 |  |  |  |  |  |  |  | 
| 257 |  |  |  |  |  |  | sub addHandler($$$) | 
| 258 | 0 |  |  | 0 | 1 | 0 | {   my ($self, $name, $soap, $code) = @_; | 
| 259 |  |  |  |  |  |  |  | 
| 260 | 0 | 0 |  |  |  | 0 | my $version = ref $soap ? $soap->version : $soap; | 
| 261 | 0 |  |  |  |  | 0 | $self->{handler}{$version}{$name} = $code; | 
| 262 |  |  |  |  |  |  | } | 
| 263 |  |  |  |  |  |  |  | 
| 264 |  |  |  |  |  |  |  | 
| 265 |  |  |  |  |  |  | sub setWsdlResponse($;$) | 
| 266 | 0 |  |  | 0 | 1 | 0 | {   my ($self, $filename, $type) = @_; | 
| 267 | 0 |  | 0 |  |  | 0 | panic "not implemented by backend {pkg}", pkg => (ref $self || $self); | 
| 268 |  |  |  |  |  |  | } | 
| 269 |  |  |  |  |  |  |  | 
| 270 |  |  |  |  |  |  | #------------------ | 
| 271 |  |  |  |  |  |  |  | 
| 272 |  |  |  |  |  |  | sub handlers($) | 
| 273 | 0 |  |  | 0 | 1 | 0 | {   my ($self, $soap) = @_; | 
| 274 | 0 | 0 |  |  |  | 0 | my $version = ref $soap ? $soap->version : $soap; | 
| 275 | 0 |  | 0 |  |  | 0 | my $table   = $self->{handler}{$version} || {}; | 
| 276 | 0 |  |  |  |  | 0 | keys %$table; | 
| 277 |  |  |  |  |  |  | } | 
| 278 |  |  |  |  |  |  |  | 
| 279 |  |  |  |  |  |  |  | 
| 280 | 1 |  |  | 1 | 1 | 2 | sub soapVersions() { sort keys %{shift->{handler}} } | 
|  | 1 |  |  |  |  | 5 |  | 
| 281 |  |  |  |  |  |  |  | 
| 282 |  |  |  |  |  |  |  | 
| 283 |  |  |  |  |  |  | sub printIndex(;$) | 
| 284 | 0 |  |  | 0 | 1 | 0 | {   my $self = shift; | 
| 285 | 0 |  | 0 |  |  | 0 | my $fh   = shift || \*STDOUT; | 
| 286 |  |  |  |  |  |  |  | 
| 287 | 0 |  |  |  |  | 0 | foreach my $version ($self->soapVersions) | 
| 288 | 0 |  |  |  |  | 0 | {   my @handlers = $self->handlers($version); | 
| 289 | 0 | 0 |  |  |  | 0 | @handlers or next; | 
| 290 |  |  |  |  |  |  |  | 
| 291 | 0 |  |  |  |  | 0 | local $" = "\n   "; | 
| 292 | 0 |  |  |  |  | 0 | $fh->print("$version:\n   @handlers\n"); | 
| 293 |  |  |  |  |  |  | } | 
| 294 |  |  |  |  |  |  | } | 
| 295 |  |  |  |  |  |  |  | 
| 296 |  |  |  |  |  |  |  | 
| 297 |  |  |  |  |  |  | sub faultInvalidXML($) | 
| 298 | 1 |  |  | 1 | 1 | 87 | {   my ($self, $error) = @_; | 
| 299 | 1 |  |  |  |  | 4 | ( RC_UNPROCESSABLE_ENTITY, 'XML syntax error' | 
| 300 |  |  |  |  |  |  | , __x("The XML cannot be parsed: {error}", error => $error)); | 
| 301 |  |  |  |  |  |  | } | 
| 302 |  |  |  |  |  |  |  | 
| 303 |  |  |  |  |  |  |  | 
| 304 |  |  |  |  |  |  | sub faultNotSoapMessage($) | 
| 305 | 1 |  |  | 1 | 1 | 94 | {   my ($self, $type) = @_; | 
| 306 | 1 |  |  |  |  | 4 | ( RC_FORBIDDEN, 'message not SOAP' | 
| 307 |  |  |  |  |  |  | , __x( "The message was XML, but not SOAP; not an Envelope but `{type}'" | 
| 308 |  |  |  |  |  |  | , type => $type)); | 
| 309 |  |  |  |  |  |  | } | 
| 310 |  |  |  |  |  |  |  | 
| 311 |  |  |  |  |  |  |  | 
| 312 |  |  |  |  |  |  | sub faultUnsupportedSoapVersion($) | 
| 313 | 1 |  |  | 1 | 1 | 15 | {   my ($self, $envns) = @_; | 
| 314 | 1 |  |  |  |  | 4 | ( RC_NOT_IMPLEMENTED, 'SOAP version not supported' | 
| 315 |  |  |  |  |  |  | , __x("The soap version `{envns}' is not supported", envns => $envns)); | 
| 316 |  |  |  |  |  |  | } | 
| 317 |  |  |  |  |  |  |  | 
| 318 |  |  |  |  |  |  | #------------------ | 
| 319 |  |  |  |  |  |  |  | 
| 320 |  |  |  |  |  |  | 1; |