SOAP-Clean
view release on metacpan or search on metacpan
lib/SOAP/Clean/CGI.pm view on Meta::CPAN
my $request_method = $ENV{REQUEST_METHOD} || 0;
my $soapaction = $ENV{HTTP_SOAPACTION} || 0;
my $content_type = $ENV{CONTENT_TYPE} || 0;
my $query_string = $ENV{QUERY_STRING} || 0;
my $result;
# Determine how the request should be handled.
if ( $soapaction || $content_type =~ 'application/soap\+xml' ) {
# if the SOAPAction: header appears or the Content-type is
# application/soap+xml, then it process it as a soap request, not
# matter what the request method was.
$result = $self->handle_soap($content_type =~ 'text/xml');
} else {
# use the request method to decide how to handle it.
if ( $request_method eq "POST" ) {
# POST method
$result = $self->handle_post();
} elsif ( $request_method eq "GET" ) {
# GET method. Use the query string to decide how to handle.
if ( lc($query_string) eq "wsdl" ) {
$result = $self->handle_wsdl();
} else {
$result = $self->handle_get();
}
} else {
# No request method? The script must be being called interactively
# for debugging purposes. Handle it as SOAP.
$result = $self->handle_soap(0);
}
}
return $result;
}
########################################################################
sub handle_soap {
my ($self,$content_type_is_text_xml) = @_;
# Set the handler for die calls.
$SIG{__DIE__} = \&soap_die_handler;
my $server_urn = $self->{urn};
defined($server_urn) || assert(0,"No server URN");
my $server_name = $self->{name};
defined($server_name) || assert(0,"No server name");
# Read the request from STDIN
my $request = xml_from_fh(\*STDIN);
defined($request) || assert(0,"Can't parse request?!?");
# Take a SOAP request. Parse it and extract the method name and
# arguments. Call the appropriate function for the method. Package the
# results into a SOAP response and return it.
# Here we verify the digital signature if the server wants to check
# digital signatures
if (defined($self->{dsig})) { verify_envelope($self,$request); }
#### DECRYPTION HERE #########
if (defined($self->{enc})) { decrypt_body($self,$request); }
my $envelope = xml_get_child($request,$SOAP_ENV,'Envelope');
assert(defined($envelope));
my $body = xml_get_child($envelope,$SOAP_ENV,'Body');
assert(defined($body));
# The body contains a single element which is the message.
my @children = xml_get_children($body);
$#children == 0 ||
assert(0,"Error! file \"".__FILE__."\", line ".__LINE__);
my $message = $children[0];
# The method name is the node name of the message.
my ($method_urn,$method_name) = xml_get_name($message);
# The method name must appear in the right namespace.
($method_urn eq $server_urn) ||
assert(0,"Method name not in the server namespace");
# The method arguments are the children of the message.
my %request_args = ();
foreach my $arg ( xml_get_children($message) ) {
my ($arg_ns,$arg_name) = xml_get_name($arg);
# The arg name must appear in the right namespace.
($arg_ns eq $server_urn) ||
assert(0,"Arg name not in the server namespace");
$request_args{$arg_name} = $arg;
}
# %response_args = call $method_name with %request_args;
my %response_args = $self->_dispatch_method($method_name, %request_args);
# Put the response arguments together in a list.
my @response_args_list = ();
foreach my $k (keys %response_args) {
push @response_args_list, $response_args{$k};
}
# Put together $method_name."Response" with %responses;
my $response =
document(element("SOAP-ENV:Envelope",
namespace("SOAP-ENV",$SOAP_ENV),
namespace("SOAP-ENC",$SOAP_ENC),
namespace("xsi",$xsi),
namespace("xsd",$xsd),
namespace("server",$server_urn),
element("SOAP-ENV:Header"),
element("SOAP-ENV:Body",
element("server:".$method_name."Result",
@response_args_list))));
# fixme: encrypt if need be
# Use whatever content type that this client used.
my $type;
if ( $content_type_is_text_xml ) {
# .NET requires this,...
$type = 'text/xml';
} else {
# but SOAP 1.2 requires this,
$type = 'application/soap+xml';
}
$type = 'text/xml';
print header(-type=>$type,
-charset=>'utf-8');
xml_to_fh($response,\*STDOUT);
return 0;
}
########################################################################
sub handle_post {
my ($self) = @_;
# Set the handler for die calls.
$SIG{__DIE__} = \&html_die_handler;
my $server_urn = $self->{urn};
defined($server_urn) || assert(0,"No server URN");
my $server_name = $self->{name};
defined($server_name) || assert(0,"No server name");
my $method_name = param("_method_");
print header,
start_html($server_name.": Results"),
h1($server_name.": Results"), p;
if (!param()) {
print "No params? How did you manage that?", hr;
print end_html;
return 1;
}
# Throw an error if either dsig or enc was expected.
if (defined($self->{dsig})) {
assert(0,"No digitial signatures for POST's");
}
if (defined($self->{enc})) {
assert(0,"No encryption for POST's");
}
# Determine the formal parameters based on the method name
my @formal_params;
if ( $method_name eq "Call" || $method_name eq "Spawn" ) {
my %h = ();
foreach my $p ( @{$self->{params}} ) {
$h{$$p{name}} = $p;
}
foreach my $n ( @{$self->{in_order}} ) {
my $p = $h{$n};
assert(defined($p));
if ( $$p{direc} eq "out" ) {
# nothing
} else {
push @formal_params, $p;
}
}
} elsif ( $method_name eq "Running" || $method_name eq "Results" ) {
@formal_params = ({ name=> 'uid',
direc=> 'in',
mech=> 'val',
type=> 'string',
});
} else {
die;
}
# Parse the actual parameters.
my %request_args = ();
foreach my $p ( @formal_params ) {
my $name = $$p{name};
assert(defined($p),"No value for $name");
my $mech = $$p{mech};
my $type = $$p{type};
my $value;
if ( $mech eq 'val' ) {
$value = param($name);
} elsif ( $mech eq 'file' ) {
my $fh = param($name); #upload($name);
assert($fh,"File $name is missing");
$value = '';
# deleteme
#print pre("+".$fh."\n"),p;
while (<$fh>) {
# deleteme
#print pre("*\n"),p;
$value .= $_;
}
} else {
assert(0);
}
if ( $value ne '') {
$request_args{$name} = $value;
}
( run in 1.720 second using v1.01-cache-2.11-cpan-71847e10f99 )