0% found this document useful (0 votes)
576 views

Web Service & SOAP

Nusoap.php is free software; you can redistribute it and / or modify it under the terms of the GNU Lesser General Public License as published by the free software foundation. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS for A PARTICULAR PURPOSE.

Uploaded by

NEnk NeNyz
Copyright
© Attribution Non-Commercial (BY-NC)
Available Formats
Download as TXT, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
576 views

Web Service & SOAP

Nusoap.php is free software; you can redistribute it and / or modify it under the terms of the GNU Lesser General Public License as published by the free software foundation. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS for A PARTICULAR PURPOSE.

Uploaded by

NEnk NeNyz
Copyright
© Attribution Non-Commercial (BY-NC)
Available Formats
Download as TXT, PDF, TXT or read online on Scribd
You are on page 1/ 148

web serviceces_produk.

php
<?php
//menampilkan daftar produk
function getProductList(){
mysql_connect("localhost","root","");
mysql_select_db("gadget_db");
$result=mysql_query("SELECT produk_id, merk, tipe, harga
from produk");
$index=0;
while($data=mysql_fetch_array($result)){
$books[$index]=array(
"produk_id"=>$data['produk_id'],
"merk"=>$data['merk'],
"tipe"=>$data['tipe'],
"harga"=>$data['harga']
);
$index++;
}
mysql_close();
return $books;
}
require("nusoap.php");
$server=new soap_server();
$server->configureWSDL("Gadget","urn:BooksService");
$server->wsdl->addComplexType(
"book",
"complexType",
"struct",
"all",
"",
//elemen2 yang akan dikirim ke soap client
array(
"produk_id"=>array("name"=>"produk_id","type"=>"xsd:string"),
"merk"=>array("name"=>"merk","type"=>"xsd:string"),
"tipe"=>array("name"=>"tipe","type"=>"xsd:string"),
"harga"=>array("name"=>"harga","type"=>"xsd:string")
)
);
$server->wsdl->addComplexType(
"idArray",
"complexType",
"array",
"",
"SOAP-ENC:Array",
array(),
array(
array("ref"=>"SOAP-ENC:arrayType","wsdl:arrayType"=>"xsd:string[
]")
),
"xsd:string"
);
$server->wsdl->addComplexType(
"booksArray",
"complexType",
"array",
"",
"SOAP-ENC:Array",
array(),
array(
array("ref"=>"SOAP-ENC:arrayType","wsdl:arrayType"=>"tns:book[]"
)
),
"tns:book"
);
//mendafatarkan function2 yg telah dibuat
$server->register("getProductByCategory",array("idCat"=>"xsd:string"),array("ret
urn"=>"tns:booksArray"),"urn:BooksService","urn:BooksService#getProductByCategor
y");
$server->register("getProductDetail",array("productId"=>"xsd:string"),array("ret
urn"=>"tns:book"),"urn:BooksService","urn:BooksService#getProductDetail");
$server->register("getProductList",array(),array("return"=>"tns:booksArray"),"ur
n:BooksService","urn:BooksService#getProductList");
$HTTP_RAW_POST_DATA=isset($HTTP_RAW_POST_DATA)? $HTTP_RAW_POST_DATA : "";
$server->service($HTTP_RAW_POST_DATA);
?>

nusoap.php
<?php
/*
$Id: nusoap.php,v 1.94 2005/08/04 01:27:42 snichol Exp $
NuSOAP - Web Services Toolkit for PHP
Copyright (c) 2002 NuSphere Corporation
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
If you have any questions or comments, please email:
Dietrich Ayala
[email protected]
http://dietrich.ganx4.com/nusoap
NuSphere Corporation
http://www.nusphere.com
*/
/* load classes
// necessary classes
require_once('class.soapclient.php');
require_once('class.soap_val.php');
require_once('class.soap_parser.php');
require_once('class.soap_fault.php');
// transport classes
require_once('class.soap_transport_http.php');
// optional add-on classes
require_once('class.xmlschema.php');
require_once('class.wsdl.php');
// server class
require_once('class.soap_server.php');*/
// class variable emulation
// cf. http://www.webkreator.com/php/techniques/php-static-class-variables.html
$GLOBALS['_transient']['static']['nusoap_base']->globalDebugLevel = 9;
/**
*
* nusoap_base
*
* @author Dietrich Ayala <[email protected]>
* @version $Id: nusoap.php,v 1.94 2005/08/04 01:27:42 snichol Exp $
* @access public
*/
class nusoap_base {
/**
* Identification for HTTP headers.
*
* @var string
* @access private
*/
var $title = 'NuSOAP';
/**
* Version for HTTP headers.
*
* @var string
* @access private
*/
var $version = '0.7.2';
/**
* CVS revision for HTTP headers.
*
* @var string
* @access private
*/
var $revision = '$Revision: 1.94 $';
/**
* Current error string (manipulated by getError/setError)
*
* @var string
* @access private
*/
var $error_str = '';
/**
* Current debug string (manipulated by debug/appendDebug/clearDebug/getDebu
g/getDebugAsXMLComment)
*
* @var string
* @access private
*/
var $debug_str = '';
/**
* toggles automatic encoding of special characters as entities
* (should always be true, I think)
*
* @var boolean
* @access private
*/
var $charencoding = true;
/**
* the debug level for this instance
*
* @var integer
* @access private
*/
var $debugLevel;
/**
* set schema version
*
* @var string
* @access public
*/
var $XMLSchemaVersion = 'http://www.w3.org/2001/XMLSchema';
/**
* charset encoding for outgoing messages
*
* @var string
* @access public
*/
var $soap_defencoding = 'ISO-8859-1';
//var $soap_defencoding = 'UTF-8';
/**
* namespaces in an array of prefix => uri
*
* this is "seeded" by a set of constants, but it may be altered by code
*
* @var array
* @access public
*/
var $namespaces = array(
'SOAP-ENV' => 'http://schemas.xmlsoap.org/soap/envelope/',
'xsd' => 'http://www.w3.org/2001/XMLSchema',
'xsi' => 'http://www.w3.org/2001/XMLSchema-instance',
'SOAP-ENC' => 'http://schemas.xmlsoap.org/soap/encoding/'
);
/**
* namespaces used in the current context, e.g. during serialization
*
* @var array
* @access private
*/
var $usedNamespaces = array();
/**
* XML Schema types in an array of uri => (array of xml type => php type)
* is this legacy yet?
* no, this is used by the xmlschema class to verify type => namespace ma
ppings.
* @var array
* @access public
*/
var $typemap = array(
'http://www.w3.org/2001/XMLSchema' => array(
'string'=>'string','boolean'=>'boolean','float'=>'double','doubl
e'=>'double','decimal'=>'double',
'duration'=>'','dateTime'=>'string','time'=>'string','date'=>'st
ring','gYearMonth'=>'',
'gYear'=>'','gMonthDay'=>'','gDay'=>'','gMonth'=>'','hexBinary'=
>'string','base64Binary'=>'string',
// abstract "any" types
'anyType'=>'string','anySimpleType'=>'string',
// derived datatypes
'normalizedString'=>'string','token'=>'string','language'=>'','N
MTOKEN'=>'','NMTOKENS'=>'','Name'=>'','NCName'=>'','ID'=>'',
'IDREF'=>'','IDREFS'=>'','ENTITY'=>'','ENTITIES'=>'','integer'=>
'integer','nonPositiveInteger'=>'integer',
'negativeInteger'=>'integer','long'=>'integer','int'=>'integer',
'short'=>'integer','byte'=>'integer','nonNegativeInteger'=>'integer',
'unsignedLong'=>'','unsignedInt'=>'','unsignedShort'=>'','unsign
edByte'=>'','positiveInteger'=>''),
'http://www.w3.org/2000/10/XMLSchema' => array(
'i4'=>'','int'=>'integer','boolean'=>'boolean','string'=>'string
','double'=>'double',
'float'=>'double','dateTime'=>'string',
'timeInstant'=>'string','base64Binary'=>'string','base64'=>'stri
ng','ur-type'=>'array'),
'http://www.w3.org/1999/XMLSchema' => array(
'i4'=>'','int'=>'integer','boolean'=>'boolean','string'=>'string
','double'=>'double',
'float'=>'double','dateTime'=>'string',
'timeInstant'=>'string','base64Binary'=>'string','base64'=>'stri
ng','ur-type'=>'array'),
'http://soapinterop.org/xsd' => array('SOAPStruct'=>'struct'),
'http://schemas.xmlsoap.org/soap/encoding/' => array('base64'=>'string',
'array'=>'array','Array'=>'array'),
'http://xml.apache.org/xml-soap' => array('Map')
);
/**
* XML entities to convert
*
* @var array
* @access public
* @deprecated
* @see expandEntities
*/
var $xmlEntities = array('quot' => '"','amp' => '&',
'lt' => '<','gt' => '>','apos' => "'");
/**
* constructor
*
* @access public
*/
function nusoap_base() {
$this->debugLevel = $GLOBALS['_transient']['static']['nusoap_bas
e']->globalDebugLevel;
}
/**
* gets the global debug level, which applies to future instances
*
* @return integer Debug level 0-9, where 0 turns off
* @access public
*/
function getGlobalDebugLevel() {
return $GLOBALS['_transient']['static']['nusoap_base']->globalDe
bugLevel;
}
/**
* sets the global debug level, which applies to future instances
*
* @param int $level Debug level 0-9, where 0 turns off
* @access public
*/
function setGlobalDebugLevel($level) {
$GLOBALS['_transient']['static']['nusoap_base']->globalDebugLeve
l = $level;
}
/**
* gets the debug level for this instance
*
* @return int Debug level 0-9, where 0 turns off
* @access public
*/
function getDebugLevel() {
return $this->debugLevel;
}
/**
* sets the debug level for this instance
*
* @param int $level Debug level 0-9, where 0 turns off
* @access public
*/
function setDebugLevel($level) {
$this->debugLevel = $level;
}
/**
* adds debug data to the instance debug string with formatting
*
* @param string $string debug data
* @access private
*/
function debug($string){
if ($this->debugLevel > 0) {
$this->appendDebug($this->getmicrotime().' '.get_class($
this).": $string\n");
}
}
/**
* adds debug data to the instance debug string without formatting
*
* @param string $string debug data
* @access public
*/
function appendDebug($string){
if ($this->debugLevel > 0) {
// it would be nice to use a memory stream here to use
// memory more efficiently
$this->debug_str .= $string;
}
}
/**
* clears the current debug data for this instance
*
* @access public
*/
function clearDebug() {
// it would be nice to use a memory stream here to use
// memory more efficiently
$this->debug_str = '';
}
/**
* gets the current debug data for this instance
*
* @return debug data
* @access public
*/
function &getDebug() {
// it would be nice to use a memory stream here to use
// memory more efficiently
return $this->debug_str;
}
/**
* gets the current debug data for this instance as an XML comment
* this may change the contents of the debug data
*
* @return debug data as an XML comment
* @access public
*/
function &getDebugAsXMLComment() {
// it would be nice to use a memory stream here to use
// memory more efficiently
while (strpos($this->debug_str, '--')) {
$this->debug_str = str_replace('--', '- -', $this->debug
_str);
}
return "<!--\n" . $this->debug_str . "\n-->";
}
/**
* expands entities, e.g. changes '<' to '&lt;'.
*
* @param string $val The string in which to expand entities.
* @access private
*/
function expandEntities($val) {
if ($this->charencoding) {
$val = str_replace('&', '&amp;', $val);
$val = str_replace("'", '&apos;', $val);
$val = str_replace('"', '&quot;', $val);
$val = str_replace('<', '&lt;', $val);
$val = str_replace('>', '&gt;', $val);
}
return $val;
}
/**
* returns error string if present
*
* @return mixed error string or false
* @access public
*/
function getError(){
if($this->error_str != ''){
return $this->error_str;
}
return false;
}
/**
* sets error string
*
* @return boolean $string error string
* @access private
*/
function setError($str){
$this->error_str = $str;
}
/**
* detect if array is a simple array or a struct (associative array)
*
* @param mixed $val The PHP array
* @return string (arraySimple|arrayStruct)
* @access private
*/
function isArraySimpleOrStruct($val) {
$keyList = array_keys($val);
foreach ($keyList as $keyListValue) {
if (!is_int($keyListValue)) {
return 'arrayStruct';
}
}
return 'arraySimple';
}
/**
* serializes PHP values in accordance w/ section 5. Type information is
* not serialized if $use == 'literal'.
*
* @param mixed $val The value to serialize
* @param string $name The name (local part) of the XML element
* @param string $type The XML schema type (local part) for the
element
* @param string $name_ns The namespace for the name of th
e XML element
* @param string $type_ns The namespace for the type of th
e element
* @param array $attributes The attributes to serialize as n
ame=>value pairs
* @param string $use The WSDL "use" (encoded|literal)
* @return string The serialized element, possibly with child elem
ents
* @access public
*/
function serialize_val($val,$name=false,$type=false,$name_ns=false,$type
_ns=false,$attributes=false,$use='encoded'){
$this->debug("in serialize_val: name=$name, type=$type, name_ns=
$name_ns, type_ns=$type_ns, use=$use");
$this->appendDebug('value=' . $this->varDump($val));
$this->appendDebug('attributes=' . $this->varDump($attributes));
if(is_object($val) && get_class($val) == 'soapval'){
return $val->serialize($use);
}
// force valid name if necessary
if (is_numeric($name)) {
$name = '__numeric_' . $name;
} elseif (! $name) {
$name = 'noname';
}
// if name has ns, add ns prefix to name
$xmlns = '';
if($name_ns){
$prefix = 'nu'.rand(1000,9999);
$name = $prefix.':'.$name;
$xmlns .= " xmlns:$prefix=\"$name_ns\"";
}
// if type is prefixed, create type prefix
if($type_ns != '' && $type_ns == $this->namespaces['xsd']){
// need to fix this. shouldn't default to xsd if no ns s
pecified
// w/o checking against typemap
$type_prefix = 'xsd';
} elseif($type_ns){
$type_prefix = 'ns'.rand(1000,9999);
$xmlns .= " xmlns:$type_prefix=\"$type_ns\"";
}
// serialize attributes if present
$atts = '';
if($attributes){
foreach($attributes as $k => $v){
$atts .= " $k=\"".$this->expandEntities($v).'"';
}
}
// serialize null value
if (is_null($val)) {
if ($use == 'literal') {
// TODO: depends on minOccurs
return "<$name$xmlns $atts/>";
} else {
if (isset($type) && isset($type_prefix)) {
$type_str = " xsi:type=\"$type_prefix:$t
ype\"";
} else {
$type_str = '';
}
return "<$name$xmlns$type_str $atts xsi:nil=\"true\"/>";
}
}
// serialize if an xsd built-in primitive type
if($type != '' && isset($this->typemap[$this->XMLSchemaVersion][$type]))
{
if (is_bool($val)) {
if ($type == 'boolean') {
$val = $val ? 'true' : 'false';
} elseif (! $val) {
$val = 0;
}
} else if (is_string($val)) {
$val = $this->expandEntities($val);
}
if ($use == 'literal') {
return "<$name$xmlns $atts>$val</$name>";
} else {
return "<$name$xmlns $atts xsi:type=\"xsd:$type\">$val</
$name>";
}
}
// detect type and serialize
$xml = '';
switch(true) {
case (is_bool($val) || $type == 'boolean'):
if ($type == 'boolean') {
$val = $val ? 'true' : 'false';
} elseif (! $val) {
$val = 0;
}
if ($use == 'literal') {
$xml .= "<$name$xmlns $atts>$val</$name>
";
} else {
$xml .= "<$name$xmlns xsi:type=\"xsd:boo
lean\"$atts>$val</$name>";
}
break;
case (is_int($val) || is_long($val) || $type == 'int'):
if ($use == 'literal') {
$xml .= "<$name$xmlns $atts>$val</$name>
";
} else {
$xml .= "<$name$xmlns xsi:type=\"xsd:int
\"$atts>$val</$name>";
}
break;
case (is_float($val)|| is_double($val) || $type == 'floa
t'):
if ($use == 'literal') {
$xml .= "<$name$xmlns $atts>$val</$name>
";
} else {
$xml .= "<$name$xmlns xsi:type=\"xsd:flo
at\"$atts>$val</$name>";
}
break;
case (is_string($val) || $type == 'string'):
$val = $this->expandEntities($val);
if ($use == 'literal') {
$xml .= "<$name$xmlns $atts>$val</$name>
";
} else {
$xml .= "<$name$xmlns xsi:type=\"xsd:str
ing\"$atts>$val</$name>";
}
break;
case is_object($val):
if (! $name) {
$name = get_class($val);
$this->debug("In serialize_val, used cla
ss name $name as element name");
} else {
$this->debug("In serialize_val, do not o
verride name $name for element name for class " . get_class($val));
}
foreach(get_object_vars($val) as $k => $v){
$pXml = isset($pXml) ? $pXml.$this->seri
alize_val($v,$k,false,false,false,false,$use) : $this->serialize_val($v,$k,false
,false,false,false,$use);
}
$xml .= '<'.$name.'>'.$pXml.'</'.$name.'>';
break;
break;
case (is_array($val) || $type):
// detect if struct or array
$valueType = $this->isArraySimpleOrStruct($val);
if($valueType=='arraySimple' || ereg('^ArrayOf',$type)){
$i = 0;
if(is_array($val) && count($val)> 0){
foreach($val as $v){
if(is_object($v) && get_class($v) == 'soapval')
{
$tt_ns = $v->typ
e_ns;
$tt = $v->type;
} elseif (is_array($v))
{
$tt = $this->isA
rraySimpleOrStruct($v);
} else {
$tt = gettype($v
);
}
$array_types[$tt] = 1;
// TODO: for literal, th
e name should be $name
$xml .= $this->serialize
_val($v,'item',false,false,false,false,$use);
++$i;
}
if(count($array_types) > 1){
$array_typename = 'xsd:a
nyType';
} elseif(isset($tt) && isset($th
is->typemap[$this->XMLSchemaVersion][$tt])) {
if ($tt == 'integer') {
$tt = 'int';
}
$array_typename = 'xsd:'
.$tt;
} elseif(isset($tt) && $tt == 'a
rraySimple'){
$array_typename = 'SOAP-
ENC:Array';
} elseif(isset($tt) && $tt == 'a
rrayStruct'){
$array_typename = 'unnam
ed_struct_use_soapval';
} else {
// if type is prefixed,
create type prefix
if ($tt_ns != '' && $tt_
ns == $this->namespaces['xsd']){
$array_typename
= 'xsd:' . $tt;
} elseif ($tt_ns) {
$tt_prefix = 'ns
' . rand(1000, 9999);
$array_typename
= "$tt_prefix:$tt";
$xmlns .= " xmln
s:$tt_prefix=\"$tt_ns\"";
} else {
$array_typename
= $tt;
}
}
$array_type = $i;
if ($use == 'literal') {
$type_str = '';
} else if (isset($type) && isset
($type_prefix)) {
$type_str = " xsi:type=\
"$type_prefix:$type\"";
} else {
$type_str = " xsi:type=\
"SOAP-ENC:Array\" SOAP-ENC:arrayType=\"".$array_typename."[$array_type]\"";
}
// empty array
} else {
if ($use == 'literal') {
$type_str = '';
} else if (isset($type) && isset
($type_prefix)) {
$type_str = " xsi:type=\
"$type_prefix:$type\"";
} else {
$type_str = " xsi:type=\
"SOAP-ENC:Array\" SOAP-ENC:arrayType=\"xsd:anyType[0]\"";
}
}
// TODO: for array in literal, there is
no wrapper here
$xml = "<$name$xmlns$type_str$atts>".$xm
l."</$name>";
} else {
// got a struct
if(isset($type) && isset($type_prefix)){
$type_str = " xsi:type=\"$type_p
refix:$type\"";
} else {
$type_str = '';
}
if ($use == 'literal') {
$xml .= "<$name$xmlns $atts>";
} else {
$xml .= "<$name$xmlns$type_str$a
tts>";
}
foreach($val as $k => $v){
// Apache Map
if ($type == 'Map' && $type_ns =
= 'http://xml.apache.org/xml-soap') {
$xml .= '<item>';
$xml .= $this->serialize
_val($k,'key',false,false,false,false,$use);
$xml .= $this->serialize
_val($v,'value',false,false,false,false,$use);
$xml .= '</item>';
} else {
$xml .= $this->serialize
_val($v,$k,false,false,false,false,$use);
}
}
$xml .= "</$name>";
}
break;
default:
$xml .= 'not detected, got '.gettype($val).' for
'.$val;
break;
}
return $xml;
}
/**
* serializes a message
*
* @param string $body the XML of the SOAP body
* @param mixed $headers optional string of XML with SOAP header content, or
array of soapval objects for SOAP headers
* @param array $namespaces optional the namespaces used in generating the bo
dy and headers
* @param string $style optional (rpc|document)
* @param string $use optional (encoded|literal)
* @param string $encodingStyle optional (usually 'http://schemas.xmlsoap.org
/soap/encoding/' for encoded)
* @return string the message
* @access public
*/
function serializeEnvelope($body,$headers=false,$namespaces=array(),$style='
rpc',$use='encoded',$encodingStyle='http://schemas.xmlsoap.org/soap/encoding/'){
// TODO: add an option to automatically run utf8_encode on $body and $header
s
// if $this->soap_defencoding is UTF-8. Not doing this automatically allows
// one to send arbitrary UTF-8 characters, not just characters that map to I
SO-8859-1
$this->debug("In serializeEnvelope length=" . strlen($body) . " body (ma
x 1000 characters)=" . substr($body, 0, 1000) . " style=$style use=$use encoding
Style=$encodingStyle");
$this->debug("headers:");
$this->appendDebug($this->varDump($headers));
$this->debug("namespaces:");
$this->appendDebug($this->varDump($namespaces));
// serialize namespaces
$ns_string = '';
foreach(array_merge($this->namespaces,$namespaces) as $k => $v){
$ns_string .= " xmlns:$k=\"$v\"";
}
if($encodingStyle) {
$ns_string = " SOAP-ENV:encodingStyle=\"$encodingStyle\"$ns_stri
ng";
}
// serialize headers
if($headers){
if (is_array($headers)) {
$xml = '';
foreach ($headers as $header) {
$xml .= $this->serialize_val($header, false, fal
se, false, false, false, $use);
}
$headers = $xml;
$this->debug("In serializeEnvelope, serialzied array of
headers to $headers");
}
$headers = "<SOAP-ENV:Header>".$headers."</SOAP-ENV:Header>";
}
// serialize envelope
return
'<?xml version="1.0" encoding="'.$this->soap_defencoding .'"?'.">".
'<SOAP-ENV:Envelope'.$ns_string.">".
$headers.
"<SOAP-ENV:Body>".
$body.
"</SOAP-ENV:Body>".
"</SOAP-ENV:Envelope>";
}
/**
* formats a string to be inserted into an HTML stream
*
* @param string $str The string to format
* @return string The formatted string
* @access public
* @deprecated
*/
function formatDump($str){
$str = htmlspecialchars($str);
return nl2br($str);
}
/**
* contracts (changes namespace to prefix) a qualified name
*
* @param string $qname qname
* @return string contracted qname
* @access private
*/
function contractQname($qname){
// get element namespace
//$this->xdebug("Contract $qname");
if (strrpos($qname, ':')) {
// get unqualified name
$name = substr($qname, strrpos($qname, ':') + 1);
// get ns
$ns = substr($qname, 0, strrpos($qname, ':'));
$p = $this->getPrefixFromNamespace($ns);
if ($p) {
return $p . ':' . $name;
}
return $qname;
} else {
return $qname;
}
}
/**
* expands (changes prefix to namespace) a qualified name
*
* @param string $string qname
* @return string expanded qname
* @access private
*/
function expandQname($qname){
// get element prefix
if(strpos($qname,':') && !ereg('^http://',$qname)){
// get unqualified name
$name = substr(strstr($qname,':'),1);
// get ns prefix
$prefix = substr($qname,0,strpos($qname,':'));
if(isset($this->namespaces[$prefix])){
return $this->namespaces[$prefix].':'.$name;
} else {
return $qname;
}
} else {
return $qname;
}
}
/**
* returns the local part of a prefixed string
* returns the original string, if not prefixed
*
* @param string $str The prefixed string
* @return string The local part
* @access public
*/
function getLocalPart($str){
if($sstr = strrchr($str,':')){
// get unqualified name
return substr( $sstr, 1 );
} else {
return $str;
}
}
/**
* returns the prefix part of a prefixed string
* returns false, if not prefixed
*
* @param string $str The prefixed string
* @return mixed The prefix or false if there is no prefix
* @access public
*/
function getPrefix($str){
if($pos = strrpos($str,':')){
// get prefix
return substr($str,0,$pos);
}
return false;
}
/**
* pass it a prefix, it returns a namespace
*
* @param string $prefix The prefix
* @return mixed The namespace, false if no namespace has the specified prefi
x
* @access public
*/
function getNamespaceFromPrefix($prefix){
if (isset($this->namespaces[$prefix])) {
return $this->namespaces[$prefix];
}
//$this->setError("No namespace registered for prefix '$prefix'"
);
return false;
}
/**
* returns the prefix for a given namespace (or prefix)
* or false if no prefixes registered for the given namespace
*
* @param string $ns The namespace
* @return mixed The prefix, false if the namespace has no prefixes
* @access public
*/
function getPrefixFromNamespace($ns) {
foreach ($this->namespaces as $p => $n) {
if ($ns == $n || $ns == $p) {
$this->usedNamespaces[$p] = $n;
return $p;
}
}
return false;
}
/**
* returns the time in ODBC canonical form with microseconds
*
* @return string The time in ODBC canonical form with microseconds
* @access public
*/
function getmicrotime() {
if (function_exists('gettimeofday')) {
$tod = gettimeofday();
$sec = $tod['sec'];
$usec = $tod['usec'];
} else {
$sec = time();
$usec = 0;
}
return strftime('%Y-%m-%d %H:%M:%S', $sec) . '.' . sprintf('%06d
', $usec);
}
/**
* Returns a string with the output of var_dump
*
* @param mixed $data The variable to var_dump
* @return string The output of var_dump
* @access public
*/
function varDump($data) {
ob_start();
var_dump($data);
$ret_val = ob_get_contents();
ob_end_clean();
return $ret_val;
}
}
// XML Schema Datatype Helper Functions
//xsd:dateTime helpers
/**
* convert unix timestamp to ISO 8601 compliant date string
*
* @param string $timestamp Unix time stamp
* @access public
*/
function timestamp_to_iso8601($timestamp,$utc=true){
$datestr = date('Y-m-d\TH:i:sO',$timestamp);
if($utc){
$eregStr =
'([0-9]{4})-'. // centuries & years CCYY-
'([0-9]{2})-'. // months MM-
'([0-9]{2})'. // days DD
'T'. // separator T
'([0-9]{2}):'. // hours hh:
'([0-9]{2}):'. // minutes mm:
'([0-9]{2})(\.[0-9]*)?'. // seconds ss.ss...
'(Z|[+\-][0-9]{2}:?[0-9]{2})?'; // Z to indicate UTC, -/+HH:MM:S
S.SS... for local tz's
if(ereg($eregStr,$datestr,$regs)){
return sprintf('%04d-%02d-%02dT%02d:%02d:%02dZ',$regs[1]
,$regs[2],$regs[3],$regs[4],$regs[5],$regs[6]);
}
return false;
} else {
return $datestr;
}
}
/**
* convert ISO 8601 compliant date string to unix timestamp
*
* @param string $datestr ISO 8601 compliant date string
* @access public
*/
function iso8601_to_timestamp($datestr){
$eregStr =
'([0-9]{4})-'. // centuries & years CCYY-
'([0-9]{2})-'. // months MM-
'([0-9]{2})'. // days DD
'T'. // separator T
'([0-9]{2}):'. // hours hh:
'([0-9]{2}):'. // minutes mm:
'([0-9]{2})(\.[0-9]+)?'. // seconds ss.ss...
'(Z|[+\-][0-9]{2}:?[0-9]{2})?'; // Z to indicate UTC, -/+HH:MM:SS.SS...
for local tz's
if(ereg($eregStr,$datestr,$regs)){
// not utc
if($regs[8] != 'Z'){
$op = substr($regs[8],0,1);
$h = substr($regs[8],1,2);
$m = substr($regs[8],strlen($regs[8])-2,2);
if($op == '-'){
$regs[4] = $regs[4] + $h;
$regs[5] = $regs[5] + $m;
} elseif($op == '+'){
$regs[4] = $regs[4] - $h;
$regs[5] = $regs[5] - $m;
}
}
return strtotime("$regs[1]-$regs[2]-$regs[3] $regs[4]:$regs[5]:$
regs[6]Z");
} else {
return false;
}
}
/**
* sleeps some number of microseconds
*
* @param string $usec the number of microseconds to sleep
* @access public
* @deprecated
*/
function usleepWindows($usec)
{
$start = gettimeofday();
do
{
$stop = gettimeofday();
$timePassed = 1000000 * ($stop['sec'] - $start['sec'])
+ $stop['usec'] - $start['usec'];
}
while ($timePassed < $usec);
}
?><?php

/**
* Contains information for a SOAP fault.
* Mainly used for returning faults from deployed functions
* in a server instance.
* @author Dietrich Ayala <[email protected]>
* @version $Id: nusoap.php,v 1.94 2005/08/04 01:27:42 snichol Exp $
* @access public
*/
class soap_fault extends nusoap_base {
/**
* The fault code (client|server)
* @var string
* @access private
*/
var $faultcode;
/**
* The fault actor
* @var string
* @access private
*/
var $faultactor;
/**
* The fault string, a description of the fault
* @var string
* @access private
*/
var $faultstring;
/**
* The fault detail, typically a string or array of string
* @var mixed
* @access private
*/
var $faultdetail;
/**
* constructor
*
* @param string $faultcode (client | server)
* @param string $faultactor only used when msg routed between multiple actor
s
* @param string $faultstring human readable error message
* @param mixed $faultdetail detail, typically a string or array of string
*/
function soap_fault($faultcode,$faultactor='',$faultstring='',$faultdeta
il=''){
parent::nusoap_base();
$this->faultcode = $faultcode;
$this->faultactor = $faultactor;
$this->faultstring = $faultstring;
$this->faultdetail = $faultdetail;
}
/**
* serialize a fault
*
* @return string The serialization of the fault instance.
* @access public
*/
function serialize(){
$ns_string = '';
foreach($this->namespaces as $k => $v){
$ns_string .= "\n xmlns:$k=\"$v\"";
}
$return_msg =
'<?xml version="1.0" encoding="'.$this->soap_defencoding
.'"?>'.
'<SOAP-ENV:Envelope SOAP-ENV:encodingStyle="http://schem
as.xmlsoap.org/soap/encoding/"'.$ns_string.">\n".
'<SOAP-ENV:Body>'.
'<SOAP-ENV:Fault>'.
$this->serialize_val($this->faultcode, '
faultcode').
$this->serialize_val($this->faultactor,
'faultactor').
$this->serialize_val($this->faultstring,
'faultstring').
$this->serialize_val($this->faultdetail,
'detail').
'</SOAP-ENV:Fault>'.
'</SOAP-ENV:Body>'.
'</SOAP-ENV:Envelope>';
return $return_msg;
}
}

?><?php

/**
* parses an XML Schema, allows access to it's data, other utility methods
* no validation... yet.
* very experimental and limited. As is discussed on XML-DEV, I'm one of the peop
le
* that just doesn't have time to read the spec(s) thoroughly, and just have a co
uple of trusty
* tutorials I refer to :)
*
* @author Dietrich Ayala <[email protected]>
* @version $Id: nusoap.php,v 1.94 2005/08/04 01:27:42 snichol Exp $
* @access public
*/
class XMLSchema extends nusoap_base {
// files
var $schema = '';
var $xml = '';
// namespaces
var $enclosingNamespaces;
// schema info
var $schemaInfo = array();
var $schemaTargetNamespace = '';
// types, elements, attributes defined by the schema
var $attributes = array();
var $complexTypes = array();
var $complexTypeStack = array();
var $currentComplexType = null;
var $elements = array();
var $elementStack = array();
var $currentElement = null;
var $simpleTypes = array();
var $simpleTypeStack = array();
var $currentSimpleType = null;
// imports
var $imports = array();
// parser vars
var $parser;
var $position = 0;
var $depth = 0;
var $depth_array = array();
var $message = array();
var $defaultNamespace = array();
/**
* constructor
*
* @param string $schema schema document URI
* @param string $xml xml document URI
* @param string $namespaces namespaces defined in enclosing XML
* @access public
*/
function XMLSchema($schema='',$xml='',$namespaces=array()){
parent::nusoap_base();
$this->debug('xmlschema class instantiated, inside constructor')
;
// files
$this->schema = $schema;
$this->xml = $xml;
// namespaces
$this->enclosingNamespaces = $namespaces;
$this->namespaces = array_merge($this->namespaces, $namespaces);
// parse schema file
if($schema != ''){
$this->debug('initial schema file: '.$schema);
$this->parseFile($schema, 'schema');
}
// parse xml file
if($xml != ''){
$this->debug('initial xml file: '.$xml);
$this->parseFile($xml, 'xml');
}
}
/**
* parse an XML file
*
* @param string $xml, path/URL to XML file
* @param string $type, (schema | xml)
* @return boolean
* @access public
*/
function parseFile($xml,$type){
// parse xml file
if($xml != ""){
$xmlStr = @join("",@file($xml));
if($xmlStr == ""){
$msg = 'Error reading XML from '.$xml;
$this->setError($msg);
$this->debug($msg);
return false;
} else {
$this->debug("parsing $xml");
$this->parseString($xmlStr,$type);
$this->debug("done parsing $xml");
return true;
}
}
return false;
}
/**
* parse an XML string
*
* @param string $xml path or URL
* @param string $type, (schema|xml)
* @access private
*/
function parseString($xml,$type){
// parse xml string
if($xml != ""){
// Create an XML parser.
$this->parser = xml_parser_create();
// Set the options for parsing the XML data.
xml_parser_set_option($this->parser, XML_OPTION_CASE_FOLDING, 0)
;
// Set the object for the parser.
xml_set_object($this->parser, $this);
// Set the element handlers for the parser.
if($type == "schema"){
xml_set_element_handler($this->parser, 'schemaStartEleme
nt','schemaEndElement');
xml_set_character_data_handler($this->parser,'schemaChar
acterData');
} elseif($type == "xml"){
xml_set_element_handler($this->parser, 'xmlStart
Element','xmlEndElement');
xml_set_character_data_handler($this->parser,'xmlCharact
erData');
}
// Parse the XML file.
if(!xml_parse($this->parser,$xml,true)){
// Display an error message.
$errstr = sprintf('XML error parsing XML schema
on line %d: %s',
xml_get_current_line_number($this->parser),
xml_error_string(xml_get_error_code($this->parse
r))
);
$this->debug($errstr);
$this->debug("XML payload:\n" . $xml);
$this->setError($errstr);
}
xml_parser_free($this->parser);
} else{
$this->debug('no xml passed to parseString()!!');
$this->setError('no xml passed to parseString()!!');
}
}
/**
* start-element handler
*
* @param string $parser XML parser object
* @param string $name element name
* @param string $attrs associative array of attributes
* @access private
*/
function schemaStartElement($parser, $name, $attrs) {
// position in the total number of elements, starting from 0
$pos = $this->position++;
$depth = $this->depth++;
// set self as current value for this depth
$this->depth_array[$depth] = $pos;
$this->message[$pos] = array('cdata' => '');
if ($depth > 0) {
$this->defaultNamespace[$pos] = $this->defaultNamespace[
$this->depth_array[$depth - 1]];
} else {
$this->defaultNamespace[$pos] = false;
}
// get element prefix
if($prefix = $this->getPrefix($name)){
// get unqualified name
$name = $this->getLocalPart($name);
} else {
$prefix = '';
}
// loop thru attributes, expanding, and registering namespace declaratio
ns
if(count($attrs) > 0){
foreach($attrs as $k => $v){
// if ns declarations, add to class level array of valid namespa
ces
if(ereg("^xmlns",$k)){
//$this->xdebug("$k: $v");
//$this->xdebug('ns_prefix: '.$this->getPrefix($k));
if($ns_prefix = substr(strrchr($k,':'),1)){
//$this->xdebug("Add namespace[$ns_prefix] = $v"
);
$this->namespaces[$ns_prefix] =
$v;
} else {
$this->defaultNamespace[$pos] =
$v;
if (! $this->getPrefixFromNamesp
ace($v)) {
$this->namespaces['ns'.(
count($this->namespaces)+1)] = $v;
}
}
if($v == 'http://www.w3.org/2001/XMLSche
ma' || $v == 'http://www.w3.org/1999/XMLSchema' || $v == 'http://www.w3.org/2000
/10/XMLSchema'){
$this->XMLSchemaVersion = $v;
$this->namespaces['xsi'] = $v.'-
instance';
}
}
}
foreach($attrs as $k => $v){
// expand each attribute
$k = strpos($k,':') ? $this->expandQname($k) : $k;
$v = strpos($v,':') ? $this->expandQname($v) : $v;
$eAttrs[$k] = $v;
}
$attrs = $eAttrs;
} else {
$attrs = array();
}
// find status, register data
switch($name){
case 'all': // (optional) compositor
content for a complexType
case 'choice':
case 'group':
case 'sequence':
//$this->xdebug("compositor $name for currentCom
plexType: $this->currentComplexType and currentElement: $this->currentElement");
$this->complexTypes[$this->currentComplexType]['
compositor'] = $name;
//if($name == 'all' || $name == 'sequence'){
// $this->complexTypes[$this->currentComple
xType]['phpType'] = 'struct';
//}
break;
case 'attribute': // complexType attribute
//$this->xdebug("parsing attribute $attrs[name] $attrs[ref] of v
alue: ".$attrs['http://schemas.xmlsoap.org/wsdl/:arrayType']);
$this->xdebug("parsing attribute:");
$this->appendDebug($this->varDump($attrs));
if (!isset($attrs['form'])) {
$attrs['form'] = $this->schemaInfo['attr
ibuteFormDefault'];
}
if (isset($attrs['http://schemas.xmlsoap.org/wsdl/:arrayType']))
{
$v = $attrs['http://schemas.xmlsoap.org/
wsdl/:arrayType'];
if (!strpos($v, ':')) {
// no namespace in arrayType att
ribute value...
if ($this->defaultNamespace[$pos
]) {
// ...so use the default
$attrs['http://schemas.x
mlsoap.org/wsdl/:arrayType'] = $this->defaultNamespace[$pos] . ':' . $attrs['htt
p://schemas.xmlsoap.org/wsdl/:arrayType'];
}
}
}
if(isset($attrs['name'])){
$this->attributes[$attrs['name']] = $att
rs;
$aname = $attrs['name'];
} elseif(isset($attrs['ref']) && $attrs['ref'] =
= 'http://schemas.xmlsoap.org/soap/encoding/:arrayType'){
if (isset($attrs['http://schemas.xmlsoap
.org/wsdl/:arrayType'])) {
$aname = $attrs['http://schemas.xmlsoap.org/wsdl
/:arrayType'];
} else {
$aname = '';
}
} elseif(isset($attrs['ref'])){
$aname = $attrs['ref'];
$this->attributes[$attrs['ref']] = $attrs;
}

if($this->currentComplexType){ // This should *


always* be
$this->complexTypes[$this->currentComple
xType]['attrs'][$aname] = $attrs;
}
// arrayType attribute
if(isset($attrs['http://schemas.xmlsoap.org/wsdl
/:arrayType']) || $this->getLocalPart($aname) == 'arrayType'){
$this->complexTypes[$this->currentComple
xType]['phpType'] = 'array';
$prefix = $this->getPrefix($aname);
if(isset($attrs['http://schemas.xmlsoap.
org/wsdl/:arrayType'])){
$v = $attrs['http://schemas.xmls
oap.org/wsdl/:arrayType'];
} else {
$v = '';
}
if(strpos($v,'[,]')){
$this->complexTypes[$this->currentComplexType]['multidim
ensional'] = true;
}
$v = substr($v,0,strpos($v,'[')); // clip the []
if(!strpos($v,':') && isset($this->typemap[$this->XMLSchemaV
ersion][$v])){
$v = $this->XMLSchemaVersion.':'.$v;
}
$this->complexTypes[$this->currentComplexType]['arrayType']
= $v;
}
break;
case 'complexContent': // (optional) content for a comp
lexType
break;
case 'complexType':
array_push($this->complexTypeStack, $this->curre
ntComplexType);
if(isset($attrs['name'])){
$this->xdebug('processing named complexT
ype '.$attrs['name']);
//$this->currentElement = false;
$this->currentComplexType = $attrs['name
'];
$this->complexTypes[$this->currentComple
xType] = $attrs;
$this->complexTypes[$this->currentComple
xType]['typeClass'] = 'complexType';
// This is for constructs like
// <complexType name="ListOfSt
ring" base="soap:Array">
// <sequence>
// <element name="str
ing" type="xsd:string"
// minOccurs="0"
maxOccurs="unbounded" />
// </sequence>
// </complexType>
if(isset($attrs['base']) && ereg(':Array
$',$attrs['base'])){
$this->xdebug('complexType is un
usual array');
$this->complexTypes[$this->curre
ntComplexType]['phpType'] = 'array';
} else {
$this->complexTypes[$this->curre
ntComplexType]['phpType'] = 'struct';
}
}else{
$this->xdebug('processing unnamed comple
xType for element '.$this->currentElement);
$this->currentComplexType = $this->curre
ntElement . '_ContainedType';
//$this->currentElement = false;
$this->complexTypes[$this->currentComple
xType] = $attrs;
$this->complexTypes[$this->currentComple
xType]['typeClass'] = 'complexType';
// This is for constructs like
// <complexType name="ListOfSt
ring" base="soap:Array">
// <sequence>
// <element name="str
ing" type="xsd:string"
// minOccurs="0"
maxOccurs="unbounded" />
// </sequence>
// </complexType>
if(isset($attrs['base']) && ereg(':Array
$',$attrs['base'])){
$this->xdebug('complexType is un
usual array');
$this->complexTypes[$this->curre
ntComplexType]['phpType'] = 'array';
} else {
$this->complexTypes[$this->curre
ntComplexType]['phpType'] = 'struct';
}
}
break;
case 'element':
array_push($this->elementStack, $this->currentEl
ement);
// elements defined as part of a complex type sh
ould
// not really be added to $this->elements, but f
or some
// reason, they are
if (!isset($attrs['form'])) {
$attrs['form'] = $this->schemaInfo['elem
entFormDefault'];
}
if(isset($attrs['type'])){
$this->xdebug("processing typed element
".$attrs['name']." of type ".$attrs['type']);
if (! $this->getPrefix($attrs['type']))
{
if ($this->defaultNamespace[$pos
]) {
$attrs['type'] = $this->
defaultNamespace[$pos] . ':' . $attrs['type'];
$this->xdebug('used defa
ult namespace to make type ' . $attrs['type']);
}
}
// This is for constructs like
// <complexType name="ListOfSt
ring" base="soap:Array">
// <sequence>
// <element name="str
ing" type="xsd:string"
// minOccurs="0"
maxOccurs="unbounded" />
// </sequence>
// </complexType>
if ($this->currentComplexType && $this->
complexTypes[$this->currentComplexType]['phpType'] == 'array') {
$this->xdebug('arrayType for unu
sual array is ' . $attrs['type']);
$this->complexTypes[$this->curre
ntComplexType]['arrayType'] = $attrs['type'];
}
$this->currentElement = $attrs['name'];
$this->elements[ $attrs['name'] ] = $att
rs;
$this->elements[ $attrs['name'] ]['typeC
lass'] = 'element';
$ename = $attrs['name'];
} elseif(isset($attrs['ref'])){
$this->xdebug("processing element as ref
to ".$attrs['ref']);
$this->currentElement = "ref to ".$attrs
['ref'];
$ename = $this->getLocalPart($attrs['ref
']);
} else {
$this->xdebug("processing untyped elemen
t ".$attrs['name']);
$this->currentElement = $attrs['name'];
$this->elements[ $attrs['name'] ] = $att
rs;
$this->elements[ $attrs['name'] ]['typeC
lass'] = 'element';
$attrs['type'] = $this->schemaTargetName
space . ':' . $attrs['name'] . '_ContainedType';
$this->elements[ $attrs['name'] ]['type'
] = $attrs['type'];
$ename = $attrs['name'];
}
if(isset($ename) && $this->currentComplexType){
$this->complexTypes[$this->currentComple
xType]['elements'][$ename] = $attrs;
}
break;
case 'enumeration': // restriction value list m
ember
$this->xdebug('enumeration ' . $attrs['value']);
if ($this->currentSimpleType) {
$this->simpleTypes[$this->currentSimpleT
ype]['enumeration'][] = $attrs['value'];
} elseif ($this->currentComplexType) {
$this->complexTypes[$this->currentComple
xType]['enumeration'][] = $attrs['value'];
}
break;
case 'extension': // simpleContent or complexConte
nt type extension
$this->xdebug('extension ' . $attrs['base']);
if ($this->currentComplexType) {
$this->complexTypes[$this->currentComple
xType]['extensionBase'] = $attrs['base'];
}
break;
case 'import':
if (isset($attrs['schemaLocation'])) {
//$this->xdebug('import namespace ' . $a
ttrs['namespace'] . ' from ' . $attrs['schemaLocation']);
$this->imports[$attrs['namespace']][] = array('location' =>
$attrs['schemaLocation'], 'loaded' => false);
} else {
//$this->xdebug('import namespace ' . $a
ttrs['namespace']);
$this->imports[$attrs['namespace']][] = array('location' =>
'', 'loaded' => true);
if (! $this->getPrefixFromNamespace($att
rs['namespace'])) {
$this->namespaces['ns'.(count($t
his->namespaces)+1)] = $attrs['namespace'];
}
}
break;
case 'list': // simpleType value list
break;
case 'restriction': // simpleType, simpleContent or
complexContent value restriction
$this->xdebug('restriction ' . $attrs['base']);
if($this->currentSimpleType){
$this->simpleTypes[$this->currentSimpleT
ype]['type'] = $attrs['base'];
} elseif($this->currentComplexType){
$this->complexTypes[$this->currentComple
xType]['restrictionBase'] = $attrs['base'];
if(strstr($attrs['base'],':') == ':Array
'){
$this->complexTypes[$this->curre
ntComplexType]['phpType'] = 'array';
}
}
break;
case 'schema':
$this->schemaInfo = $attrs;
$this->schemaInfo['schemaVersion'] = $this->getN
amespaceFromPrefix($prefix);
if (isset($attrs['targetNamespace'])) {
$this->schemaTargetNamespace = $attrs['t
argetNamespace'];
}
if (!isset($attrs['elementFormDefault'])) {
$this->schemaInfo['elementFormDefault']
= 'unqualified';
}
if (!isset($attrs['attributeFormDefault'])) {
$this->schemaInfo['attributeFormDefault'
] = 'unqualified';
}
break;
case 'simpleContent': // (optional) content for a comp
lexType
break;
case 'simpleType':
array_push($this->simpleTypeStack, $this->curren
tSimpleType);
if(isset($attrs['name'])){
$this->xdebug("processing simpleType for
name " . $attrs['name']);
$this->currentSimpleType = $attrs['name'
];
$this->simpleTypes[ $attrs['name'] ] = $
attrs;
$this->simpleTypes[ $attrs['name'] ]['ty
peClass'] = 'simpleType';
$this->simpleTypes[ $attrs['name'] ]['ph
pType'] = 'scalar';
} else {
$this->xdebug('processing unnamed simple
Type for element '.$this->currentElement);
$this->currentSimpleType = $this->curren
tElement . '_ContainedType';
//$this->currentElement = false;
$this->simpleTypes[$this->currentSimpleT
ype] = $attrs;
$this->simpleTypes[$this->currentSimpleT
ype]['phpType'] = 'scalar';
}
break;
case 'union': // simpleType type list
break;
default:
//$this->xdebug("do not have anything to do for
element $name");
}
}
/**
* end-element handler
*
* @param string $parser XML parser object
* @param string $name element name
* @access private
*/
function schemaEndElement($parser, $name) {
// bring depth down a notch
$this->depth--;
// position of current element is equal to the last value left i
n depth_array for my depth
if(isset($this->depth_array[$this->depth])){
$pos = $this->depth_array[$this->depth];
}
// get element prefix
if ($prefix = $this->getPrefix($name)){
// get unqualified name
$name = $this->getLocalPart($name);
} else {
$prefix = '';
}
// move on...
if($name == 'complexType'){
$this->xdebug('done processing complexType ' . ($this->c
urrentComplexType ? $this->currentComplexType : '(unknown)'));
$this->currentComplexType = array_pop($this->complexType
Stack);
//$this->currentElement = false;
}
if($name == 'element'){
$this->xdebug('done processing element ' . ($this->curre
ntElement ? $this->currentElement : '(unknown)'));
$this->currentElement = array_pop($this->elementStack);
}
if($name == 'simpleType'){
$this->xdebug('done processing simpleType ' . ($this->cu
rrentSimpleType ? $this->currentSimpleType : '(unknown)'));
$this->currentSimpleType = array_pop($this->simpleTypeSt
ack);
}
}
/**
* element content handler
*
* @param string $parser XML parser object
* @param string $data element content
* @access private
*/
function schemaCharacterData($parser, $data){
$pos = $this->depth_array[$this->depth - 1];
$this->message[$pos]['cdata'] .= $data;
}
/**
* serialize the schema
*
* @access public
*/
function serializeSchema(){
$schemaPrefix = $this->getPrefixFromNamespace($this->XMLSchemaVe
rsion);
$xml = '';
// imports
if (sizeof($this->imports) > 0) {
foreach($this->imports as $ns => $list) {
foreach ($list as $ii) {
if ($ii['location'] != '') {
$xml .= " <$schemaPrefix:import
location=\"" . $ii['location'] . '" namespace="' . $ns . "\" />\n";
} else {
$xml .= " <$schemaPrefix:import
namespace=\"" . $ns . "\" />\n";
}
}
}
}
// complex types
foreach($this->complexTypes as $typeName => $attrs){
$contentStr = '';
// serialize child elements
if(isset($attrs['elements']) && (count($attrs['elements'
]) > 0)){
foreach($attrs['elements'] as $element => $ePart
s){
if(isset($eParts['ref'])){
$contentStr .= " <$schemaPrefi
x:element ref=\"$element\"/>\n";
} else {
$contentStr .= " <$schemaPrefi
x:element name=\"$element\" type=\"" . $this->contractQName($eParts['type']) . "
\"";
foreach ($eParts as $aName => $a
Value) {
// handle, e.g., abstrac
t, default, form, minOccurs, maxOccurs, nillable
if ($aName != 'name' &&
$aName != 'type') {
$contentStr .= "
$aName=\"$aValue\"";
}
}
$contentStr .= "/>\n";
}
}
// compositor wraps elements
if (isset($attrs['compositor']) && ($attrs['comp
ositor'] != '')) {
$contentStr = " <$schemaPrefix:$attrs[c
ompositor]>\n".$contentStr." </$schemaPrefix:$attrs[compositor]>\n";
}
}
// attributes
if(isset($attrs['attrs']) && (count($attrs['attrs']) >=
1)){
foreach($attrs['attrs'] as $attr => $aParts){
$contentStr .= " <$schemaPrefix:attri
bute";
foreach ($aParts as $a => $v) {
if ($a == 'ref' || $a == 'type')
{
$contentStr .= " $a=\"".
$this->contractQName($v).'"';
} elseif ($a == 'http://schemas.
xmlsoap.org/wsdl/:arrayType') {
$this->usedNamespaces['w
sdl'] = $this->namespaces['wsdl'];
$contentStr .= ' wsdl:ar
rayType="'.$this->contractQName($v).'"';
} else {
$contentStr .= " $a=\"$v
\"";
}
}
$contentStr .= "/>\n";
}
}
// if restriction
if (isset($attrs['restrictionBase']) && $attrs['restrict
ionBase'] != ''){
$contentStr = " <$schemaPrefix:restriction bas
e=\"".$this->contractQName($attrs['restrictionBase'])."\">\n".$contentStr." </
$schemaPrefix:restriction>\n";
// complex or simple content
if ((isset($attrs['elements']) && count($attrs['
elements']) > 0) || (isset($attrs['attrs']) && count($attrs['attrs']) > 0)){
$contentStr = " <$schemaPrefix:complexC
ontent>\n".$contentStr." </$schemaPrefix:complexContent>\n";
}
}
// finalize complex type
if($contentStr != ''){
$contentStr = " <$schemaPrefix:complexType name=
\"$typeName\">\n".$contentStr." </$schemaPrefix:complexType>\n";
} else {
$contentStr = " <$schemaPrefix:complexType name=
\"$typeName\"/>\n";
}
$xml .= $contentStr;
}
// simple types
if(isset($this->simpleTypes) && count($this->simpleTypes) > 0){
foreach($this->simpleTypes as $typeName => $eParts){
$xml .= " <$schemaPrefix:simpleType name=\"$type
Name\">\n <$schemaPrefix:restriction base=\"".$this->contractQName($eParts['typ
e'])."\"/>\n";
if (isset($eParts['enumeration'])) {
foreach ($eParts['enumeration'] as $e) {
$xml .= " <$schemaPrefix:enumer
ation value=\"$e\"/>\n";
}
}
$xml .= " </$schemaPrefix:simpleType>";
}
}
// elements
if(isset($this->elements) && count($this->elements) > 0){
foreach($this->elements as $element => $eParts){
$xml .= " <$schemaPrefix:element name=\"$element
\" type=\"".$this->contractQName($eParts['type'])."\"/>\n";
}
}
// attributes
if(isset($this->attributes) && count($this->attributes) > 0){
foreach($this->attributes as $attr => $aParts){
$xml .= " <$schemaPrefix:attribute name=\"$attr\
" type=\"".$this->contractQName($aParts['type'])."\"\n/>";
}
}
// finish 'er up
$el = "<$schemaPrefix:schema targetNamespace=\"$this->schemaTarg
etNamespace\"\n";
foreach (array_diff($this->usedNamespaces, $this->enclosingNames
paces) as $nsp => $ns) {
$el .= " xmlns:$nsp=\"$ns\"\n";
}
$xml = $el . ">\n".$xml."</$schemaPrefix:schema>\n";
return $xml;
}
/**
* adds debug data to the clas level debug string
*
* @param string $string debug data
* @access private
*/
function xdebug($string){
$this->debug('<' . $this->schemaTargetNamespace . '> '.$string);
}
/**
* get the PHP type of a user defined type in the schema
* PHP type is kind of a misnomer since it actually returns 'struct' for asso
c. arrays
* returns false if no type exists, or not w/ the given namespace
* else returns a string that is either a native php type, or 'struct'
*
* @param string $type, name of defined type
* @param string $ns, namespace of type
* @return mixed
* @access public
* @deprecated
*/
function getPHPType($type,$ns){
if(isset($this->typemap[$ns][$type])){
//print "found type '$type' and ns $ns in typemap<br>";
return $this->typemap[$ns][$type];
} elseif(isset($this->complexTypes[$type])){
//print "getting type '$type' and ns $ns from complexTyp
es array<br>";
return $this->complexTypes[$type]['phpType'];
}
return false;
}
/**
* returns an associative array of information about a given type
* returns false if no type exists by the given name
*
* For a complexType typeDef = array(
* 'restrictionBase' => '',
* 'phpType' => '',
* 'compositor' => '(sequence|all)',
* 'elements' => array(), // refs to elements array
* 'attrs' => array() // refs to attributes array
* ... and so on (see addComplexType)
* )
*
* For simpleType or element, the array has different keys.
*
* @param string
* @return mixed
* @access public
* @see addComplexType
* @see addSimpleType
* @see addElement
*/
function getTypeDef($type){
//$this->debug("in getTypeDef for type $type");
if(isset($this->complexTypes[$type])){
$this->xdebug("in getTypeDef, found complexType $type");
return $this->complexTypes[$type];
} elseif(isset($this->simpleTypes[$type])){
$this->xdebug("in getTypeDef, found simpleType $type");
if (!isset($this->simpleTypes[$type]['phpType'])) {
// get info for type to tack onto the simple typ
e
// TODO: can this ever really apply (i.e. what i
s a simpleType really?)
$uqType = substr($this->simpleTypes[$type]['type
'], strrpos($this->simpleTypes[$type]['type'], ':') + 1);
$ns = substr($this->simpleTypes[$type]['type'],
0, strrpos($this->simpleTypes[$type]['type'], ':'));
$etype = $this->getTypeDef($uqType);
if ($etype) {
$this->xdebug("in getTypeDef, found type
for simpleType $type:");
$this->xdebug($this->varDump($etype));
if (isset($etype['phpType'])) {
$this->simpleTypes[$type]['phpTy
pe'] = $etype['phpType'];
}
if (isset($etype['elements'])) {
$this->simpleTypes[$type]['eleme
nts'] = $etype['elements'];
}
}
}
return $this->simpleTypes[$type];
} elseif(isset($this->elements[$type])){
$this->xdebug("in getTypeDef, found element $type");
if (!isset($this->elements[$type]['phpType'])) {
// get info for type to tack onto the element
$uqType = substr($this->elements[$type]['type'],
strrpos($this->elements[$type]['type'], ':') + 1);
$ns = substr($this->elements[$type]['type'], 0,
strrpos($this->elements[$type]['type'], ':'));
$etype = $this->getTypeDef($uqType);
if ($etype) {
$this->xdebug("in getTypeDef, found type
for element $type:");
$this->xdebug($this->varDump($etype));
if (isset($etype['phpType'])) {
$this->elements[$type]['phpType'
] = $etype['phpType'];
}
if (isset($etype['elements'])) {
$this->elements[$type]['elements
'] = $etype['elements'];
}
} elseif ($ns == 'http://www.w3.org/2001/XMLSche
ma') {
$this->xdebug("in getTypeDef, element $t
ype is an XSD type");
$this->elements[$type]['phpType'] = 'sca
lar';
}
}
return $this->elements[$type];
} elseif(isset($this->attributes[$type])){
$this->xdebug("in getTypeDef, found attribute $type");
return $this->attributes[$type];
} elseif (ereg('_ContainedType$', $type)) {
$this->xdebug("in getTypeDef, have an untyped element $t
ype");
$typeDef['typeClass'] = 'simpleType';
$typeDef['phpType'] = 'scalar';
$typeDef['type'] = 'http://www.w3.org/2001/XMLSchema:str
ing';
return $typeDef;
}
$this->xdebug("in getTypeDef, did not find $type");
return false;
}
/**
* returns a sample serialization of a given type, or false if no type by the
given name
*
* @param string $type, name of type
* @return mixed
* @access public
* @deprecated
*/
function serializeTypeDef($type){
//print "in sTD() for type $type<br>";
if($typeDef = $this->getTypeDef($type)){
$str .= '<'.$type;
if(is_array($typeDef['attrs'])){
foreach($attrs as $attName => $data){
$str .= " $attName=\"{type = ".$data['type']."}\"";
}
}
$str .= " xmlns=\"".$this->schema['targetNamespace']."\"";
if(count($typeDef['elements']) > 0){
$str .= ">";
foreach($typeDef['elements'] as $element => $eData){
$str .= $this->serializeTypeDef($element);
}
$str .= "</$type>";
} elseif($typeDef['typeClass'] == 'element') {
$str .= "></$type>";
} else {
$str .= "/>";
}
return $str;
}
return false;
}
/**
* returns HTML form elements that allow a user
* to enter values for creating an instance of the given type.
*
* @param string $name, name for type instance
* @param string $type, name of type
* @return string
* @access public
* @deprecated
*/
function typeToForm($name,$type){
// get typedef
if($typeDef = $this->getTypeDef($type)){
// if struct
if($typeDef['phpType'] == 'struct'){
$buffer .= '<table>';
foreach($typeDef['elements'] as $child => $child
Def){
$buffer .= "
<tr><td align='right'>$childDef[name] (t
ype: ".$this->getLocalPart($childDef['type'])."):</td>
<td><input type='text' name='parameters[
".$name."][$childDef[name]]'></td></tr>";
}
$buffer .= '</table>';
// if array
} elseif($typeDef['phpType'] == 'array'){
$buffer .= '<table>';
for($i=0;$i < 3; $i++){
$buffer .= "
<tr><td align='right'>array item (type:
$typeDef[arrayType]):</td>
<td><input type='text' name='parameters[
".$name."][]'></td></tr>";
}
$buffer .= '</table>';
// if scalar
} else {
$buffer .= "<input type='text' name='parameters[
$name]'>";
}
} else {
$buffer .= "<input type='text' name='parameters[$name]'>
";
}
return $buffer;
}
/**
* adds a complex type to the schema
*
* example: array
*
* addType(
* 'ArrayOfstring',
* 'complexType',
* 'array',
* '',
* 'SOAP-ENC:Array',
* array('ref'=>'SOAP-ENC:arrayType','wsdl:arrayType'=>'string[]'),
* 'xsd:string'
* );
*
* example: PHP associative array ( SOAP Struct )
*
* addType(
* 'SOAPStruct',
* 'complexType',
* 'struct',
* 'all',
* array('myVar'=> array('name'=>'myVar','type'=>'string')
* );
*
* @param name
* @param typeClass (complexType|simpleType|attribute)
* @param phpType: currently supported are array and struct (php assoc ar
ray)
* @param compositor (all|sequence|choice)
* @param restrictionBase namespace:name (http://schemas.xmlsoap.org/soap
/encoding/:Array)
* @param elements = array ( name = array(name=>'',type=>'') )
* @param attrs = array(
* array(
* 'ref' => "http://schemas.xmlsoap.org/soap/encoding/:arra
yType",
* "http://schemas.xmlsoap.org/wsdl/:arrayType" => "string[
]"
* )
* )
* @param arrayType: namespace:name (http://www.w3.org/2001/XMLSchema:str
ing)
* @access public
* @see getTypeDef
*/
function addComplexType($name,$typeClass='complexType',$phpType='array',
$compositor='',$restrictionBase='',$elements=array(),$attrs=array(),$arrayType='
'){
$this->complexTypes[$name] = array(
'name' => $name,
'typeClass' => $typeClass,
'phpType' => $phpType,
'compositor'=> $compositor,
'restrictionBase' => $restrictionBase,
'elements' => $elements,
'attrs' => $attrs,
'arrayType' => $arrayType
);
$this->xdebug("addComplexType $name:");
$this->appendDebug($this->varDump($this->complexTypes[$name]));
}
/**
* adds a simple type to the schema
*
* @param string $name
* @param string $restrictionBase namespace:name (http://schemas.xmlsoap.
org/soap/encoding/:Array)
* @param string $typeClass (should always be simpleType)
* @param string $phpType (should always be scalar)
* @param array $enumeration array of values
* @access public
* @see xmlschema
* @see getTypeDef
*/
function addSimpleType($name, $restrictionBase='', $typeClass='simpleTyp
e', $phpType='scalar', $enumeration=array()) {
$this->simpleTypes[$name] = array(
'name' => $name,
'typeClass' => $typeClass,
'phpType' => $phpType,
'type' => $restrictionBase,
'enumeration' => $enumeration
);
$this->xdebug("addSimpleType $name:");
$this->appendDebug($this->varDump($this->simpleTypes[$name]));
}
/**
* adds an element to the schema
*
* @param array $attrs attributes that must include name and type
* @see xmlschema
* @access public
*/
function addElement($attrs) {
if (! $this->getPrefix($attrs['type'])) {
$attrs['type'] = $this->schemaTargetNamespace . ':' . $a
ttrs['type'];
}
$this->elements[ $attrs['name'] ] = $attrs;
$this->elements[ $attrs['name'] ]['typeClass'] = 'element';
$this->xdebug("addElement " . $attrs['name']);
$this->appendDebug($this->varDump($this->elements[ $attrs['name'
] ]));
}
}

?><?php

/**
* For creating serializable abstractions of native PHP types. This class
* allows element name/namespace, XSD type, and XML attributes to be
* associated with a value. This is extremely useful when WSDL is not
* used, but is also useful when WSDL is used with polymorphic types, including
* xsd:anyType and user-defined types.
*
* @author Dietrich Ayala <[email protected]>
* @version $Id: nusoap.php,v 1.94 2005/08/04 01:27:42 snichol Exp $
* @access public
*/
class soapval extends nusoap_base {
/**
* The XML element name
*
* @var string
* @access private
*/
var $name;
/**
* The XML type name (string or false)
*
* @var mixed
* @access private
*/
var $type;
/**
* The PHP value
*
* @var mixed
* @access private
*/
var $value;
/**
* The XML element namespace (string or false)
*
* @var mixed
* @access private
*/
var $element_ns;
/**
* The XML type namespace (string or false)
*
* @var mixed
* @access private
*/
var $type_ns;
/**
* The XML element attributes (array or false)
*
* @var mixed
* @access private
*/
var $attributes;
/**
* constructor
*
* @param string $name optional name
* @param mixed $type optional type name
* @param mixed $value optional value
* @param mixed $element_ns optional namespace of value
* @param mixed $type_ns optional namespace of type
* @param mixed $attributes associative array of attributes to add
to element serialization
* @access public
*/
function soapval($name='soapval',$type=false,$value=-1,$element_ns=false
,$type_ns=false,$attributes=false) {
parent::nusoap_base();
$this->name = $name;
$this->type = $type;
$this->value = $value;
$this->element_ns = $element_ns;
$this->type_ns = $type_ns;
$this->attributes = $attributes;
}
/**
* return serialized value
*
* @param string $use The WSDL use value (encoded|literal)
* @return string XML data
* @access public
*/
function serialize($use='encoded') {
return $this->serialize_val($this->value,$this->name,$this->type
,$this->element_ns,$this->type_ns,$this->attributes,$use);
}
/**
* decodes a soapval object into a PHP native type
*
* @return mixed
* @access public
*/
function decode(){
return $this->value;
}
}

?><?php

/**
* transport class for sending/receiving data via HTTP and HTTPS
* NOTE: PHP must be compiled with the CURL extension for HTTPS support
*
* @author Dietrich Ayala <[email protected]>
* @version $Id: nusoap.php,v 1.94 2005/08/04 01:27:42 snichol Exp $
* @access public
*/
class soap_transport_http extends nusoap_base {
var $url = '';
var $uri = '';
var $digest_uri = '';
var $scheme = '';
var $host = '';
var $port = '';
var $path = '';
var $request_method = 'POST';
var $protocol_version = '1.0';
var $encoding = '';
var $outgoing_headers = array();
var $incoming_headers = array();
var $incoming_cookies = array();
var $outgoing_payload = '';
var $incoming_payload = '';
var $useSOAPAction = true;
var $persistentConnection = false;
var $ch = false; // cURL handle
var $username = '';
var $password = '';
var $authtype = '';
var $digestRequest = array();
var $certRequest = array(); // keys must be cainfofile (optional), s
slcertfile, sslkeyfile, passphrase, verifypeer (optional), verifyhost (optional)
// cainfofile: c
ertificate authority file, e.g. '$pathToPemFiles/rootca.pem'
// sslcertfile:
SSL certificate file, e.g. '$pathToPemFiles/mycert.pem'
// sslkeyfile: S
SL key file, e.g. '$pathToPemFiles/mykey.pem'
// passphrase: S
SL key password/passphrase
// verifypeer: d
efault is 1
// verifyhost: d
efault is 1
/**
* constructor
*/
function soap_transport_http($url){
parent::nusoap_base();
$this->setURL($url);
ereg('\$Revisio' . 'n: ([^ ]+)', $this->revision, $rev);
$this->outgoing_headers['User-Agent'] = $this->title.'/'.$this->
version.' ('.$rev[1].')';
$this->debug('set User-Agent: ' . $this->outgoing_headers['User-
Agent']);
}
function setURL($url) {
$this->url = $url;
$u = parse_url($url);
foreach($u as $k => $v){
$this->debug("$k = $v");
$this->$k = $v;
}
// add any GET params to path
if(isset($u['query']) && $u['query'] != ''){
$this->path .= '?' . $u['query'];
}
// set default port
if(!isset($u['port'])){
if($u['scheme'] == 'https'){
$this->port = 443;
} else {
$this->port = 80;
}
}
$this->uri = $this->path;
$this->digest_uri = $this->uri;
// build headers
if (!isset($u['port'])) {
$this->outgoing_headers['Host'] = $this->host;
} else {
$this->outgoing_headers['Host'] = $this->host.':'.$this-
>port;
}
$this->debug('set Host: ' . $this->outgoing_headers['Host']);
if (isset($u['user']) && $u['user'] != '') {
$this->setCredentials(urldecode($u['user']), isset($u['p
ass']) ? urldecode($u['pass']) : '');
}
}
function connect($connection_timeout=0,$response_timeout=30){
// For PHP 4.3 with OpenSSL, change https scheme to ssl, then tr
eat like
// "regular" socket.
// TODO: disabled for now because OpenSSL must be *compiled* in
(not just
// loaded), and until PHP5 stream_get_wrappers is not avai
lable.
// if ($this->scheme == 'https') {
// if (version_compare(phpversion(), '4.3.0') >= 0) {
// if (extension_loaded('openssl')) {
// $this->scheme = 'ssl';
// $this->debug('Using SSL over OpenSSL');
// }
// }
// }
$this->debug("connect connection_timeout $connection_timeout, re
sponse_timeout $response_timeout, scheme $this->scheme, host $this->host, port $
this->port");
if ($this->scheme == 'http' || $this->scheme == 'ssl') {
// use persistent connection
if($this->persistentConnection && isset($this->fp) && is_resourc
e($this->fp)){
if (!feof($this->fp)) {
$this->debug('Re-use persistent connection');
return true;
}
fclose($this->fp);
$this->debug('Closed persistent connection at EOF');
}
// munge host if using OpenSSL
if ($this->scheme == 'ssl') {
$host = 'ssl://' . $this->host;
} else {
$host = $this->host;
}
$this->debug('calling fsockopen with host ' . $host . ' connecti
on_timeout ' . $connection_timeout);
// open socket
if($connection_timeout > 0){
$this->fp = @fsockopen( $host, $this->port, $this->errno
, $this->error_str, $connection_timeout);
} else {
$this->fp = @fsockopen( $host, $this->port, $this->errno
, $this->error_str);
}
// test pointer
if(!$this->fp) {
$msg = 'Couldn\'t open socket connection to server ' . $
this->url;
if ($this->errno) {
$msg .= ', Error ('.$this->errno.'): '.$this->er
ror_str;
} else {
$msg .= ' prior to connect(). This is often a p
roblem looking up the host name.';
}
$this->debug($msg);
$this->setError($msg);
return false;
}
// set response timeout
$this->debug('set response timeout to ' . $response_timeout);
socket_set_timeout( $this->fp, $response_timeout);
$this->debug('socket connected');
return true;
} else if ($this->scheme == 'https') {
if (!extension_loaded('curl')) {
$this->setError('CURL Extension, or OpenSSL extension w/
PHP version >= 4.3 is required for HTTPS');
return false;
}
$this->debug('connect using https');
// init CURL
$this->ch = curl_init();
// set url
$hostURL = ($this->port != '') ? "https://$this->host:$this->por
t" : "https://$this->host";
// add path
$hostURL .= $this->path;
curl_setopt($this->ch, CURLOPT_URL, $hostURL);
// follow location headers (re-directs)
curl_setopt($this->ch, CURLOPT_FOLLOWLOCATION, 1);
// ask for headers in the response output
curl_setopt($this->ch, CURLOPT_HEADER, 1);
// ask for the response output as the return value
curl_setopt($this->ch, CURLOPT_RETURNTRANSFER, 1);
// encode
// We manage this ourselves through headers and encoding
// if(function_exists('gzuncompress')){
// curl_setopt($this->ch, CURLOPT_ENCODING, 'deflate');
// }
// persistent connection
if ($this->persistentConnection) {
// The way we send data, we cannot use persistent connec
tions, since
// there will be some "junk" at the end of our request.
//curl_setopt($this->ch, CURL_HTTP_VERSION_1_1, true);
$this->persistentConnection = false;
$this->outgoing_headers['Connection'] = 'close';
$this->debug('set Connection: ' . $this->outgoing_header
s['Connection']);
}
// set timeout
if ($connection_timeout != 0) {
curl_setopt($this->ch, CURLOPT_TIMEOUT, $connection_time
out);
}
// TODO: cURL has added a connection timeout separate from the r
esponse timeout
//if ($connection_timeout != 0) {
// curl_setopt($this->ch, CURLOPT_CONNECTIONTIMEOUT, $conne
ction_timeout);
//}
//if ($response_timeout != 0) {
// curl_setopt($this->ch, CURLOPT_TIMEOUT, $response_timeou
t);
//}
// recent versions of cURL turn on peer/host checking by default
,
// while PHP binaries are not compiled with a default location f
or the
// CA cert bundle, so disable peer/host checking.
//curl_setopt($this->ch, CURLOPT_CAINFO, 'f:\php-4.3.2-win32\extensions\curl-ca-
bundle.crt');
curl_setopt($this->ch, CURLOPT_SSL_VERIFYPEER, 0);
curl_setopt($this->ch, CURLOPT_SSL_VERIFYHOST, 0);
// support client certificates (thanks Tobias Boes, Doug Anarino
, Eryan Ariobowo)
if ($this->authtype == 'certificate') {
if (isset($this->certRequest['cainfofile'])) {
curl_setopt($this->ch, CURLOPT_CAINFO, $this->ce
rtRequest['cainfofile']);
}
if (isset($this->certRequest['verifypeer'])) {
curl_setopt($this->ch, CURLOPT_SSL_VERIFYPEER, $
this->certRequest['verifypeer']);
} else {
curl_setopt($this->ch, CURLOPT_SSL_VERIFYPEER, 1
);
}
if (isset($this->certRequest['verifyhost'])) {
curl_setopt($this->ch, CURLOPT_SSL_VERIFYHOST, $
this->certRequest['verifyhost']);
} else {
curl_setopt($this->ch, CURLOPT_SSL_VERIFYHOST, 1
);
}
if (isset($this->certRequest['sslcertfile'])) {
curl_setopt($this->ch, CURLOPT_SSLCERT, $this->c
ertRequest['sslcertfile']);
}
if (isset($this->certRequest['sslkeyfile'])) {
curl_setopt($this->ch, CURLOPT_SSLKEY, $this->ce
rtRequest['sslkeyfile']);
}
if (isset($this->certRequest['passphrase'])) {
curl_setopt($this->ch, CURLOPT_SSLKEYPASSWD , $t
his->certRequest['passphrase']);
}
}
$this->debug('cURL connection set up');
return true;
} else {
$this->setError('Unknown scheme ' . $this->scheme);
$this->debug('Unknown scheme ' . $this->scheme);
return false;
}
}
/**
* send the SOAP message via HTTP
*
* @param string $data message data
* @param integer $timeout set connection timeout in seconds
* @param integer $response_timeout set response timeout in second
s
* @param array $cookies cookies to send
* @return string data
* @access public
*/
function send($data, $timeout=0, $response_timeout=30, $cookies=NULL) {
$this->debug('entered send() with data of length: '.strlen($data
));
$this->tryagain = true;
$tries = 0;
while ($this->tryagain) {
$this->tryagain = false;
if ($tries++ < 2) {
// make connnection
if (!$this->connect($timeout, $response_timeout)
){
return false;
}
// send request
if (!$this->sendRequest($data, $cookies)){
return false;
}
// get response
$respdata = $this->getResponse();
} else {
$this->setError('Too many tries to get an OK res
ponse');
}
}
$this->debug('end of send()');
return $respdata;
}

/**
* send the SOAP message via HTTPS 1.0 using CURL
*
* @param string $msg message data
* @param integer $timeout set connection timeout in seconds
* @param integer $response_timeout set response timeout in second
s
* @param array $cookies cookies to send
* @return string data
* @access public
*/
function sendHTTPS($data, $timeout=0, $response_timeout=30, $cookies) {
return $this->send($data, $timeout, $response_timeout, $cookies)
;
}
/**
* if authenticating, set user credentials here
*
* @param string $username
* @param string $password
* @param string $authtype (basic, digest, certificate)
* @param array $digestRequest (keys must be nonce, nc, realm, qop
)
* @param array $certRequest (keys must be cainfofile (optional),
sslcertfile, sslkeyfile, passphrase, verifypeer (optional), verifyhost (optional
): see corresponding options in cURL docs)
* @access public
*/
function setCredentials($username, $password, $authtype = 'basic', $dige
stRequest = array(), $certRequest = array()) {
$this->debug("Set credentials for authtype $authtype");
// cf. RFC 2617
if ($authtype == 'basic') {
$this->outgoing_headers['Authorization'] = 'Basic '.base
64_encode(str_replace(':','',$username).':'.$password);
} elseif ($authtype == 'digest') {
if (isset($digestRequest['nonce'])) {
$digestRequest['nc'] = isset($digestRequest['nc'
]) ? $digestRequest['nc']++ : 1;
// calculate the Digest hashes (calculate code b
ased on digest implementation found at: http://www.rassoc.com/gregr/weblog/stori
es/2002/07/09/webServicesSecurityHttpDigestAuthenticationWithoutActiveDirectory.
html)
// A1 = unq(username-value) ":" unq(realm-value)
":" passwd
$A1 = $username. ':' . (isset($digestRequest['re
alm']) ? $digestRequest['realm'] : '') . ':' . $password;
// H(A1) = MD5(A1)
$HA1 = md5($A1);
// A2 = Method ":" digest-uri-value
$A2 = 'POST:' . $this->digest_uri;
// H(A2)
$HA2 = md5($A2);
// KD(secret, data) = H(concat(secret, ":", data
))
// if qop == auth:
// request-digest = <"> < KD ( H(A1), unq(n
once-value)
// ":" nc-value
// ":" unq(cnonce-v
alue)
// ":" unq(qop-valu
e)
// ":" H(A2)
// ) <">
// if qop is missing,
// request-digest = <"> < KD ( H(A1), unq(nonce
-value) ":" H(A2) ) > <">
$unhashedDigest = '';
$nonce = isset($digestRequest['nonce']) ? $diges
tRequest['nonce'] : '';
$cnonce = $nonce;
if ($digestRequest['qop'] != '') {
$unhashedDigest = $HA1 . ':' . $nonce .
':' . sprintf("%08d", $digestRequest['nc']) . ':' . $cnonce . ':' . $digestReque
st['qop'] . ':' . $HA2;
} else {
$unhashedDigest = $HA1 . ':' . $nonce .
':' . $HA2;
}
$hashedDigest = md5($unhashedDigest);
$this->outgoing_headers['Authorization'] = 'Dige
st username="' . $username . '", realm="' . $digestRequest['realm'] . '", nonce=
"' . $nonce . '", uri="' . $this->digest_uri . '", cnonce="' . $cnonce . '", nc=
' . sprintf("%08x", $digestRequest['nc']) . ', qop="' . $digestRequest['qop'] .
'", response="' . $hashedDigest . '"';
}
} elseif ($authtype == 'certificate') {
$this->certRequest = $certRequest;
}
$this->username = $username;
$this->password = $password;
$this->authtype = $authtype;
$this->digestRequest = $digestRequest;
if (isset($this->outgoing_headers['Authorization'])) {
$this->debug('set Authorization: ' . substr($this->outgo
ing_headers['Authorization'], 0, 12) . '...');
} else {
$this->debug('Authorization header not set');
}
}
/**
* set the soapaction value
*
* @param string $soapaction
* @access public
*/
function setSOAPAction($soapaction) {
$this->outgoing_headers['SOAPAction'] = '"' . $soapaction . '"';
$this->debug('set SOAPAction: ' . $this->outgoing_headers['SOAPA
ction']);
}
/**
* use http encoding
*
* @param string $enc encoding style. supported values: gzip, deflate,
or both
* @access public
*/
function setEncoding($enc='gzip, deflate') {
if (function_exists('gzdeflate')) {
$this->protocol_version = '1.1';
$this->outgoing_headers['Accept-Encoding'] = $enc;
$this->debug('set Accept-Encoding: ' . $this->outgoing_h
eaders['Accept-Encoding']);
if (!isset($this->outgoing_headers['Connection'])) {
$this->outgoing_headers['Connection'] = 'close';
$this->persistentConnection = false;
$this->debug('set Connection: ' . $this->outgoin
g_headers['Connection']);
}
set_magic_quotes_runtime(0);
// deprecated
$this->encoding = $enc;
}
}
/**
* set proxy info here
*
* @param string $proxyhost
* @param string $proxyport
* @param string $proxyusername
* @param string $proxypassword
* @access public
*/
function setProxy($proxyhost, $proxyport, $proxyusername = '', $proxypas
sword = '') {
$this->uri = $this->url;
$this->host = $proxyhost;
$this->port = $proxyport;
if ($proxyusername != '' && $proxypassword != '') {
$this->outgoing_headers['Proxy-Authorization'] = ' Basic
'.base64_encode($proxyusername.':'.$proxypassword);
$this->debug('set Proxy-Authorization: ' . $this->outgoi
ng_headers['Proxy-Authorization']);
}
}
/**
* decode a string that is encoded w/ "chunked' transfer encoding
* as defined in RFC2068 19.4.6
*
* @param string $buffer
* @param string $lb
* @returns string
* @access public
* @deprecated
*/
function decodeChunked($buffer, $lb){
// length := 0
$length = 0;
$new = '';
// read chunk-size, chunk-extension (if any) and CRLF
// get the position of the linebreak
$chunkend = strpos($buffer, $lb);
if ($chunkend == FALSE) {
$this->debug('no linebreak found in decodeChunked');
return $new;
}
$temp = substr($buffer,0,$chunkend);
$chunk_size = hexdec( trim($temp) );
$chunkstart = $chunkend + strlen($lb);
// while (chunk-size > 0) {
while ($chunk_size > 0) {
$this->debug("chunkstart: $chunkstart chunk_size: $chunk
_size");
$chunkend = strpos( $buffer, $lb, $chunkstart + $chunk_s
ize);
// Just in case we got a broken connection
if ($chunkend == FALSE) {
$chunk = substr($buffer,$chunkstart);
// append chunk-data to entity-body
$new .= $chunk;
$length += strlen($chunk);
break;
}
// read chunk-data and CRLF
$chunk = substr($buffer,$chunkstart,$chunkend-$chunkstar
t);
// append chunk-data to entity-body
$new .= $chunk;
// length := length + chunk-size
$length += strlen($chunk);
// read chunk-size and CRLF
$chunkstart = $chunkend + strlen($lb);
$chunkend = strpos($buffer, $lb, $chunkstart) + strlen($
lb);
if ($chunkend == FALSE) {
break; //Just in case we got a broken connection
}
$temp = substr($buffer,$chunkstart,$chunkend-$chunkstart
);
$chunk_size = hexdec( trim($temp) );
$chunkstart = $chunkend;
}
return $new;
}
/*
* Writes payload, including HTTP headers, to $this->outgoing_paylo
ad.
*/
function buildPayload($data, $cookie_str = '') {
// add content-length header
$this->outgoing_headers['Content-Length'] = strlen($data);
$this->debug('set Content-Length: ' . $this->outgoing_headers['C
ontent-Length']);
// start building outgoing payload:
$req = "$this->request_method $this->uri HTTP/$this->protocol_ve
rsion";
$this->debug("HTTP request: $req");
$this->outgoing_payload = "$req\r\n";
// loop thru headers, serializing
foreach($this->outgoing_headers as $k => $v){
$hdr = $k.': '.$v;
$this->debug("HTTP header: $hdr");
$this->outgoing_payload .= "$hdr\r\n";
}
// add any cookies
if ($cookie_str != '') {
$hdr = 'Cookie: '.$cookie_str;
$this->debug("HTTP header: $hdr");
$this->outgoing_payload .= "$hdr\r\n";
}
// header/body separator
$this->outgoing_payload .= "\r\n";
// add data
$this->outgoing_payload .= $data;
}
function sendRequest($data, $cookies = NULL) {
// build cookie string
$cookie_str = $this->getCookiesForRequest($cookies, (($this->sch
eme == 'ssl') || ($this->scheme == 'https')));
// build payload
$this->buildPayload($data, $cookie_str);
if ($this->scheme == 'http' || $this->scheme == 'ssl') {
// send payload
if(!fputs($this->fp, $this->outgoing_payload, strlen($this->outg
oing_payload))) {
$this->setError('couldn\'t write message data to socket'
);
$this->debug('couldn\'t write message data to socket');
return false;
}
$this->debug('wrote data to socket, length = ' . strlen($this->o
utgoing_payload));
return true;
} else if ($this->scheme == 'https') {
// set payload
// TODO: cURL does say this should only be the verb, and in fact
it
// turns out that the URI and HTTP version are appended to this,
which
// some servers refuse to work with
//curl_setopt($this->ch, CURLOPT_CUSTOMREQUEST, $this->outgoing_
payload);
foreach($this->outgoing_headers as $k => $v){
$curl_headers[] = "$k: $v";
}
if ($cookie_str != '') {
$curl_headers[] = 'Cookie: ' . $cookie_str;
}
curl_setopt($this->ch, CURLOPT_HTTPHEADER, $curl_headers);
if ($this->request_method == "POST") {
curl_setopt($this->ch, CURLOPT_POST, 1);
curl_setopt($this->ch, CURLOPT_POSTFIELDS, $data);
} else {
}
$this->debug('set cURL payload');
return true;
}
}
function getResponse(){
$this->incoming_payload = '';
if ($this->scheme == 'http' || $this->scheme == 'ssl') {
// loop until headers have been retrieved
$data = '';
while (!isset($lb)){
// We might EOF during header read.
if(feof($this->fp)) {
$this->incoming_payload = $data;
$this->debug('found no headers before EOF after
length ' . strlen($data));
$this->debug("received before EOF:\n" . $data);
$this->setError('server failed to send headers')
;
return false;
}
$tmp = fgets($this->fp, 256);
$tmplen = strlen($tmp);
$this->debug("read line of $tmplen bytes: " . trim($tmp)
);
if ($tmplen == 0) {
$this->incoming_payload = $data;
$this->debug('socket read of headers timed out a
fter length ' . strlen($data));
$this->debug("read before timeout: " . $data);
$this->setError('socket read of headers timed ou
t');
return false;
}
$data .= $tmp;
$pos = strpos($data,"\r\n\r\n");
if($pos > 1){
$lb = "\r\n";
} else {
$pos = strpos($data,"\n\n");
if($pos > 1){
$lb = "\n";
}
}
// remove 100 header
if(isset($lb) && ereg('^HTTP/1.1 100',$data)){
unset($lb);
$data = '';
}//
}
// store header data
$this->incoming_payload .= $data;
$this->debug('found end of headers after length ' . strlen($data
));
// process headers
$header_data = trim(substr($data,0,$pos));
$header_array = explode($lb,$header_data);
$this->incoming_headers = array();
$this->incoming_cookies = array();
foreach($header_array as $header_line){
$arr = explode(':',$header_line, 2);
if(count($arr) > 1){
$header_name = strtolower(trim($arr[0]));
$this->incoming_headers[$header_name] = trim($ar
r[1]);
if ($header_name == 'set-cookie') {
// TODO: allow multiple cookies from par
seCookie
$cookie = $this->parseCookie(trim($arr[1
]));
if ($cookie) {
$this->incoming_cookies[] = $coo
kie;
$this->debug('found cookie: ' .
$cookie['name'] . ' = ' . $cookie['value']);
} else {
$this->debug('did not find cooki
e in ' . trim($arr[1]));
}
}
} else if (isset($header_name)) {
// append continuation line to previous header
$this->incoming_headers[$header_name] .= $lb . '
' . $header_line;
}
}
// loop until msg has been received
if (isset($this->incoming_headers['transfer-encoding']) && strto
lower($this->incoming_headers['transfer-encoding']) == 'chunked') {
$content_length = 2147483647; // ignore any content-le
ngth header
$chunked = true;
$this->debug("want to read chunked content");
} elseif (isset($this->incoming_headers['content-length'])) {
$content_length = $this->incoming_headers['content-lengt
h'];
$chunked = false;
$this->debug("want to read content of length $content_le
ngth");
} else {
$content_length = 2147483647;
$chunked = false;
$this->debug("want to read content to EOF");
}
$data = '';
do {
if ($chunked) {
$tmp = fgets($this->fp, 256);
$tmplen = strlen($tmp);
$this->debug("read chunk line of $tmplen bytes")
;
if ($tmplen == 0) {
$this->incoming_payload = $data;
$this->debug('socket read of chunk lengt
h timed out after length ' . strlen($data));
$this->debug("read before timeout:\n" .
$data);
$this->setError('socket read of chunk le
ngth timed out');
return false;
}
$content_length = hexdec(trim($tmp));
$this->debug("chunk length $content_length");
}
$strlen = 0;
while (($strlen < $content_length) && (!feof($this->fp))) {
$readlen = min(8192, $content_length - $strlen);
$tmp = fread($this->fp, $readlen);
$tmplen = strlen($tmp);
$this->debug("read buffer of $tmplen bytes");
if (($tmplen == 0) && (!feof($this->fp))) {
$this->incoming_payload = $data;
$this->debug('socket read of body timed
out after length ' . strlen($data));
$this->debug("read before timeout:\n" .
$data);
$this->setError('socket read of body tim
ed out');
return false;
}
$strlen += $tmplen;
$data .= $tmp;
}
if ($chunked && ($content_length > 0)) {
$tmp = fgets($this->fp, 256);
$tmplen = strlen($tmp);
$this->debug("read chunk terminator of $tmplen b
ytes");
if ($tmplen == 0) {
$this->incoming_payload = $data;
$this->debug('socket read of chunk termi
nator timed out after length ' . strlen($data));
$this->debug("read before timeout:\n" .
$data);
$this->setError('socket read of chunk te
rminator timed out');
return false;
}
}
} while ($chunked && ($content_length > 0) && (!feof($this->fp))
);
if (feof($this->fp)) {
$this->debug('read to EOF');
}
$this->debug('read body of length ' . strlen($data));
$this->incoming_payload .= $data;
$this->debug('received a total of '.strlen($this->incoming_paylo
ad).' bytes of data from server');
// close filepointer
if(
(isset($this->incoming_headers['connection']) && strtolo
wer($this->incoming_headers['connection']) == 'close') ||
(! $this->persistentConnection) || feof($this->fp)){
fclose($this->fp);
$this->fp = false;
$this->debug('closed socket');
}
// connection was closed unexpectedly
if($this->incoming_payload == ''){
$this->setError('no response from server');
return false;
}
// decode transfer-encoding
// if(isset($this->incoming_headers['transfer-encoding']) && strtol
ower($this->incoming_headers['transfer-encoding']) == 'chunked'){
// if(!$data = $this->decodeChunked($data, $lb)){
// $this->setError('Decoding of chunked data failed
');
// return false;
// }
//print "<pre>\nde-chunked:\n---------------\n$data\n\n-
--------------\n</pre>";
// set decoded payload
// $this->incoming_payload = $header_data.$lb.$lb.$data;
// }
} else if ($this->scheme == 'https') {
// send and receive
$this->debug('send and receive with cURL');
$this->incoming_payload = curl_exec($this->ch);
$data = $this->incoming_payload;
$cErr = curl_error($this->ch);
if ($cErr != '') {
$err = 'cURL ERROR: '.curl_errno($this->ch).': '.$cErr.'<br>';
// TODO: there is a PHP bug that can cause this to SEGV for CURL
INFO_CONTENT_TYPE
foreach(curl_getinfo($this->ch) as $k => $v){
$err .= "$k: $v<br>";
}
$this->debug($err);
$this->setError($err);
curl_close($this->ch);
return false;
} else {
//echo '<pre>';
//var_dump(curl_getinfo($this->ch));
//echo '</pre>';
}
// close curl
$this->debug('No cURL error, closing cURL');
curl_close($this->ch);
// remove 100 header(s)
while (ereg('^HTTP/1.1 100',$data)) {
if ($pos = strpos($data,"\r\n\r\n")) {
$data = ltrim(substr($data,$pos));
} elseif($pos = strpos($data,"\n\n") ) {
$data = ltrim(substr($data,$pos));
}
}
// separate content from HTTP headers
if ($pos = strpos($data,"\r\n\r\n")) {
$lb = "\r\n";
} elseif( $pos = strpos($data,"\n\n")) {
$lb = "\n";
} else {
$this->debug('no proper separation of headers and docume
nt');
$this->setError('no proper separation of headers and doc
ument');
return false;
}
$header_data = trim(substr($data,0,$pos));
$header_array = explode($lb,$header_data);
$data = ltrim(substr($data,$pos));
$this->debug('found proper separation of headers and document');
$this->debug('cleaned data, stringlen: '.strlen($data));
// clean headers
foreach ($header_array as $header_line) {
$arr = explode(':',$header_line,2);
if(count($arr) > 1){
$header_name = strtolower(trim($arr[0]));
$this->incoming_headers[$header_name] = trim($ar
r[1]);
if ($header_name == 'set-cookie') {
// TODO: allow multiple cookies from par
seCookie
$cookie = $this->parseCookie(trim($arr[1
]));
if ($cookie) {
$this->incoming_cookies[] = $coo
kie;
$this->debug('found cookie: ' .
$cookie['name'] . ' = ' . $cookie['value']);
} else {
$this->debug('did not find cooki
e in ' . trim($arr[1]));
}
}
} else if (isset($header_name)) {
// append continuation line to previous header
$this->incoming_headers[$header_name] .= $lb . '
' . $header_line;
}
}
}
$arr = explode(' ', $header_array[0], 3);
$http_version = $arr[0];
$http_status = intval($arr[1]);
$http_reason = count($arr) > 2 ? $arr[2] : '';
// see if we need to resend the request with http digest authent
ication
if (isset($this->incoming_headers['location']) && $http_status =
= 301) {
$this->debug("Got 301 $http_reason with Location: " . $t
his->incoming_headers['location']);
$this->setURL($this->incoming_headers['location']);
$this->tryagain = true;
return false;
}
// see if we need to resend the request with http digest authent
ication
if (isset($this->incoming_headers['www-authenticate']) && $http_
status == 401) {
$this->debug("Got 401 $http_reason with WWW-Authenticate
: " . $this->incoming_headers['www-authenticate']);
if (strstr($this->incoming_headers['www-authenticate'],
"Digest ")) {
$this->debug('Server wants digest authentication
');
// remove "Digest " from our elements
$digestString = str_replace('Digest ', '', $this
->incoming_headers['www-authenticate']);
// parse elements into array
$digestElements = explode(',', $digestString);
foreach ($digestElements as $val) {
$tempElement = explode('=', trim($val),
2);
$digestRequest[$tempElement[0]] = str_re
place("\"", '', $tempElement[1]);
}
// should have (at least) qop, realm, nonce
if (isset($digestRequest['nonce'])) {
$this->setCredentials($this->username, $
this->password, 'digest', $digestRequest);
$this->tryagain = true;
return false;
}
}
$this->debug('HTTP authentication failed');
$this->setError('HTTP authentication failed');
return false;
}
if (
($http_status >= 300 && $http_status <= 307) ||
($http_status >= 400 && $http_status <= 417) ||
($http_status >= 501 && $http_status <= 505)
) {
$this->setError("Unsupported HTTP response status $http_
status $http_reason (soapclient->response has contents of the response)");
return false;
}
// decode content-encoding
if(isset($this->incoming_headers['content-encoding']) && $this->
incoming_headers['content-encoding'] != ''){
if(strtolower($this->incoming_headers['content-encoding'
]) == 'deflate' || strtolower($this->incoming_headers['content-encoding']) == 'g
zip'){
// if decoding works, use it. else assume data wasn't gz
encoded
if(function_exists('gzinflate')){
//$timer->setMarker('starting decoding o
f gzip/deflated content');
// IIS 5 requires gzinflate instead of g
zuncompress (similar to IE 5 and gzdeflate v. gzcompress)
// this means there are no Zlib headers,
although there should be
$this->debug('The gzinflate function exi
sts');
$datalen = strlen($data);
if ($this->incoming_headers['content-enc
oding'] == 'deflate') {
if ($degzdata = @gzinflate($data
)) {
$data = $degzdata;
$this->debug('The payload has be
en inflated to ' . strlen($data) . ' bytes');
if (strlen($data) < $datalen) {
// test for the case tha
t the payload has been compressed twice
$this->debug('The inflat
ed payload is smaller than the gzipped one; try again');
if ($degzdata =
@gzinflate($data)) {
$data = $degzdat
a;
$this->debug('Th
e payload has been inflated again to ' . strlen($data) . ' bytes');
}
}
} else {
$this->debug('Error using gzinfl
ate to inflate the payload');
$this->setError('Error using gzi
nflate to inflate the payload');
}
} elseif ($this->incoming_headers['conte
nt-encoding'] == 'gzip') {
if ($degzdata = @gzinflate(subst
r($data, 10))) { // do our best
$data = $degzdata;
$this->debug('The payload has be
en un-gzipped to ' . strlen($data) . ' bytes');
if (strlen($data) < $datalen) {
// test for the case tha
t the payload has been compressed twice
$this->debug('The un-gzi
pped payload is smaller than the gzipped one; try again');
if ($degzdata =
@gzinflate(substr($data, 10))) {
$data = $degzdat
a;
$this->debug('Th
e payload has been un-gzipped again to ' . strlen($data) . ' bytes');
}
}
} else {
$this->debug('Error using gzinfl
ate to un-gzip the payload');
$this->setError('Error u
sing gzinflate to un-gzip the payload');
}
}
//$timer->setMarker('finished decoding o
f gzip/deflated content');
//print "<xmp>\nde-inflated:\n----------
-----\n$data\n-------------\n</xmp>";
// set decoded payload
$this->incoming_payload = $header_data.$
lb.$lb.$data;
} else {
$this->debug('The server sent compressed
data. Your php install must have the Zlib extension compiled in to support this
.');
$this->setError('The server sent compres
sed data. Your php install must have the Zlib extension compiled in to support t
his.');
}
} else {
$this->debug('Unsupported Content-Encoding ' . $
this->incoming_headers['content-encoding']);
$this->setError('Unsupported Content-Encoding '
. $this->incoming_headers['content-encoding']);
}
} else {
$this->debug('No Content-Encoding header');
}
if(strlen($data) == 0){
$this->debug('no data after headers!');
$this->setError('no data present after HTTP headers');
return false;
}
return $data;
}
function setContentType($type, $charset = false) {
$this->outgoing_headers['Content-Type'] = $type . ($charset ? ';
charset=' . $charset : '');
$this->debug('set Content-Type: ' . $this->outgoing_headers['Con
tent-Type']);
}
function usePersistentConnection(){
if (isset($this->outgoing_headers['Accept-Encoding'])) {
return false;
}
$this->protocol_version = '1.1';
$this->persistentConnection = true;
$this->outgoing_headers['Connection'] = 'Keep-Alive';
$this->debug('set Connection: ' . $this->outgoing_headers['Conne
ction']);
return true;
}
/**
* parse an incoming Cookie into it's parts
*
* @param string $cookie_str content of cookie
* @return array with data of that cookie
* @access private
*/
/*
* TODO: allow a Set-Cookie string to be parsed into multiple cookies
*/
function parseCookie($cookie_str) {
$cookie_str = str_replace('; ', ';', $cookie_str) . ';';
$data = split(';', $cookie_str);
$value_str = $data[0];
$cookie_param = 'domain=';
$start = strpos($cookie_str, $cookie_param);
if ($start > 0) {
$domain = substr($cookie_str, $start + strlen($cookie_pa
ram));
$domain = substr($domain, 0, strpos($domain, ';'));
} else {
$domain = '';
}
$cookie_param = 'expires=';
$start = strpos($cookie_str, $cookie_param);
if ($start > 0) {
$expires = substr($cookie_str, $start + strlen($cookie_p
aram));
$expires = substr($expires, 0, strpos($expires, ';'));
} else {
$expires = '';
}
$cookie_param = 'path=';
$start = strpos($cookie_str, $cookie_param);
if ( $start > 0 ) {
$path = substr($cookie_str, $start + strlen($cookie_para
m));
$path = substr($path, 0, strpos($path, ';'));
} else {
$path = '/';
}
$cookie_param = ';secure;';
if (strpos($cookie_str, $cookie_param) !== FALSE) {
$secure = true;
} else {
$secure = false;
}
$sep_pos = strpos($value_str, '=');
if ($sep_pos) {
$name = substr($value_str, 0, $sep_pos);
$value = substr($value_str, $sep_pos + 1);
$cookie= array( 'name' => $name,
'value' => $value,
'domain' => $domain,
'path' => $path,
'expires' => $expires,
'secure' => $secure
);
return $cookie;
}
return false;
}
/**
* sort out cookies for the current request
*
* @param array $cookies array with all cookies
* @param boolean $secure is the send-content secure or not?
* @return string for Cookie-HTTP-Header
* @access private
*/
function getCookiesForRequest($cookies, $secure=false) {
$cookie_str = '';
if ((! is_null($cookies)) && (is_array($cookies))) {
foreach ($cookies as $cookie) {
if (! is_array($cookie)) {
continue;
}
$this->debug("check cookie for validity: ".$cookie['name
'].'='.$cookie['value']);
if ((isset($cookie['expires'])) && (! empty($coo
kie['expires']))) {
if (strtotime($cookie['expires']) <= tim
e()) {
$this->debug('cookie has expired
');
continue;
}
}
if ((isset($cookie['domain'])) && (! empty($cook
ie['domain']))) {
$domain = preg_quote($cookie['domain']);
if (! preg_match("'.*$domain$'i", $this-
>host)) {
$this->debug('cookie has differe
nt domain');
continue;
}
}
if ((isset($cookie['path'])) && (! empty($cookie
['path']))) {
$path = preg_quote($cookie['path']);
if (! preg_match("'^$path.*'i", $this->p
ath)) {
$this->debug('cookie is for a di
fferent path');
continue;
}
}
if ((! $secure) && (isset($cookie['secure'])) &&
($cookie['secure'])) {
$this->debug('cookie is secure, transpor
t is not');
continue;
}
$cookie_str .= $cookie['name'] . '=' . $cookie['
value'] . '; ';
$this->debug('add cookie to Cookie-String: ' . $cookie['
name'] . '=' . $cookie['value']);
}
}
return $cookie_str;
}
}
?><?php

/**
*
* soap_server allows the user to create a SOAP server
* that is capable of receiving messages and returning responses
*
* NOTE: WSDL functionality is experimental
*
* @author Dietrich Ayala <[email protected]>
* @version $Id: nusoap.php,v 1.94 2005/08/04 01:27:42 snichol Exp $
* @access public
*/
class soap_server extends nusoap_base {
/**
* HTTP headers of request
* @var array
* @access private
*/
var $headers = array();
/**
* HTTP request
* @var string
* @access private
*/
var $request = '';
/**
* SOAP headers from request (incomplete namespace resolution; special c
haracters not escaped) (text)
* @var string
* @access public
*/
var $requestHeaders = '';
/**
* SOAP body request portion (incomplete namespace resolution; special c
haracters not escaped) (text)
* @var string
* @access public
*/
var $document = '';
/**
* SOAP payload for request (text)
* @var string
* @access public
*/
var $requestSOAP = '';
/**
* requested method namespace URI
* @var string
* @access private
*/
var $methodURI = '';
/**
* name of method requested
* @var string
* @access private
*/
var $methodname = '';
/**
* method parameters from request
* @var array
* @access private
*/
var $methodparams = array();
/**
* SOAP Action from request
* @var string
* @access private
*/
var $SOAPAction = '';
/**
* character set encoding of incoming (request) messages
* @var string
* @access public
*/
var $xml_encoding = '';
/**
* toggles whether the parser decodes element content w/ utf8_decode()
* @var boolean
* @access public
*/
var $decode_utf8 = true;
/**
* HTTP headers of response
* @var array
* @access public
*/
var $outgoing_headers = array();
/**
* HTTP response
* @var string
* @access private
*/
var $response = '';
/**
* SOAP headers for response (text)
* @var string
* @access public
*/
var $responseHeaders = '';
/**
* SOAP payload for response (text)
* @var string
* @access private
*/
var $responseSOAP = '';
/**
* method return value to place in response
* @var mixed
* @access private
*/
var $methodreturn = false;
/**
* whether $methodreturn is a string of literal XML
* @var boolean
* @access public
*/
var $methodreturnisliteralxml = false;
/**
* SOAP fault for response (or false)
* @var mixed
* @access private
*/
var $fault = false;
/**
* text indication of result (for debugging)
* @var string
* @access private
*/
var $result = 'successful';
/**
* assoc array of operations => opData; operations are added by the regi
ster()
* method or by parsing an external WSDL definition
* @var array
* @access private
*/
var $operations = array();
/**
* wsdl instance (if one)
* @var mixed
* @access private
*/
var $wsdl = false;
/**
* URL for WSDL (if one)
* @var mixed
* @access private
*/
var $externalWSDLURL = false;
/**
* whether to append debug to response as XML comment
* @var boolean
* @access public
*/
var $debug_flag = false;

/**
* constructor
* the optional parameter is a path to a WSDL file that you'd like to bind th
e server instance to.
*
* @param mixed $wsdl file path or URL (string), or wsdl instance (object)
* @access public
*/
function soap_server($wsdl=false){
parent::nusoap_base();
// turn on debugging?
global $debug;
global $HTTP_SERVER_VARS;
if (isset($_SERVER)) {
$this->debug("_SERVER is defined:");
$this->appendDebug($this->varDump($_SERVER));
} elseif (isset($HTTP_SERVER_VARS)) {
$this->debug("HTTP_SERVER_VARS is defined:");
$this->appendDebug($this->varDump($HTTP_SERVER_VARS));
} else {
$this->debug("Neither _SERVER nor HTTP_SERVER_VARS is de
fined.");
}
if (isset($debug)) {
$this->debug("In soap_server, set debug_flag=$debug base
d on global flag");
$this->debug_flag = $debug;
} elseif (isset($_SERVER['QUERY_STRING'])) {
$qs = explode('&', $_SERVER['QUERY_STRING']);
foreach ($qs as $v) {
if (substr($v, 0, 6) == 'debug=') {
$this->debug("In soap_server, set debug_
flag=" . substr($v, 6) . " based on query string #1");
$this->debug_flag = substr($v, 6);
}
}
} elseif (isset($HTTP_SERVER_VARS['QUERY_STRING'])) {
$qs = explode('&', $HTTP_SERVER_VARS['QUERY_STRING']);
foreach ($qs as $v) {
if (substr($v, 0, 6) == 'debug=') {
$this->debug("In soap_server, set debug_
flag=" . substr($v, 6) . " based on query string #2");
$this->debug_flag = substr($v, 6);
}
}
}
// wsdl
if($wsdl){
$this->debug("In soap_server, WSDL is specified");
if (is_object($wsdl) && (get_class($wsdl) == 'wsdl')) {
$this->wsdl = $wsdl;
$this->externalWSDLURL = $this->wsdl->wsdl;
$this->debug('Use existing wsdl instance from '
. $this->externalWSDLURL);
} else {
$this->debug('Create wsdl from ' . $wsdl);
$this->wsdl = new wsdl($wsdl);
$this->externalWSDLURL = $wsdl;
}
$this->appendDebug($this->wsdl->getDebug());
$this->wsdl->clearDebug();
if($err = $this->wsdl->getError()){
die('WSDL ERROR: '.$err);
}
}
}
/**
* processes request and returns response
*
* @param string $data usually is the value of $HTTP_RAW_POST_DATA
* @access public
*/
function service($data){
global $HTTP_SERVER_VARS;
if (isset($_SERVER['QUERY_STRING'])) {
$qs = $_SERVER['QUERY_STRING'];
} elseif (isset($HTTP_SERVER_VARS['QUERY_STRING'])) {
$qs = $HTTP_SERVER_VARS['QUERY_STRING'];
} else {
$qs = '';
}
$this->debug("In service, query string=$qs");
if (ereg('wsdl', $qs) ){
$this->debug("In service, this is a request for WSDL");
if($this->externalWSDLURL){
if (strpos($this->externalWSDLURL,"://")!==false) { // assume URL
header('Location: '.$this->externalWSDLURL);
} else { // assume file
header("Content-Type: text/xml\r\n");
$fp = fopen($this->externalWSDLURL, 'r');
fpassthru($fp);
}
} elseif ($this->wsdl) {
header("Content-Type: text/xml; charset=ISO-8859
-1\r\n");
print $this->wsdl->serialize($this->debug_flag);
if ($this->debug_flag) {
$this->debug('wsdl:');
$this->appendDebug($this->varDump($this-
>wsdl));
print $this->getDebugAsXMLComment();
}
} else {
header("Content-Type: text/html; charset=ISO-885
9-1\r\n");
print "This service does not provide WSDL";
}
} elseif ($data == '' && $this->wsdl) {
$this->debug("In service, there is no data, so return We
b description");
print $this->wsdl->webDescription();
} else {
$this->debug("In service, invoke the request");
$this->parse_request($data);
if (! $this->fault) {
$this->invoke_method();
}
if (! $this->fault) {
$this->serialize_return();
}
$this->send_response();
}
}
/**
* parses HTTP request headers.
*
* The following fields are set by this function (when successful)
*
* headers
* request
* xml_encoding
* SOAPAction
*
* @access private
*/
function parse_http_headers() {
global $HTTP_SERVER_VARS;
$this->request = '';
$this->SOAPAction = '';
if(function_exists('getallheaders')){
$this->debug("In parse_http_headers, use getallheaders")
;
$headers = getallheaders();
foreach($headers as $k=>$v){
$k = strtolower($k);
$this->headers[$k] = $v;
$this->request .= "$k: $v\r\n";
$this->debug("$k: $v");
}
// get SOAPAction header
if(isset($this->headers['soapaction'])){
$this->SOAPAction = str_replace('"','',$this->he
aders['soapaction']);
}
// get the character encoding of the incoming request
if(isset($this->headers['content-type']) && strpos($this
->headers['content-type'],'=')){
$enc = str_replace('"','',substr(strstr($this->h
eaders["content-type"],'='),1));
if(eregi('^(ISO-8859-1|US-ASCII|UTF-8)$',$enc)){
$this->xml_encoding = strtoupper($enc);
} else {
$this->xml_encoding = 'US-ASCII';
}
} else {
// should be US-ASCII for HTTP 1.0 or ISO-8859-1
for HTTP 1.1
$this->xml_encoding = 'ISO-8859-1';
}
} elseif(isset($_SERVER) && is_array($_SERVER)){
$this->debug("In parse_http_headers, use _SERVER");
foreach ($_SERVER as $k => $v) {
if (substr($k, 0, 5) == 'HTTP_') {
$k = str_replace(' ', '-', strtolower(st
r_replace('_', ' ', substr($k, 5))));
$k = strtolower(substr($k, 5));
} else {
$k = str_replace(' ', '-', strtolower(st
r_replace('_', ' ', $k))); $k = st
rtolower($k);
}
if ($k == 'soapaction') {
// get SOAPAction header
$k = 'SOAPAction';
$v = str_replace('"', '', $v);
$v = str_replace('\\', '', $v);
$this->SOAPAction = $v;
} else if ($k == 'content-type') {
// get the character encoding of the inc
oming request
if (strpos($v, '=')) {
$enc = substr(strstr($v, '='), 1
);
$enc = str_replace('"', '', $enc
);
$enc = str_replace('\\', '', $en
c);
if (eregi('^(ISO-8859-1|US-ASCII
|UTF-8)$', $enc)) {
$this->xml_encoding = st
rtoupper($enc);
} else {
$this->xml_encoding = 'U
S-ASCII';
}
} else {
// should be US-ASCII for HTTP 1
.0 or ISO-8859-1 for HTTP 1.1
$this->xml_encoding = 'ISO-8859-
1';
}
}
$this->headers[$k] = $v;
$this->request .= "$k: $v\r\n";
$this->debug("$k: $v");
}
} elseif (is_array($HTTP_SERVER_VARS)) {
$this->debug("In parse_http_headers, use HTTP_SERVER_VAR
S");
foreach ($HTTP_SERVER_VARS as $k => $v) {
if (substr($k, 0, 5) == 'HTTP_') {
$k = str_replace(' ', '-', strtolower(st
r_replace('_', ' ', substr($k, 5))));
$k = strtolower(substr($k, 5));
} else {
$k = str_replace(' ', '-', strtolower(st
r_replace('_', ' ', $k))); $k = st
rtolower($k);
}
if ($k == 'soapaction') {
// get SOAPAction header
$k = 'SOAPAction';
$v = str_replace('"', '', $v);
$v = str_replace('\\', '', $v);
$this->SOAPAction = $v;
} else if ($k == 'content-type') {
// get the character encoding of the inc
oming request
if (strpos($v, '=')) {
$enc = substr(strstr($v, '='), 1
);
$enc = str_replace('"', '', $enc
);
$enc = str_replace('\\', '', $en
c);
if (eregi('^(ISO-8859-1|US-ASCII
|UTF-8)$', $enc)) {
$this->xml_encoding = st
rtoupper($enc);
} else {
$this->xml_encoding = 'U
S-ASCII';
}
} else {
// should be US-ASCII for HTTP 1
.0 or ISO-8859-1 for HTTP 1.1
$this->xml_encoding = 'ISO-8859-
1';
}
}
$this->headers[$k] = $v;
$this->request .= "$k: $v\r\n";
$this->debug("$k: $v");
}
} else {
$this->debug("In parse_http_headers, HTTP headers not ac
cessible");
$this->setError("HTTP headers not accessible");
}
}
/**
* parses a request
*
* The following fields are set by this function (when successful)
*
* headers
* request
* xml_encoding
* SOAPAction
* request
* requestSOAP
* methodURI
* methodname
* methodparams
* requestHeaders
* document
*
* This sets the fault field on error
*
* @param string $data XML string
* @access private
*/
function parse_request($data='') {
$this->debug('entering parse_request()');
$this->parse_http_headers();
$this->debug('got character encoding: '.$this->xml_encoding);
// uncompress if necessary
if (isset($this->headers['content-encoding']) && $this->headers[
'content-encoding'] != '') {
$this->debug('got content encoding: ' . $this->headers['
content-encoding']);
if ($this->headers['content-encoding'] == 'deflate' || $
this->headers['content-encoding'] == 'gzip') {
// if decoding works, use it. else assume data wasn't gz
encoded
if (function_exists('gzuncompress')) {
if ($this->headers['content-encoding'] =
= 'deflate' && $degzdata = @gzuncompress($data)) {
$data = $degzdata;
} elseif ($this->headers['content-encodi
ng'] == 'gzip' && $degzdata = gzinflate(substr($data, 10))) {
$data = $degzdata;
} else {
$this->fault('Client', 'Errors o
ccurred when trying to decode the data');
return;
}
} else {
$this->fault('Client', 'This Server does
not support compressed data');
return;
}
}
}
$this->request .= "\r\n".$data;
$data = $this->parseRequest($this->headers, $data);
$this->requestSOAP = $data;
$this->debug('leaving parse_request');
}
/**
* invokes a PHP function for the requested SOAP method
*
* The following fields are set by this function (when successful)
*
* methodreturn
*
* Note that the PHP function that is called may also set the following
* fields to affect the response sent to the client
*
* responseHeaders
* outgoing_headers
*
* This sets the fault field on error
*
* @access private
*/
function invoke_method() {
$this->debug('in invoke_method, methodname=' . $this->methodname
. ' methodURI=' . $this->methodURI . ' SOAPAction=' . $this->SOAPAction);
if ($this->wsdl) {
if ($this->opData = $this->wsdl->getOperationData($this-
>methodname)) {
$this->debug('in invoke_method, found WSDL opera
tion=' . $this->methodname);
$this->appendDebug('opData=' . $this->varDump($t
his->opData));
} elseif ($this->opData = $this->wsdl->getOperationDataF
orSoapAction($this->SOAPAction)) {
// Note: hopefully this case will only be used f
or doc/lit, since rpc services should have wrapper element
$this->debug('in invoke_method, found WSDL soapA
ction=' . $this->SOAPAction . ' for operation=' . $this->opData['name']);
$this->appendDebug('opData=' . $this->varDump($t
his->opData));
$this->methodname = $this->opData['name'];
} else {
$this->debug('in invoke_method, no WSDL for oper
ation=' . $this->methodname);
$this->fault('Client', "Operation '" . $this->me
thodname . "' is not defined in the WSDL for this service");
return;
}
} else {
$this->debug('in invoke_method, no WSDL to validate meth
od');
}
// if a . is present in $this->methodname, we see if there is a
class in scope,
// which could be referred to. We will also distinguish between
two deliminators,
// to allow methods to be called a the class or an instance
$class = '';
$method = '';
if (strpos($this->methodname, '..') > 0) {
$delim = '..';
} else if (strpos($this->methodname, '.') > 0) {
$delim = '.';
} else {
$delim = '';
}
if (strlen($delim) > 0 && substr_count($this->methodname, $delim
) == 1 &&
class_exists(substr($this->methodname, 0, strpos($this->
methodname, $delim)))) {
// get the class and method name
$class = substr($this->methodname, 0, strpos($this->meth
odname, $delim));
$method = substr($this->methodname, strpos($this->method
name, $delim) + strlen($delim));
$this->debug("in invoke_method, class=$class method=$met
hod delim=$delim");
}
// does method exist?
if ($class == '') {
if (!function_exists($this->methodname)) {
$this->debug("in invoke_method, function '$this-
>methodname' not found!");
$this->result = 'fault: method not found';
$this->fault('Client',"method '$this->methodname
' not defined in service");
return;
}
} else {
$method_to_compare = (substr(phpversion(), 0, 2) == '4.'
) ? strtolower($method) : $method;
if (!in_array($method_to_compare, get_class_methods($cla
ss))) {
$this->debug("in invoke_method, method '$this->m
ethodname' not found in class '$class'!");
$this->result = 'fault: method not found';
$this->fault('Client',"method '$this->methodname
' not defined in service");
return;
}
}
// evaluate message, getting back parameters
// verify that request parameters match the method's signature
if(! $this->verify_method($this->methodname,$this->methodparams)
){
// debug
$this->debug('ERROR: request not verified against method
signature');
$this->result = 'fault: request failed validation agains
t method signature';
// return fault
$this->fault('Client',"Operation '$this->methodname' not
defined in service.");
return;
}
// if there are parameters to pass
$this->debug('in invoke_method, params:');
$this->appendDebug($this->varDump($this->methodparams));
$this->debug("in invoke_method, calling '$this->methodname'");
if (!function_exists('call_user_func_array')) {
if ($class == '') {
$this->debug('in invoke_method, calling function
using eval()');
$funcCall = "\$this->methodreturn = $this->metho
dname(";
} else {
if ($delim == '..') {
$this->debug('in invoke_method, calling
class method using eval()');
$funcCall = "\$this->methodreturn = ".$c
lass."::".$method."(";
} else {
$this->debug('in invoke_method, calling
instance method using eval()');
// generate unique instance name
$instname = "\$inst_".time();
$funcCall = $instname." = new ".$class."
(); ";
$funcCall .= "\$this->methodreturn = ".$
instname."->".$method."(";
}
}
if ($this->methodparams) {
foreach ($this->methodparams as $param) {
if (is_array($param)) {
$this->fault('Client', 'NuSOAP d
oes not handle complexType parameters correctly when using eval; call_user_func_
array must be available');
return;
}
$funcCall .= "\"$param\",";
}
$funcCall = substr($funcCall, 0, -1);
}
$funcCall .= ');';
$this->debug('in invoke_method, function call: '.$funcCa
ll);
@eval($funcCall);
} else {
if ($class == '') {
$this->debug('in invoke_method, calling function
using call_user_func_array()');
$call_arg = "$this->methodname"; // strai
ght assignment changes $this->methodname to lower case after call_user_func_arra
y()
} elseif ($delim == '..') {
$this->debug('in invoke_method, calling class me
thod using call_user_func_array()');
$call_arg = array ($class, $method);
} else {
$this->debug('in invoke_method, calling instance
method using call_user_func_array()');
$instance = new $class ();
$call_arg = array(&$instance, $method);
}
$this->methodreturn = call_user_func_array($call_arg, $t
his->methodparams);
}
$this->debug('in invoke_method, methodreturn:');
$this->appendDebug($this->varDump($this->methodreturn));
$this->debug("in invoke_method, called method $this->methodname,
received $this->methodreturn of type ".gettype($this->methodreturn));
}
/**
* serializes the return value from a PHP function into a full SOAP Envel
ope
*
* The following fields are set by this function (when successful)
*
* responseSOAP
*
* This sets the fault field on error
*
* @access private
*/
function serialize_return() {
$this->debug('Entering serialize_return methodname: ' . $this->m
ethodname . ' methodURI: ' . $this->methodURI);
// if fault
if (isset($this->methodreturn) && (get_class($this->methodreturn
) == 'soap_fault')) {
$this->debug('got a fault object from method');
$this->fault = $this->methodreturn;
return;
} elseif ($this->methodreturnisliteralxml) {
$return_val = $this->methodreturn;
// returned value(s)
} else {
$this->debug('got a(n) '.gettype($this->methodreturn).'
from method');
$this->debug('serializing return value');
if($this->wsdl){
// weak attempt at supporting multiple output pa
rams
if(sizeof($this->opData['output']['parts']) > 1)
{
$opParams = $this->methodreturn;
} else {
// TODO: is this really necessary?
$opParams = array($this->methodreturn);
}
$return_val = $this->wsdl->serializeRPCParameters($t
his->methodname,'output',$opParams);
$this->appendDebug($this->wsdl->getDebug());
$this->wsdl->clearDebug();
if($errstr = $this->wsdl->getError()){
$this->debug('got wsdl error: '.$errstr)
;
$this->fault('Server', 'unable to serial
ize result');
return;
}
} else {
if (isset($this->methodreturn)) {
$return_val = $this->serialize_val($this
->methodreturn, 'return');
} else {
$return_val = '';
$this->debug('in absence of WSDL, assume
void return for backward compatibility');
}
}
}
$this->debug('return value:');
$this->appendDebug($this->varDump($return_val));
$this->debug('serializing response');
if ($this->wsdl) {
$this->debug('have WSDL for serialization: style is ' .
$this->opData['style']);
if ($this->opData['style'] == 'rpc') {
$this->debug('style is rpc for serialization: us
e is ' . $this->opData['output']['use']);
if ($this->opData['output']['use'] == 'literal')
{
$payload = '<'.$this->methodname.'Respon
se xmlns="'.$this->methodURI.'">'.$return_val.'</'.$this->methodname."Response>"
;
} else {
$payload = '<ns1:'.$this->methodname.'Re
sponse xmlns:ns1="'.$this->methodURI.'">'.$return_val.'</ns1:'.$this->methodname
."Response>";
}
} else {
$this->debug('style is not rpc for serialization
: assume document');
$payload = $return_val;
}
} else {
$this->debug('do not have WSDL for serialization: assume
rpc/encoded');
$payload = '<ns1:'.$this->methodname.'Response xmlns:ns1
="'.$this->methodURI.'">'.$return_val.'</ns1:'.$this->methodname."Response>";
}
$this->result = 'successful';
if($this->wsdl){
//if($this->debug_flag){
$this->appendDebug($this->wsdl->getDebug());
// }
if (isset($opData['output']['encodingStyle'])) {
$encodingStyle = $opData['output']['encodingStyl
e'];
} else {
$encodingStyle = '';
}
// Added: In case we use a WSDL, return a serialized env
. WITH the usedNamespaces.
$this->responseSOAP = $this->serializeEnvelope($payload,
$this->responseHeaders,$this->wsdl->usedNamespaces,$this->opData['style'],$encod
ingStyle);
} else {
$this->responseSOAP = $this->serializeEnvelope($payload,
$this->responseHeaders);
}
$this->debug("Leaving serialize_return");
}
/**
* sends an HTTP response
*
* The following fields are set by this function (when successful)
*
* outgoing_headers
* response
*
* @access private
*/
function send_response() {
$this->debug('Enter send_response');
if ($this->fault) {
$payload = $this->fault->serialize();
$this->outgoing_headers[] = "HTTP/1.0 500 Internal Serve
r Error";
$this->outgoing_headers[] = "Status: 500 Internal Server
Error";
} else {
$payload = $this->responseSOAP;
// Some combinations of PHP+Web server allow the Status
// to come through as a header. Since OK is the default
// just do nothing.
// $this->outgoing_headers[] = "HTTP/1.0 200 OK";
// $this->outgoing_headers[] = "Status: 200 OK";
}
// add debug data if in debug mode
if(isset($this->debug_flag) && $this->debug_flag){
$payload .= $this->getDebugAsXMLComment();
}
$this->outgoing_headers[] = "Server: $this->title Server v$this-
>version";
ereg('\$Revisio' . 'n: ([^ ]+)', $this->revision, $rev);
$this->outgoing_headers[] = "X-SOAP-Server: $this->title/$this->
version (".$rev[1].")";
// Let the Web server decide about this
//$this->outgoing_headers[] = "Connection: Close\r\n";
$payload = $this->getHTTPBody($payload);
$type = $this->getHTTPContentType();
$charset = $this->getHTTPContentTypeCharset();
$this->outgoing_headers[] = "Content-Type: $type" . ($charset ?
'; charset=' . $charset : '');
//begin code to compress payload - by John
// NOTE: there is no way to know whether the Web server will als
o compress
// this data.
if (strlen($payload) > 1024 && isset($this->headers) && isset($t
his->headers['accept-encoding'])) {
if (strstr($this->headers['accept-encoding'], 'gzip')) {
if (function_exists('gzencode')) {
if (isset($this->debug_flag) && $this->d
ebug_flag) {
$payload .= "<!-- Content being
gzipped -->";
}
$this->outgoing_headers[] = "Content-Enc
oding: gzip";
$payload = gzencode($payload);
} else {
if (isset($this->debug_flag) && $this->d
ebug_flag) {
$payload .= "<!-- Content will n
ot be gzipped: no gzencode -->";
}
}
} elseif (strstr($this->headers['accept-encoding'], 'def
late')) {
// Note: MSIE requires gzdeflate output (no Zlib
header and checksum),
// instead of gzcompress output,
// which conflicts with HTTP 1.1 spec (http://ww
w.w3.org/Protocols/rfc2616/rfc2616-sec3.html#sec3.5)
if (function_exists('gzdeflate')) {
if (isset($this->debug_flag) && $this->d
ebug_flag) {
$payload .= "<!-- Content being
deflated -->";
}
$this->outgoing_headers[] = "Content-Enc
oding: deflate";
$payload = gzdeflate($payload);
} else {
if (isset($this->debug_flag) && $this->d
ebug_flag) {
$payload .= "<!-- Content will n
ot be deflated: no gzcompress -->";
}
}
}
}
//end code
$this->outgoing_headers[] = "Content-Length: ".strlen($payload);
reset($this->outgoing_headers);
foreach($this->outgoing_headers as $hdr){
header($hdr, false);
}
print $payload;
$this->response = join("\r\n",$this->outgoing_headers)."\r\n\r\n
".$payload;
}
/**
* takes the value that was created by parsing the request
* and compares to the method's signature, if available.
*
* @param string $operation The operation to be invoked
* @param array $request The array of parameter values
* @return boolean Whether the operation was found
* @access private
*/
function verify_method($operation,$request){
if(isset($this->wsdl) && is_object($this->wsdl)){
if($this->wsdl->getOperationData($operation)){
return true;
}
} elseif(isset($this->operations[$operation])){
return true;
}
return false;
}
/**
* processes SOAP message received from client
*
* @param array $headers The HTTP headers
* @param string $data unprocessed request data from cl
ient
* @return mixed value of the message, decoded into a PHP type
* @access private
*/
function parseRequest($headers, $data) {
$this->debug('Entering parseRequest() for data of length ' . str
len($data) . ' and type ' . $headers['content-type']);
if (!strstr($headers['content-type'], 'text/xml')) {
$this->setError('Request not of type text/xml');
return false;
}
if (strpos($headers['content-type'], '=')) {
$enc = str_replace('"', '', substr(strstr($headers["cont
ent-type"], '='), 1));
$this->debug('Got response encoding: ' . $enc);
if(eregi('^(ISO-8859-1|US-ASCII|UTF-8)$',$enc)){
$this->xml_encoding = strtoupper($enc);
} else {
$this->xml_encoding = 'US-ASCII';
}
} else {
// should be US-ASCII for HTTP 1.0 or ISO-8859-1 for HTT
P 1.1
$this->xml_encoding = 'ISO-8859-1';
}
$this->debug('Use encoding: ' . $this->xml_encoding . ' when cre
ating soap_parser');
// parse response, get soap parser obj
$parser = new soap_parser($data,$this->xml_encoding,'',$this->de
code_utf8);
// parser debug
$this->debug("parser debug: \n".$parser->getDebug());
// if fault occurred during message parsing
if($err = $parser->getError()){
$this->result = 'fault: error in msg parsing: '.$err;
$this->fault('Client',"error in msg parsing:\n".$err);
// else successfully parsed request into soapval object
} else {
// get/set methodname
$this->methodURI = $parser->root_struct_namespace;
$this->methodname = $parser->root_struct_name;
$this->debug('methodname: '.$this->methodname.' methodUR
I: '.$this->methodURI);
$this->debug('calling parser->get_response()');
$this->methodparams = $parser->get_response();
// get SOAP headers
$this->requestHeaders = $parser->getHeaders();
// add document for doclit support
$this->document = $parser->document;
}
}
/**
* gets the HTTP body for the current response.
*
* @param string $soapmsg The SOAP payload
* @return string The HTTP body, which includes the SOAP payload
* @access private
*/
function getHTTPBody($soapmsg) {
return $soapmsg;
}
/**
* gets the HTTP content type for the current response.
*
* Note: getHTTPBody must be called before this.
*
* @return string the HTTP content type for the current response.
* @access private
*/
function getHTTPContentType() {
return 'text/xml';
}
/**
* gets the HTTP content type charset for the current response.
* returns false for non-text content types.
*
* Note: getHTTPBody must be called before this.
*
* @return string the HTTP content type charset for the current response.
* @access private
*/
function getHTTPContentTypeCharset() {
return $this->soap_defencoding;
}
/**
* add a method to the dispatch map (this has been replaced by the regist
er method)
*
* @param string $methodname
* @param string $in array of input values
* @param string $out array of output values
* @access public
* @deprecated
*/
function add_to_map($methodname,$in,$out){
$this->operations[$methodname] = array('name' => $method
name,'in' => $in,'out' => $out);
}
/**
* register a service function with the server
*
* @param string $name the name of the PHP function, class.method or c
lass..method
* @param array $in assoc array of input values: key = param name, val
ue = param type
* @param array $out assoc array of output values: key = param name, v
alue = param type
* @param mixed $namespace the element namespace for the method or
false
* @param mixed $soapaction the soapaction for the method or false
* @param mixed $style optional (rpc|document) or false Note: when
'document' is specified, parameter and return wrappers are created for you auto
matically
* @param mixed $use optional (encoded|literal) or false
* @param string $documentation optional Description to include in
WSDL
* @param string $encodingStyle optional (usually 'http://schemas.
xmlsoap.org/soap/encoding/' for encoded)
* @access public
*/
function register($name,$in=array(),$out=array(),$namespace=false,$soapa
ction=false,$style=false,$use=false,$documentation='',$encodingStyle=''){
global $HTTP_SERVER_VARS;
if($this->externalWSDLURL){
die('You cannot bind to an external WSDL file, and regis
ter methods outside of it! Please choose either WSDL or no WSDL.');
}
if (! $name) {
die('You must specify a name when you register an operat
ion');
}
if (!is_array($in)) {
die('You must provide an array for operation inputs');
}
if (!is_array($out)) {
die('You must provide an array for operation outputs');
}
if(false == $namespace) {
}
if(false == $soapaction) {
if (isset($_SERVER)) {
$SERVER_NAME = $_SERVER['SERVER_NAME'];
$SCRIPT_NAME = isset($_SERVER['PHP_SELF']) ? $_S
ERVER['PHP_SELF'] : $_SERVER['SCRIPT_NAME'];
} elseif (isset($HTTP_SERVER_VARS)) {
$SERVER_NAME = $HTTP_SERVER_VARS['SERVER_NAME'];
$SCRIPT_NAME = isset($HTTP_SERVER_VARS['PHP_SELF
']) ? $HTTP_SERVER_VARS['PHP_SELF'] : $HTTP_SERVER_VARS['SCRIPT_NAME'];
} else {
$this->setError("Neither _SERVER nor HTTP_SERVER
_VARS is available");
}
$soapaction = "http://$SERVER_NAME$SCRIPT_NAME/$name";
}
if(false == $style) {
$style = "rpc";
}
if(false == $use) {
$use = "encoded";
}
if ($use == 'encoded' && $encodingStyle = '') {
$encodingStyle = 'http://schemas.xmlsoap.org/soap/encodi
ng/';
}
$this->operations[$name] = array(
'name' => $name,
'in' => $in,
'out' => $out,
'namespace' => $namespace,
'soapaction' => $soapaction,
'style' => $style);
if($this->wsdl){
$this->wsdl->addOperation($name,$in,$out,$namespace,$soapaction,
$style,$use,$documentation,$encodingStyle);
}
return true;
}
/**
* Specify a fault to be returned to the client.
* This also acts as a flag to the server that a fault has occured.
*
* @param string $faultcode
* @param string $faultstring
* @param string $faultactor
* @param string $faultdetail
* @access public
*/
function fault($faultcode,$faultstring,$faultactor='',$faultdetail=''){
if ($faultdetail == '' && $this->debug_flag) {
$faultdetail = $this->getDebug();
}
$this->fault = new soap_fault($faultcode,$faultactor,$faultstrin
g,$faultdetail);
$this->fault->soap_defencoding = $this->soap_defencoding;
}
/**
* Sets up wsdl object.
* Acts as a flag to enable internal WSDL generation
*
* @param string $serviceName, name of the service
* @param mixed $namespace optional 'tns' service namespace or false
* @param mixed $endpoint optional URL of service endpoint or false
* @param string $style optional (rpc|document) WSDL style (also specified by
operation)
* @param string $transport optional SOAP transport
* @param mixed $schemaTargetNamespace optional 'types' targetNamespace for s
ervice schema or false
*/
function configureWSDL($serviceName,$namespace = false,$endpoint = false,$st
yle='rpc', $transport = 'http://schemas.xmlsoap.org/soap/http', $schemaTargetNam
espace = false)
{
global $HTTP_SERVER_VARS;
if (isset($_SERVER)) {
$SERVER_NAME = $_SERVER['SERVER_NAME'];
$SERVER_PORT = $_SERVER['SERVER_PORT'];
$SCRIPT_NAME = isset($_SERVER['PHP_SELF']) ? $_SERVER['P
HP_SELF'] : $_SERVER['SCRIPT_NAME'];
$HTTPS = $_SERVER['HTTPS'];
} elseif (isset($HTTP_SERVER_VARS)) {
$SERVER_NAME = $HTTP_SERVER_VARS['SERVER_NAME'];
$SERVER_PORT = $HTTP_SERVER_VARS['SERVER_PORT'];
$SCRIPT_NAME = isset($HTTP_SERVER_VARS['PHP_SELF']) ? $H
TTP_SERVER_VARS['PHP_SELF'] : $HTTP_SERVER_VARS['SCRIPT_NAME'];
$HTTPS = $HTTP_SERVER_VARS['HTTPS'];
} else {
$this->setError("Neither _SERVER nor HTTP_SERVER_VARS is
available");
}
if ($SERVER_PORT == 80) {
$SERVER_PORT = '';
} else {
$SERVER_PORT = ':' . $SERVER_PORT;
}
if(false == $namespace) {
$namespace = "http://$SERVER_NAME/soap/$serviceName";
}
if(false == $endpoint) {
if ($HTTPS == '1' || $HTTPS == 'on') {
$SCHEME = 'https';
} else {
$SCHEME = 'http';
}
$endpoint = "$SCHEME://$SERVER_NAME$SERVER_PORT$SCRIPT_NAME";
}
if(false == $schemaTargetNamespace) {
$schemaTargetNamespace = $namespace;
}
$this->wsdl = new wsdl;
$this->wsdl->serviceName = $serviceName;
$this->wsdl->endpoint = $endpoint;
$this->wsdl->namespaces['tns'] = $namespace;
$this->wsdl->namespaces['soap'] = 'http://schemas.xmlsoap.org/ws
dl/soap/';
$this->wsdl->namespaces['wsdl'] = 'http://schemas.xmlsoap.org/ws
dl/';
if ($schemaTargetNamespace != $namespace) {
$this->wsdl->namespaces['types'] = $schemaTargetNamespac
e;
}
$this->wsdl->schemas[$schemaTargetNamespace][0] = new xmlschema('', '',
$this->wsdl->namespaces);
$this->wsdl->schemas[$schemaTargetNamespace][0]->schemaTargetNamespace =
$schemaTargetNamespace;
$this->wsdl->schemas[$schemaTargetNamespace][0]->imports['http://schemas
.xmlsoap.org/soap/encoding/'][0] = array('location' => '', 'loaded' => true);
$this->wsdl->schemas[$schemaTargetNamespace][0]->imports['http://schemas
.xmlsoap.org/wsdl/'][0] = array('location' => '', 'loaded' => true);
$this->wsdl->bindings[$serviceName.'Binding'] = array(
'name'=>$serviceName.'Binding',
'style'=>$style,
'transport'=>$transport,
'portType'=>$serviceName.'PortType');
$this->wsdl->ports[$serviceName.'Port'] = array(
'binding'=>$serviceName.'Binding',
'location'=>$endpoint,
'bindingType'=>'http://schemas.xmlsoap.org/wsdl/soap/');
}
}

?><?php

/**
* parses a WSDL file, allows access to it's data, other utility methods
*
* @author Dietrich Ayala <[email protected]>
* @version $Id: nusoap.php,v 1.94 2005/08/04 01:27:42 snichol Exp $
* @access public
*/
class wsdl extends nusoap_base {
// URL or filename of the root of this WSDL
var $wsdl;
// define internal arrays of bindings, ports, operations, messages, etc.
var $schemas = array();
var $currentSchema;
var $message = array();
var $complexTypes = array();
var $messages = array();
var $currentMessage;
var $currentOperation;
var $portTypes = array();
var $currentPortType;
var $bindings = array();
var $currentBinding;
var $ports = array();
var $currentPort;
var $opData = array();
var $status = '';
var $documentation = false;
var $endpoint = '';
// array of wsdl docs to import
var $import = array();
// parser vars
var $parser;
var $position = 0;
var $depth = 0;
var $depth_array = array();
// for getting wsdl
var $proxyhost = '';
var $proxyport = '';
var $proxyusername = '';
var $proxypassword = '';
var $timeout = 0;
var $response_timeout = 30;
/**
* constructor
*
* @param string $wsdl WSDL document URL
* @param string $proxyhost
* @param string $proxyport
* @param string $proxyusername
* @param string $proxypassword
* @param integer $timeout set the connection timeout
* @param integer $response_timeout set the response timeout
* @access public
*/
function wsdl($wsdl = '',$proxyhost=false,$proxyport=false,$proxyusername=fa
lse,$proxypassword=false,$timeout=0,$response_timeout=30){
parent::nusoap_base();
$this->wsdl = $wsdl;
$this->proxyhost = $proxyhost;
$this->proxyport = $proxyport;
$this->proxyusername = $proxyusername;
$this->proxypassword = $proxypassword;
$this->timeout = $timeout;
$this->response_timeout = $response_timeout;

// parse wsdl file


if ($wsdl != "") {
$this->debug('initial wsdl URL: ' . $wsdl);
$this->parseWSDL($wsdl);
}
// imports
// TODO: handle imports more properly, grabbing them in-line and nesting
them
$imported_urls = array();
$imported = 1;
while ($imported > 0) {
$imported = 0;
// Schema imports
foreach ($this->schemas as $ns => $list) {
foreach ($list as $xs) {
$wsdlparts = parse_url($this->ws
dl); // this is bogusly simple!
foreach ($xs->imports as $ns2 => $list2) {
for ($ii = 0; $ii < count($list2); $ii++
) {
if (! $list2[$ii]['loaded']) {
$this->schemas[$ns]->imp
orts[$ns2][$ii]['loaded'] = true;
$url = $list2[$ii]['loca
tion'];
if ($url
!= '') {
$urlparts = parse_url($url);
if (!isset($urlparts['host'])) {
$url = $wsdlparts['scheme'] . '://' . $wsdlparts['host'] . (isset($wsdlparts['po
rt']) ? ':' .$wsdlparts['port'] : '') .
substr($wsdlparts['path'],0,strrpos($wsdlparts['path'],'/') + 1) .$urlparts['pat
h'];
}
if (! in_array($url, $imported_urls)) {
$this->p
arseWSDL($url);
$importe
d++;
$importe
d_urls[] = $url;
}
} else {
$this->debug("Unexpected scenario: empty URL for unloaded import");
}
}
}
}
}
}
// WSDL imports
$wsdlparts = parse_url($this->wsdl); // this
is bogusly simple!
foreach ($this->import as $ns => $list) {
for ($ii = 0; $ii < count($list); $ii++) {
if (! $list[$ii]['loaded']) {
$this->import[$ns][$ii]['loaded'] = true
;
$url = $list[$ii]['location'];
if ($url != '') {
$urlparts = pars
e_url($url);
if (!isset($urlp
arts['host'])) {
$url = $
wsdlparts['scheme'] . '://' . $wsdlparts['host'] . (isset($wsdlparts['port']) ?
':' . $wsdlparts['port'] : '') .
substr($wsdlparts['path'],0,strrpos($wsdlparts['path'],'/') + 1) .$urlparts['pat
h'];
}
if (! in_array($
url, $imported_urls)) {
$this->parseWSDL($url);
$imported++;
$imported_urls[] = $url;
}
} else {
$this->debug("Un
expected scenario: empty URL for unloaded import");
}
}
}
}
}
// add new data to operation data
foreach($this->bindings as $binding => $bindingData) {
if (isset($bindingData['operations']) && is_array($bindingData['oper
ations'])) {
foreach($bindingData['operations'] as $operation => $data) {
$this->debug('post-parse data gathering for ' . $operation);
$this->bindings[$binding]['operations'][$operation]['input']
=
isset($this->bindings[$binding][
'operations'][$operation]['input']) ?
array_merge($this->bindings[$bin
ding]['operations'][$operation]['input'], $this->portTypes[ $bindingData['portTy
pe'] ][$operation]['input']) :
$this->portTypes[ $bindingData['
portType'] ][$operation]['input'];
$this->bindings[$binding]['operations'][$operation]['output'
] =
isset($this->bindings[$binding][
'operations'][$operation]['output']) ?
array_merge($this->bindings[$bin
ding]['operations'][$operation]['output'], $this->portTypes[ $bindingData['portT
ype'] ][$operation]['output']) :
$this->portTypes[ $bindingData['
portType'] ][$operation]['output'];
if(isset($this->messages[ $this->bindings[$binding]['operati
ons'][$operation]['input']['message'] ])){
$this->bindings[$binding]['opera
tions'][$operation]['input']['parts'] = $this->messages[ $this->bindings[$bindin
g]['operations'][$operation]['input']['message'] ];
}
if(isset($this->messages[ $this->binding
s[$binding]['operations'][$operation]['output']['message'] ])){
$this->bindings[$binding]['operations'][$operati
on]['output']['parts'] = $this->messages[ $this->bindings[$binding]['operations'
][$operation]['output']['message'] ];
}
if (isset($bindingData['style'])) {
$this->bindings[$binding]['operations'][$operation]['sty
le'] = $bindingData['style'];
}
$this->bindings[$binding]['operations'][$operation]['transpo
rt'] = isset($bindingData['transport']) ? $bindingData['transport'] : '';
$this->bindings[$binding]['operations'][$operation]['documen
tation'] = isset($this->portTypes[ $bindingData['portType'] ][$operation]['docum
entation']) ? $this->portTypes[ $bindingData['portType'] ][$operation]['document
ation'] : '';
$this->bindings[$binding]['operations'][$operation]['endpoin
t'] = isset($bindingData['endpoint']) ? $bindingData['endpoint'] : '';
}
}
}
}
/**
* parses the wsdl document
*
* @param string $wsdl path or URL
* @access private
*/
function parseWSDL($wsdl = '')
{
if ($wsdl == '') {
$this->debug('no wsdl passed to parseWSDL()!!');
$this->setError('no wsdl passed to parseWSDL()!!');
return false;
}
// parse $wsdl for url format
$wsdl_props = parse_url($wsdl);
if (isset($wsdl_props['scheme']) && ($wsdl_props['scheme'] == 'http' ||
$wsdl_props['scheme'] == 'https')) {
$this->debug('getting WSDL http(s) URL ' . $wsdl);
// get wsdl
$tr = new soap_transport_http($wsdl);
$tr->request_method = 'GET';
$tr->useSOAPAction = false;
if($this->proxyhost && $this->proxyport){
$tr->setProxy($this->proxyhost,$this->proxyport,
$this->proxyusername,$this->proxypassword);
}
$tr->setEncoding('gzip, deflate');
$wsdl_string = $tr->send('', $this->timeout, $this->resp
onse_timeout);
//$this->debug("WSDL request\n" . $tr->outgoing_payload)
;
//$this->debug("WSDL response\n" . $tr->incoming_payload
);
$this->appendDebug($tr->getDebug());
// catch errors
if($err = $tr->getError() ){
$errstr = 'HTTP ERROR: '.$err;
$this->debug($errstr);
$this->setError($errstr);
unset($tr);
return false;
}
unset($tr);
$this->debug("got WSDL URL");
} else {
// $wsdl is not http(s), so treat it as a file URL or plain file pat
h
if (isset($wsdl_props['scheme']) && ($wsdl_props['scheme'] == 'f
ile') && isset($wsdl_props['path'])) {
$path = isset($wsdl_props['host']) ? ($wsdl_props['host'
] . ':' . $wsdl_props['path']) : $wsdl_props['path'];
} else {
$path = $wsdl;
}
$this->debug('getting WSDL file ' . $path);
if ($fp = @fopen($path, 'r')) {
$wsdl_string = '';
while ($data = fread($fp, 32768)) {
$wsdl_string .= $data;
}
fclose($fp);
} else {
$errstr = "Bad path to WSDL file $path";
$this->debug($errstr);
$this->setError($errstr);
return false;
}
}
$this->debug('Parse WSDL');
// end new code added
// Create an XML parser.
$this->parser = xml_parser_create();
// Set the options for parsing the XML data.
// xml_parser_set_option($parser, XML_OPTION_SKIP_WHITE, 1);
xml_parser_set_option($this->parser, XML_OPTION_CASE_FOLDING, 0);
// Set the object for the parser.
xml_set_object($this->parser, $this);
// Set the element handlers for the parser.
xml_set_element_handler($this->parser, 'start_element', 'end_element');
xml_set_character_data_handler($this->parser, 'character_data');
// Parse the XML file.
if (!xml_parse($this->parser, $wsdl_string, true)) {
// Display an error message.
$errstr = sprintf(
'XML error parsing WSDL from %s on line %d: %s',
$wsdl,
xml_get_current_line_number($this->parser),
xml_error_string(xml_get_error_code($this->parser))
);
$this->debug($errstr);
$this->debug("XML payload:\n" . $wsdl_string);
$this->setError($errstr);
return false;
}
// free the parser
xml_parser_free($this->parser);
$this->debug('Parsing WSDL done');
// catch wsdl parse errors
if($this->getError()){
return false;
}
return true;
}
/**
* start-element handler
*
* @param string $parser XML parser object
* @param string $name element name
* @param string $attrs associative array of attributes
* @access private
*/
function start_element($parser, $name, $attrs)
{
if ($this->status == 'schema') {
$this->currentSchema->schemaStartElement($parser, $name, $attrs);
$this->appendDebug($this->currentSchema->getDebug());
$this->currentSchema->clearDebug();
} elseif (ereg('schema$', $name)) {
$this->debug('Parsing WSDL schema');
// $this->debug("startElement for $name ($attrs[name]). status = $th
is->status (".$this->getLocalPart($name).")");
$this->status = 'schema';
$this->currentSchema = new xmlschema('', '', $this->namespaces);
$this->currentSchema->schemaStartElement($parser, $name, $attrs);
$this->appendDebug($this->currentSchema->getDebug());
$this->currentSchema->clearDebug();
} else {
// position in the total number of elements, starting from 0
$pos = $this->position++;
$depth = $this->depth++;
// set self as current value for this depth
$this->depth_array[$depth] = $pos;
$this->message[$pos] = array('cdata' => '');
// process attributes
if (count($attrs) > 0) {
// register namespace declarations
foreach($attrs as $k => $v) {
if (ereg("^xmlns", $k)) {
if ($ns_prefix = substr(strrchr($k, ':'), 1)) {
$this->namespaces[$ns_prefix] = $v;
} else {
$this->namespaces['ns' . (count($this->namespaces) +
1)] = $v;
}
if ($v == 'http://www.w3.org/2001/XMLSchema' || $v == 'h
ttp://www.w3.org/1999/XMLSchema' || $v == 'http://www.w3.org/2000/10/XMLSchema')
{
$this->XMLSchemaVersion = $v;
$this->namespaces['xsi'] = $v . '-instance';
}
}
}
// expand each attribute prefix to its namespace
foreach($attrs as $k => $v) {
$k = strpos($k, ':') ? $this->expandQname($k) : $k;
if ($k != 'location' && $k != 'soapAction' && $k != 'namespa
ce') {
$v = strpos($v, ':') ? $this->expandQname($v) : $v;
}
$eAttrs[$k] = $v;
}
$attrs = $eAttrs;
} else {
$attrs = array();
}
// get element prefix, namespace and name
if (ereg(':', $name)) {
// get ns prefix
$prefix = substr($name, 0, strpos($name, ':'));
// get ns
$namespace = isset($this->namespaces[$prefix]) ? $this->namespac
es[$prefix] : '';
// get unqualified name
$name = substr(strstr($name, ':'), 1);
}
// process attributes, expanding any prefixes to namespa
ces
// find status, register data
switch ($this->status) {
case 'message':
if ($name == 'part') {
if (isset($attrs['type'])) {
$this->debug("msg " . $this->currentMessage
. ": found part $attrs[name]: " . implode(',', $attrs));
$this->messages[$this->currentMessage][$attr
s['name']] = $attrs['type'];
}
if (isset($attrs['element'])) {
$this->debug("msg " . $this->currentMessage
. ": found part $attrs[name]: " . implode(',', $attrs));
$this->messages[$this->currentMessage][$
attrs['name']] = $attrs['element'];
}
}
break;
case 'portType':
switch ($name) {
case 'operation':
$this->currentPortOperation = $attrs['na
me'];
$this->debug("portType $this->currentPor
tType operation: $this->currentPortOperation");
if (isset($attrs['parameterOrder'])) {
$this->portTypes[$this->currentP
ortType][$attrs['name']]['parameterOrder'] = $attrs['parameterOrder'];
}
break;
case 'documentation':
$this->documentation = true;
break;
// merge input/output data
default:
$m = isset($attrs['message']) ?
$this->getLocalPart($attrs['message']) : '';
$this->portTypes[$this->currentP
ortType][$this->currentPortOperation][$name]['message'] = $m;
break;
}
break;
case 'binding':
switch ($name) {
case 'binding':
// get ns prefix
if (isset($attrs['style'])) {
$this->bindings[$this->currentBindin
g]['prefix'] = $prefix;
}
$this->bindings[$this->currentBi
nding] = array_merge($this->bindings[$this->currentBinding], $attrs);
break;
case 'header':
$this->bindings[$this->curre
ntBinding]['operations'][$this->currentOperation][$this->opStatus]['headers'][]
= $attrs;
break;
case 'operation':
if (isset($attrs['soapAction
'])) {
$this->bindings[$this->c
urrentBinding]['operations'][$this->currentOperation]['soapAction'] = $attrs['so
apAction'];
}
if (isset($attrs['style']))
{
$this->bindings[$this->c
urrentBinding]['operations'][$this->currentOperation]['style'] = $attrs['style']
;
}
if (isset($attrs['name'])) {
$this->currentOperation
= $attrs['name'];
$this->debug("current bi
nding operation: $this->currentOperation");
$this->bindings[$this->c
urrentBinding]['operations'][$this->currentOperation]['name'] = $attrs['name'];
$this->bindings[$this->c
urrentBinding]['operations'][$this->currentOperation]['binding'] = $this->curren
tBinding;
$this->bindings[$this->c
urrentBinding]['operations'][$this->currentOperation]['endpoint'] = isset($this-
>bindings[$this->currentBinding]['endpoint']) ? $this->bindings[$this->currentBi
nding]['endpoint'] : '';
}
break;
case 'input':
$this->opStatus = 'input';
break;
case 'output':
$this->opStatus = 'output';
break;
case 'body':
if (isset($this->bindings[$t
his->currentBinding]['operations'][$this->currentOperation][$this->opStatus])) {
$this->bindings[$this->c
urrentBinding]['operations'][$this->currentOperation][$this->opStatus] = array_m
erge($this->bindings[$this->currentBinding]['operations'][$this->currentOperatio
n][$this->opStatus], $attrs);
} else {
$this->bindings[$this->c
urrentBinding]['operations'][$this->currentOperation][$this->opStatus] = $attrs;
}
break;
}
break;
case 'service':
switch ($name) {
case 'port':
$this->currentPort = $attrs['nam
e'];
$this->debug('current port: ' .
$this->currentPort);
$this->ports[$this->currentPort]
['binding'] = $this->getLocalPart($attrs['binding']);
break;
case 'address':
$this->ports[$this->currentPort]
['location'] = $attrs['location'];
$this->ports[$this->currentPort]
['bindingType'] = $namespace;
$this->bindings[ $this->ports[$t
his->currentPort]['binding'] ]['bindingType'] = $namespace;
$this->bindings[ $this->ports[$t
his->currentPort]['binding'] ]['endpoint'] = $attrs['location'];
break;
}
break;
}
// set status
switch ($name) {
case 'import':
if (isset($attrs['location'])) {
$this->import[$attrs['namespace']][] = array('location' => $
attrs['location'], 'loaded' => false);
$this->debug('parsing import ' . $attrs['namespace']. ' - '
. $attrs['location'] . ' (' . count($this->import[$attrs['namespace']]).')');
} else {
$this->import[$attrs['namespace']][] = array('location' => '
', 'loaded' => true);
if (! $this->getPrefixFromNamespace($att
rs['namespace'])) {
$this->namespaces['ns'.(count($t
his->namespaces)+1)] = $attrs['namespace'];
}
$this->debug('parsing import ' . $attrs['namespace']. ' - [n
o location] (' . count($this->import[$attrs['namespace']]).')');
}
break;
//wait for schema
//case 'types':
// $this->status = 'schema';
// break;
case 'message':
$this->status = 'message';
$this->messages[$attrs['name']] = array();
$this->currentMessage = $attrs['name'];
break;
case 'portType':
$this->status = 'portType';
$this->portTypes[$attrs['name']] = array();
$this->currentPortType = $attrs['name'];
break;
case "binding":
if (isset($attrs['name'])) {
// get binding name
if (strpos($attrs['name'], ':')) {
$this->currentBinding = $this->getLocalP
art($attrs['name']);
} else {
$this->currentBinding = $attrs['name'];
}
$this->status = 'binding';
$this->bindings[$this->currentBinding]['
portType'] = $this->getLocalPart($attrs['type']);
$this->debug("current binding: $this->cu
rrentBinding of portType: " . $attrs['type']);
}
break;
case 'service':
$this->serviceName = $attrs['name'];
$this->status = 'service';
$this->debug('current service: ' . $this->servic
eName);
break;
case 'definitions':
foreach ($attrs as $name => $value) {
$this->wsdl_info[$name] = $value;
}
break;
}
}
}
/**
* end-element handler
*
* @param string $parser XML parser object
* @param string $name element name
* @access private
*/
function end_element($parser, $name){
// unset schema status
if (/*ereg('types$', $name) ||*/ ereg('schema$', $name)) {
$this->status = "";
$this->appendDebug($this->currentSchema->getDebug());
$this->currentSchema->clearDebug();
$this->schemas[$this->currentSchema->schemaTargetNamespa
ce][] = $this->currentSchema;
$this->debug('Parsing WSDL schema done');
}
if ($this->status == 'schema') {
$this->currentSchema->schemaEndElement($parser, $name);
} else {
// bring depth down a notch
$this->depth--;
}
// end documentation
if ($this->documentation) {
//TODO: track the node to which documentation should be
assigned; it can be a part, message, etc.
//$this->portTypes[$this->currentPortType][$this->curren
tPortOperation]['documentation'] = $this->documentation;
$this->documentation = false;
}
}
/**
* element content handler
*
* @param string $parser XML parser object
* @param string $data element content
* @access private
*/
function character_data($parser, $data)
{
$pos = isset($this->depth_array[$this->depth]) ? $this->depth_ar
ray[$this->depth] : 0;
if (isset($this->message[$pos]['cdata'])) {
$this->message[$pos]['cdata'] .= $data;
}
if ($this->documentation) {
$this->documentation .= $data;
}
}
function getBindingData($binding)
{
if (is_array($this->bindings[$binding])) {
return $this->bindings[$binding];
}
}
/**
* returns an assoc array of operation names => operation data
*
* @param string $bindingType eg: soap, smtp, dime (only soap is current
ly supported)
* @return array
* @access public
*/
function getOperations($bindingType = 'soap')
{
$ops = array();
if ($bindingType == 'soap') {
$bindingType = 'http://schemas.xmlsoap.org/wsdl/soap/';
}
// loop thru ports
foreach($this->ports as $port => $portData) {
// binding type of port matches parameter
if ($portData['bindingType'] == $bindingType) {
//$this->debug("getOperations for port $port");
//$this->debug("port data: " . $this->varDump($p
ortData));
//$this->debug("bindings: " . $this->varDump($th
is->bindings[ $portData['binding'] ]));
// merge bindings
if (isset($this->bindings[ $portData['binding']
]['operations'])) {
$ops = array_merge ($ops, $this->binding
s[ $portData['binding'] ]['operations']);
}
}
}
return $ops;
}
/**
* returns an associative array of data necessary for calling an operati
on
*
* @param string $operation , name of operation
* @param string $bindingType , type of binding eg: soap
* @return array
* @access public
*/
function getOperationData($operation, $bindingType = 'soap')
{
if ($bindingType == 'soap') {
$bindingType = 'http://schemas.xmlsoap.org/wsdl/soap/';
}
// loop thru ports
foreach($this->ports as $port => $portData) {
// binding type of port matches parameter
if ($portData['bindingType'] == $bindingType) {
// get binding
//foreach($this->bindings[ $portData['binding']
]['operations'] as $bOperation => $opData) {
foreach(array_keys($this->bindings[ $portData['b
inding'] ]['operations']) as $bOperation) {
// note that we could/should also check
the namespace here
if ($operation == $bOperation) {
$opData = $this->bindings[ $port
Data['binding'] ]['operations'][$operation];
return $opData;
}
}
}
}
}
/**
* returns an associative array of data necessary for calling an operati
on
*
* @param string $soapAction soapAction for operation
* @param string $bindingType type of binding eg: soap
* @return array
* @access public
*/
function getOperationDataForSoapAction($soapAction, $bindingType = 'soap
') {
if ($bindingType == 'soap') {
$bindingType = 'http://schemas.xmlsoap.org/wsdl/soap/';
}
// loop thru ports
foreach($this->ports as $port => $portData) {
// binding type of port matches parameter
if ($portData['bindingType'] == $bindingType) {
// loop through operations for the binding
foreach ($this->bindings[ $portData['binding'] ]
['operations'] as $bOperation => $opData) {
if ($opData['soapAction'] == $soapAction
) {
return $opData;
}
}
}
}
}
/**
* returns an array of information about a given type
* returns false if no type exists by the given name
*
* typeDef = array(
* 'elements' => array(), // refs to elements array
* 'restrictionBase' => '',
* 'phpType' => '',
* 'order' => '(sequence|all)',
* 'attrs' => array() // refs to attributes array
* )
*
* @param $type string the type
* @param $ns string namespace (not prefix) of the type
* @return mixed
* @access public
* @see xmlschema
*/
function getTypeDef($type, $ns) {
$this->debug("in getTypeDef: type=$type, ns=$ns");
if ((! $ns) && isset($this->namespaces['tns'])) {
$ns = $this->namespaces['tns'];
$this->debug("in getTypeDef: type namespace forced to $n
s");
}
if (isset($this->schemas[$ns])) {
$this->debug("in getTypeDef: have schema for namespace $
ns");
for ($i = 0; $i < count($this->schemas[$ns]); $i++) {
$xs = &$this->schemas[$ns][$i];
$t = $xs->getTypeDef($type);
$this->appendDebug($xs->getDebug());
$xs->clearDebug();
if ($t) {
if (!isset($t['phpType'])) {
// get info for type to tack ont
o the element
$uqType = substr($t['type'], str
rpos($t['type'], ':') + 1);
$ns = substr($t['type'], 0, strr
pos($t['type'], ':'));
$etype = $this->getTypeDef($uqTy
pe, $ns);
if ($etype) {
$this->debug("found type
for [element] $type:");
$this->debug($this->varD
ump($etype));
if (isset($etype['phpTyp
e'])) {
$t['phpType'] =
$etype['phpType'];
}
if (isset($etype['elemen
ts'])) {
$t['elements'] =
$etype['elements'];
}
if (isset($etype['attrs'
])) {
$t['attrs'] = $e
type['attrs'];
}
}
}
return $t;
}
}
} else {
$this->debug("in getTypeDef: do not have schema for name
space $ns");
}
return false;
}
/**
* prints html description of services
*
* @access private
*/
function webDescription(){
global $HTTP_SERVER_VARS;
if (isset($_SERVER)) {
$PHP_SELF = $_SERVER['PHP_SELF'];
} elseif (isset($HTTP_SERVER_VARS)) {
$PHP_SELF = $HTTP_SERVER_VARS['PHP_SELF'];
} else {
$this->setError("Neither _SERVER nor HTTP_SERVER_VARS is
available");
}
$b = '
<html><head><title>NuSOAP: '.$this->serviceName.'</title>
<style type="text/css">
body { font-family: arial; color: #000000; background-col
or: #ffffff; margin: 0px 0px 0px 0px; }
p { font-family: arial; color: #000000; margin-top: 0p
x; margin-bottom: 12px; }
pre { background-color: silver; padding: 5px; font-family: C
ourier New; font-size: x-small; color: #000000;}
ul { margin-top: 10px; margin-left: 20px; }
li { list-style-type: none; margin-top: 10px; color: #0
00000; }
.content{
margin-left: 0px; padding-bottom: 2em; }
.nav {
padding-top: 10px; padding-bottom: 10px; padding-left: 1
5px; font-size: .70em;
margin-top: 10px; margin-left: 0px; color: #000000;
background-color: #ccccff; width: 20%; margin-left: 20px
; margin-top: 20px; }
.title {
font-family: arial; font-size: 26px; color: #ffffff;
background-color: #999999; width: 105%; margin-left: 0px
;
padding-top: 10px; padding-bottom: 10px; padding-left: 1
5px;}
.hidden {
position: absolute; visibility: hidden; z-index: 200; le
ft: 250px; top: 100px;
font-family: arial; overflow: hidden; width: 600;
padding: 20px; font-size: 10px; background-color: #99999
9;
layer-background-color:#FFFFFF; }
a,a:active { color: charcoal; font-weight: bold; }
a:visited { color: #666666; font-weight: bold; }
a:hover { color: cc3300; font-weight: bold; }
</style>
<script language="JavaScript" type="text/javascript">
<!--
// POP-UP CAPTIONS...
function lib_bwcheck(){ //Browsercheck (needed)
this.ver=navigator.appVersion
this.agent=navigator.userAgent
this.dom=document.getElementById?1:0
this.opera5=this.agent.indexOf("Opera 5")>-1
this.ie5=(this.ver.indexOf("MSIE 5")>-1 && this.dom && !this
.opera5)?1:0;
this.ie6=(this.ver.indexOf("MSIE 6")>-1 && this.dom && !this
.opera5)?1:0;
this.ie4=(document.all && !this.dom && !this.opera5)?1:0;
this.ie=this.ie4||this.ie5||this.ie6
this.mac=this.agent.indexOf("Mac")>-1
this.ns6=(this.dom && parseInt(this.ver) >= 5) ?1:0;
this.ns4=(document.layers && !this.dom)?1:0;
this.bw=(this.ie6 || this.ie5 || this.ie4 || this.ns4 || thi
s.ns6 || this.opera5)
return this
}
var bw = new lib_bwcheck()
//Makes crossbrowser object.
function makeObj(obj){
this.evnt=bw.dom? document.getElementById(obj):bw.ie4?docume
nt.all[obj]:bw.ns4?document.layers[obj]:0;
if(!this.evnt) return false
this.css=bw.dom||bw.ie4?this.evnt.style:bw.ns4?this.evnt:0;
this.wref=bw.dom||bw.ie4?this.evnt:bw.ns4?this.css.document:
0;
this.writeIt=b_writeIt;
return this
}
// A unit of measure that will be added when setting the positio
n of a layer.
//var px = bw.ns4||window.opera?"":"px";
function b_writeIt(text){
if (bw.ns4){this.wref.write(text);this.wref.close()}
else this.wref.innerHTML = text
}
//Shows the messages
var oDesc;
function popup(divid){
if(oDesc = new makeObj(divid)){
oDesc.css.visibility = "visible"
}
}
function popout(){ // Hides message
if(oDesc) oDesc.css.visibility = "hidden"
}
//-->
</script>
</head>
<body>
<div class=content>
<br><br>
<div class=title>'.$this->serviceName.'</div>
<div class=nav>
<p>View the <a href="'.$PHP_SELF.'?wsdl">WSDL</a
> for the service.
Click on an operation name to view it&apos;s det
ails.</p>
<ul>';
foreach($this->getOperations() as $op => $data){
$b .= "<li><a href='#' onclick=\"popout();po
pup('$op')\">$op</a></li>";
// create hidden div
$b .= "<div id='$op' class='hidden'>
<a href='#' onclick='popout()'><font color='
#ffffff'>Close</font></a><br><br>";
foreach($data as $donnie => $marie){ // loop
through opdata
if($donnie == 'input' || $donnie
== 'output'){ // show input/output data
$b .= "<font color='white'>"
.ucfirst($donnie).':</font><br>';
foreach($marie as $captain =
> $tenille){ // loop through data
if($captain == '
parts'){ // loop thru parts
$b .= "&nbsp
;&nbsp;$captain:<br>";
//if(is_array($tenille))
{
foreach(
$tenille as $joanie => $chachi){
$b .= "&nbsp;&nbsp;&nbsp;&nbsp;$joanie: $chachi<br>";
}
//}
} else {
$b .= "&nbsp
;&nbsp;$captain: $tenille<br>";
}
}
} else {
$b .= "<font color='white'>"
.ucfirst($donnie).":</font> $marie<br>";
}
}
$b .= '</div>';
}
$b .= '
<ul>
</div>
</div></body></html>';
return $b;
}
/**
* serialize the parsed wsdl
*
* @param mixed $debug whether to put debug=1 in endpoint URL
* @return string serialization of WSDL
* @access public
*/
function serialize($debug = 0)
{
$xml = '<?xml version="1.0" encoding="ISO-8859-1"?>';
$xml .= "\n<definitions";
foreach($this->namespaces as $k => $v) {
$xml .= " xmlns:$k=\"$v\"";
}
// 10.9.02 - add poulter fix for wsdl and tns declarations
if (isset($this->namespaces['wsdl'])) {
$xml .= " xmlns=\"" . $this->namespaces['wsdl'] . "\"";
}
if (isset($this->namespaces['tns'])) {
$xml .= " targetNamespace=\"" . $this->namespaces['tns']
. "\"";
}
$xml .= '>';
// imports
if (sizeof($this->import) > 0) {
foreach($this->import as $ns => $list) {
foreach ($list as $ii) {
if ($ii['location'] != '') {
$xml .= '<import location="' . $
ii['location'] . '" namespace="' . $ns . '" />';
} else {
$xml .= '<import namespace="' .
$ns . '" />';
}
}
}
}
// types
if (count($this->schemas)>=1) {
$xml .= "\n<types>";
foreach ($this->schemas as $ns => $list) {
foreach ($list as $xs) {
$xml .= $xs->serializeSchema();
}
}
$xml .= '</types>';
}
// messages
if (count($this->messages) >= 1) {
foreach($this->messages as $msgName => $msgParts) {
$xml .= "\n<message name=\"" . $msgName . '">';
if(is_array($msgParts)){
foreach($msgParts as $partName => $partT
ype) {
// print 'serializing '.$partTyp
e.', sv: '.$this->XMLSchemaVersion.'<br>';
if (strpos($partType, ':')) {
$typePrefix = $this->getPref
ixFromNamespace($this->getPrefix($partType));
} elseif (isset($this->typemap[$
this->namespaces['xsd']][$partType])) {
// print 'checking typemap:
'.$this->XMLSchemaVersion.'<br>';
$typePrefix = 'xsd';
} else {
foreach($this->typemap as $n
s => $types) {
if (isset($types[$partTy
pe])) {
$typePrefix = $this-
>getPrefixFromNamespace($ns);
}
}
if (!isset($typePrefix)) {
die("$partType has no na
mespace!");
}
}
$ns = $this->getNamespaceFromPre
fix($typePrefix);
$typeDef = $this->getTypeDef($th
is->getLocalPart($partType), $ns);
if ($typeDef['typeClass'] == 'el
ement') {
$elementortype = 'elemen
t';
} else {
$elementortype = 'type';
}
$xml .= '<part name="' . $partNa
me . '" ' . $elementortype . '="' . $typePrefix . ':' . $this->getLocalPart($par
tType) . '" />';
}
}
$xml .= '</message>';
}
}
// bindings & porttypes
if (count($this->bindings) >= 1) {
$binding_xml = '';
$portType_xml = '';
foreach($this->bindings as $bindingName => $attrs) {
$binding_xml .= "\n<binding name=\"" . $bindingN
ame . '" type="tns:' . $attrs['portType'] . '">';
$binding_xml .= '<soap:binding style="' . $attrs
['style'] . '" transport="' . $attrs['transport'] . '"/>';
$portType_xml .= "\n<portType name=\"" . $attrs[
'portType'] . '">';
foreach($attrs['operations'] as $opName => $opPa
rts) {
$binding_xml .= '<operation name="' . $o
pName . '">';
$binding_xml .= '<soap:operation soapAct
ion="' . $opParts['soapAction'] . '" style="'. $opParts['style'] . '"/>';
if (isset($opParts['input']['encodingSty
le']) && $opParts['input']['encodingStyle'] != '') {
$enc_style = ' encodingStyle="'
. $opParts['input']['encodingStyle'] . '"';
} else {
$enc_style = '';
}
$binding_xml .= '<input><soap:body use="
' . $opParts['input']['use'] . '" namespace="' . $opParts['input']['namespace']
. '"' . $enc_style . '/></input>';
if (isset($opParts['output']['encodingSt
yle']) && $opParts['output']['encodingStyle'] != '') {
$enc_style = ' encodingStyle="'
. $opParts['output']['encodingStyle'] . '"';
} else {
$enc_style = '';
}
$binding_xml .= '<output><soap:body use=
"' . $opParts['output']['use'] . '" namespace="' . $opParts['output']['namespace
'] . '"' . $enc_style . '/></output>';
$binding_xml .= '</operation>';
$portType_xml .= '<operation name="' . $
opParts['name'] . '"';
if (isset($opParts['parameterOrder'])) {
$portType_xml .= ' parameterOrder="'
. $opParts['parameterOrder'] . '"';
}
$portType_xml .= '>';
if(isset($opParts['documentation']) && $
opParts['documentation'] != '') {
$portType_xml .= '<documentation
>' . htmlspecialchars($opParts['documentation']) . '</documentation>';
}
$portType_xml .= '<input message="tns:'
. $opParts['input']['message'] . '"/>';
$portType_xml .= '<output message="tns:'
. $opParts['output']['message'] . '"/>';
$portType_xml .= '</operation>';
}
$portType_xml .= '</portType>';
$binding_xml .= '</binding>';
}
$xml .= $portType_xml . $binding_xml;
}
// services
$xml .= "\n<service name=\"" . $this->serviceName . '">';
if (count($this->ports) >= 1) {
foreach($this->ports as $pName => $attrs) {
$xml .= '<port name="' . $pName . '" binding="tn
s:' . $attrs['binding'] . '">';
$xml .= '<soap:address location="' . $attrs['loc
ation'] . ($debug ? '?debug=1' : '') . '"/>';
$xml .= '</port>';
}
}
$xml .= '</service>';
return $xml . "\n</definitions>";
}
/**
* serialize PHP values according to a WSDL message definition
*
* TODO
* - multi-ref serialization
* - validate PHP values against type definitions, return errors if inva
lid
*
* @param string $operation operation name
* @param string $direction (input|output)
* @param mixed $parameters parameter value(s)
* @return mixed parameters serialized as XML or false on error (e.g. op
eration not found)
* @access public
*/
function serializeRPCParameters($operation, $direction, $parameters)
{
$this->debug("in serializeRPCParameters: operation=$operation, d
irection=$direction, XMLSchemaVersion=$this->XMLSchemaVersion");
$this->appendDebug('parameters=' . $this->varDump($parameters));
if ($direction != 'input' && $direction != 'output') {
$this->debug('The value of the \$direction argument need
s to be either "input" or "output"');
$this->setError('The value of the \$direction argument n
eeds to be either "input" or "output"');
return false;
}
if (!$opData = $this->getOperationData($operation)) {
$this->debug('Unable to retrieve WSDL data for operation
: ' . $operation);
$this->setError('Unable to retrieve WSDL data for operat
ion: ' . $operation);
return false;
}
$this->debug('opData:');
$this->appendDebug($this->varDump($opData));
// Get encoding style for output and set to current
$encodingStyle = 'http://schemas.xmlsoap.org/soap/encoding/';
if(($direction == 'input') && isset($opData['output']['encodingS
tyle']) && ($opData['output']['encodingStyle'] != $encodingStyle)) {
$encodingStyle = $opData['output']['encodingStyle'];
$enc_style = $encodingStyle;
}
// set input params
$xml = '';
if (isset($opData[$direction]['parts']) && sizeof($opData[$direc
tion]['parts']) > 0) {
$use = $opData[$direction]['use'];
$this->debug('have ' . count($opData[$direction]['parts'
]) . ' part(s) to serialize');
if (is_array($parameters)) {
$parametersArrayType = $this->isArraySimpleOrStr
uct($parameters);
$this->debug('have ' . count($parameters) . ' pa
rameter(s) provided as ' . $parametersArrayType . ' to serialize');
foreach($opData[$direction]['parts'] as $name =>
$type) {
$this->debug('serializing part "'.$name.
'" of type "'.$type.'"');
// Track encoding style
if (isset($opData[$direction]['encodingS
tyle']) && $encodingStyle != $opData[$direction]['encodingStyle']) {
$encodingStyle = $opData[$direct
ion]['encodingStyle'];
$enc_style = $encodingStyle;
} else {
$enc_style = false;
}
// NOTE: add error handling here
// if serializeType returns false, then
catch global error and fault
if ($parametersArrayType == 'arraySimple
') {
$p = array_shift($parameters);
$this->debug('calling serializeT
ype w/indexed param');
$xml .= $this->serializeType($na
me, $type, $p, $use, $enc_style);
} elseif (isset($parameters[$name])) {
$this->debug('calling serializeT
ype w/named param');
$xml .= $this->serializeType($na
me, $type, $parameters[$name], $use, $enc_style);
} else {
// TODO: only send nillable
$this->debug('calling serializeT
ype w/null param');
$xml .= $this->serializeType($na
me, $type, null, $use, $enc_style);
}
}
} else {
$this->debug('no parameters passed.');
}
}
$this->debug("serializeRPCParameters returning: $xml");
return $xml;
}
/**
* serialize a PHP value according to a WSDL message definition
*
* TODO
* - multi-ref serialization
* - validate PHP values against type definitions, return errors if inva
lid
*
* @param string $ type name
* @param mixed $ param value
* @return mixed new param or false if initial value didn't validate
* @access public
* @deprecated
*/
function serializeParameters($operation, $direction, $parameters)
{
$this->debug("in serializeParameters: operation=$operation, dire
ction=$direction, XMLSchemaVersion=$this->XMLSchemaVersion");
$this->appendDebug('parameters=' . $this->varDump($parameters));
if ($direction != 'input' && $direction != 'output') {
$this->debug('The value of the \$direction argument need
s to be either "input" or "output"');
$this->setError('The value of the \$direction argument n
eeds to be either "input" or "output"');
return false;
}
if (!$opData = $this->getOperationData($operation)) {
$this->debug('Unable to retrieve WSDL data for operation
: ' . $operation);
$this->setError('Unable to retrieve WSDL data for operat
ion: ' . $operation);
return false;
}
$this->debug('opData:');
$this->appendDebug($this->varDump($opData));
// Get encoding style for output and set to current
$encodingStyle = 'http://schemas.xmlsoap.org/soap/encoding/';
if(($direction == 'input') && isset($opData['output']['encodingS
tyle']) && ($opData['output']['encodingStyle'] != $encodingStyle)) {
$encodingStyle = $opData['output']['encodingStyle'];
$enc_style = $encodingStyle;
}
// set input params
$xml = '';
if (isset($opData[$direction]['parts']) && sizeof($opData[$direc
tion]['parts']) > 0) {
$use = $opData[$direction]['use'];
$this->debug("use=$use");
$this->debug('got ' . count($opData[$direction]['parts']
) . ' part(s)');
if (is_array($parameters)) {
$parametersArrayType = $this->isArraySimpleOrStr
uct($parameters);
$this->debug('have ' . $parametersArrayType . '
parameters');
foreach($opData[$direction]['parts'] as $name =>
$type) {
$this->debug('serializing part "'.$name.
'" of type "'.$type.'"');
// Track encoding style
if(isset($opData[$direction]['encodingSt
yle']) && $encodingStyle != $opData[$direction]['encodingStyle']) {
$encodingStyle = $opData[$direct
ion]['encodingStyle'];
$enc_style = $encodingStyle;
} else {
$enc_style = false;
}
// NOTE: add error handling here
// if serializeType returns false, then
catch global error and fault
if ($parametersArrayType == 'arraySimple
') {
$p = array_shift($parameters);
$this->debug('calling serializeT
ype w/indexed param');
$xml .= $this->serializeType($na
me, $type, $p, $use, $enc_style);
} elseif (isset($parameters[$name])) {
$this->debug('calling serializeT
ype w/named param');
$xml .= $this->serializeType($na
me, $type, $parameters[$name], $use, $enc_style);
} else {
// TODO: only send nillable
$this->debug('calling serializeT
ype w/null param');
$xml .= $this->serializeType($na
me, $type, null, $use, $enc_style);
}
}
} else {
$this->debug('no parameters passed.');
}
}
$this->debug("serializeParameters returning: $xml");
return $xml;
}
/**
* serializes a PHP value according a given type definition
*
* @param string $name name of value (part or element)
* @param string $type XML schema type of value (type or element)
* @param mixed $value a native PHP value (parameter value)
* @param string $use use for part (encoded|literal)
* @param string $encodingStyle SOAP encoding style for the value (if di
fferent than the enclosing style)
* @param boolean $unqualified a kludge for what should be XML namespace
form handling
* @return string value serialized as an XML string
* @access private
*/
function serializeType($name, $type, $value, $use='encoded', $encodingSt
yle=false, $unqualified=false)
{
$this->debug("in serializeType: name=$name, type=$type, use=$use
, encodingStyle=$encodingStyle, unqualified=" . ($unqualified ? "unqualified" :
"qualified"));
$this->appendDebug("value=" . $this->varDump($value));
if($use == 'encoded' && $encodingStyle) {
$encodingStyle = ' SOAP-ENV:encodingStyle="' . $encoding
Style . '"';
}
// if a soapval has been supplied, let its type override the WSD
L
if (is_object($value) && get_class($value) == 'soapval') {
if ($value->type_ns) {
$type = $value->type_ns . ':' . $value->type;
$forceType = true;
$this->debug("in serializeType: soapval overrides type t
o $type");
} elseif ($value->type) {
$type = $value->type;
$forceType = true;
$this->debug("in serializeType: soapval overrides type t
o $type");
} else {
$forceType = false;
$this->debug("in serializeType: soapval does not overrid
e type");
}
$attrs = $value->attributes;
$value = $value->value;
$this->debug("in serializeType: soapval overrides value to $valu
e");
if ($attrs) {
if (!is_array($value)) {
$value['!'] = $value;
}
foreach ($attrs as $n => $v) {
$value['!' . $n] = $v;
}
$this->debug("in serializeType: soapval provides attribu
tes");
}
} else {
$forceType = false;
}
$xml = '';
if (strpos($type, ':')) {
$uqType = substr($type, strrpos($type, ':') + 1);
$ns = substr($type, 0, strrpos($type, ':'));
$this->debug("in serializeType: got a prefixed type: $uq
Type, $ns");
if ($this->getNamespaceFromPrefix($ns)) {
$ns = $this->getNamespaceFromPrefix($ns);
$this->debug("in serializeType: expanded prefixe
d type: $uqType, $ns");
}
if($ns == $this->XMLSchemaVersion || $ns == 'http://sche
mas.xmlsoap.org/soap/encoding/'){
$this->debug('in serializeType: type namespace i
ndicates XML Schema or SOAP Encoding type');
if ($unqualified && $use == 'literal') {
$elementNS = " xmlns=\"\"";
} else {
$elementNS = '';
}
if (is_null($value)) {
if ($use == 'literal') {
// TODO: depends on minOccurs
$xml = "<$name$elementNS/>";
} else {
// TODO: depends on nillable, wh
ich should be checked before calling this method
$xml = "<$name$elementNS xsi:nil
=\"true\" xsi:type=\"" . $this->getPrefixFromNamespace($ns) . ":$uqType\"/>";
}
$this->debug("in serializeType: returnin
g: $xml");
return $xml;
}
if ($uqType == 'boolean') {
if ((is_string($value) && $value == 'false') ||
(! $value)) {
$value = 'false';
} else {
$value = 'true';
}
}
if ($uqType == 'string' && gettype($value) == 's
tring') {
$value = $this->expandEntities($value);
}
if (($uqType == 'long' || $uqType == 'unsignedLo
ng') && gettype($value) == 'double') {
$value = sprintf("%.0lf", $value);
}
// it's a scalar
// TODO: what about null/nil values?
// check type isn't a custom type extending xmls
chema namespace
if (!$this->getTypeDef($uqType, $ns)) {
if ($use == 'literal') {
if ($forceType) {
$xml = "<$name$elementNS
xsi:type=\"" . $this->getPrefixFromNamespace($ns) . ":$uqType\">$value</$name>"
;
} else {
$xml = "<$name$elementNS
>$value</$name>";
}
} else {
$xml = "<$name$elementNS xsi:typ
e=\"" . $this->getPrefixFromNamespace($ns) . ":$uqType\"$encodingStyle>$value</$
name>";
}
$this->debug("in serializeType: returnin
g: $xml");
return $xml;
}
$this->debug('custom type extends XML Schema or
SOAP Encoding namespace (yuck)');
} else if ($ns == 'http://xml.apache.org/xml-soap') {
$this->debug('in serializeType: appears to be Ap
ache SOAP type');
if ($uqType == 'Map') {
$tt_prefix = $this->getPrefixFromNamespa
ce('http://xml.apache.org/xml-soap');
if (! $tt_prefix) {
$this->debug('in serializeType:
Add namespace for Apache SOAP type');
$tt_prefix = 'ns' . rand(1000, 9
999);
$this->namespaces[$tt_prefix] =
'http://xml.apache.org/xml-soap';
// force this to be added to use
dNamespaces
$tt_prefix = $this->getPrefixFro
mNamespace('http://xml.apache.org/xml-soap');
}
$contents = '';
foreach($value as $k => $v) {
$this->debug("serializing map el
ement: key $k, value $v");
$contents .= '<item>';
$contents .= $this->serialize_va
l($k,'key',false,false,false,false,$use);
$contents .= $this->serialize_va
l($v,'value',false,false,false,false,$use);
$contents .= '</item>';
}
if ($use == 'literal') {
if ($forceType) {
$xml = "<$name xsi:type=
\"" . $tt_prefix . ":$uqType\">$contents</$name>";
} else {
$xml = "<$name>$contents
</$name>";
}
} else {
$xml = "<$name xsi:type=\"" . $t
t_prefix . ":$uqType\"$encodingStyle>$contents</$name>";
}
$this->debug("in serializeType: returnin
g: $xml");
return $xml;
}
$this->debug('in serializeType: Apache SOAP type
, but only support Map');
}
} else {
// TODO: should the type be compared to types in XSD, an
d the namespace
// set to XSD if the type matches?
$this->debug("in serializeType: No namespace for type $t
ype");
$ns = '';
$uqType = $type;
}
if(!$typeDef = $this->getTypeDef($uqType, $ns)){
$this->setError("$type ($uqType) is not a supported type
.");
$this->debug("in serializeType: $type ($uqType) is not a
supported type.");
return false;
} else {
$this->debug("in serializeType: found typeDef");
$this->appendDebug('typeDef=' . $this->varDump($typeDef)
);
}
$phpType = $typeDef['phpType'];
$this->debug("in serializeType: uqType: $uqType, ns: $ns, phptyp
e: $phpType, arrayType: " . (isset($typeDef['arrayType']) ? $typeDef['arrayType'
] : '') );
// if php type == struct, map value to the <all> element names
if ($phpType == 'struct') {
if (isset($typeDef['typeClass']) && $typeDef['typeClass'
] == 'element') {
$elementName = $uqType;
if (isset($typeDef['form']) && ($typeDef['form']
== 'qualified')) {
$elementNS = " xmlns=\"$ns\"";
} else {
$elementNS = " xmlns=\"\"";
}
} else {
$elementName = $name;
if ($unqualified) {
$elementNS = " xmlns=\"\"";
} else {
$elementNS = '';
}
}
if (is_null($value)) {
if ($use == 'literal') {
// TODO: depends on minOccurs
$xml = "<$elementName$elementNS/>";
} else {
$xml = "<$elementName$elementNS xsi:nil=
\"true\" xsi:type=\"" . $this->getPrefixFromNamespace($ns) . ":$uqType\"/>";
}
$this->debug("in serializeType: returning: $xml"
);
return $xml;
}
if (is_object($value)) {
$value = get_object_vars($value);
}
if (is_array($value)) {
$elementAttrs = $this->serializeComplexTypeAttri
butes($typeDef, $value, $ns, $uqType);
if ($use == 'literal') {
if ($forceType) {
$xml = "<$elementName$elementNS$
elementAttrs xsi:type=\"" . $this->getPrefixFromNamespace($ns) . ":$uqType\">";
} else {
$xml = "<$elementName$elementNS$
elementAttrs>";
}
} else {
$xml = "<$elementName$elementNS$elementA
ttrs xsi:type=\"" . $this->getPrefixFromNamespace($ns) . ":$uqType\"$encodingSty
le>";
}
$xml .= $this->serializeComplexTypeElements($typ
eDef, $value, $ns, $uqType, $use, $encodingStyle);
$xml .= "</$elementName>";
} else {
$this->debug("in serializeType: phpType is struc
t, but value is not an array");
$this->setError("phpType is struct, but value is
not an array: see debug output for details");
$xml = '';
}
} elseif ($phpType == 'array') {
if (isset($typeDef['form']) && ($typeDef['form'] == 'qua
lified')) {
$elementNS = " xmlns=\"$ns\"";
} else {
if ($unqualified) {
$elementNS = " xmlns=\"\"";
} else {
$elementNS = '';
}
}
if (is_null($value)) {
if ($use == 'literal') {
// TODO: depends on minOccurs
$xml = "<$name$elementNS/>";
} else {
$xml = "<$name$elementNS xsi:nil=\"true\
" xsi:type=\"" .
$this->getPrefixFromNamespace('h
ttp://schemas.xmlsoap.org/soap/encoding/') .
":Array\" " .
$this->getPrefixFromNamespace('h
ttp://schemas.xmlsoap.org/soap/encoding/') .
':arrayType="' .
$this->getPrefixFromNamespace($t
his->getPrefix($typeDef['arrayType'])) .
':' .
$this->getLocalPart($typeDef['ar
rayType'])."[0]\"/>";
}
$this->debug("in serializeType: returning: $xml"
);
return $xml;
}
if (isset($typeDef['multidimensional'])) {
$nv = array();
foreach($value as $v) {
$cols = ',' . sizeof($v);
$nv = array_merge($nv, $v);
}
$value = $nv;
} else {
$cols = '';
}
if (is_array($value) && sizeof($value) >= 1) {
$rows = sizeof($value);
$contents = '';
foreach($value as $k => $v) {
$this->debug("serializing array element:
$k, $v of type: $typeDef[arrayType]");
//if (strpos($typeDef['arrayType'], ':')
) {
if (!in_array($typeDef['arrayType'],$thi
s->typemap['http://www.w3.org/2001/XMLSchema'])) {
$contents .= $this->serializeType('i
tem', $typeDef['arrayType'], $v, $use);
} else {
$contents .= $this->serialize_val($v
, 'item', $typeDef['arrayType'], null, $this->XMLSchemaVersion, false, $use);
}
}
} else {
$rows = 0;
$contents = null;
}
// TODO: for now, an empty value will be serialized as a
zero element
// array. Revisit this when coding the handling of null
/nil values.
if ($use == 'literal') {
$xml = "<$name$elementNS>"
.$contents
."</$name>";
} else {
$xml = "<$name$elementNS xsi:type=\"".$this->get
PrefixFromNamespace('http://schemas.xmlsoap.org/soap/encoding/').':Array" '.
$this->getPrefixFromNamespace('http://sc
hemas.xmlsoap.org/soap/encoding/')
.':arrayType="'
.$this->getPrefixFromNamespace($this->ge
tPrefix($typeDef['arrayType']))
.":".$this->getLocalPart($typeDef['array
Type'])."[$rows$cols]\">"
.$contents
."</$name>";
}
} elseif ($phpType == 'scalar') {
if (isset($typeDef['form']) && ($typeDef['form'] == 'qua
lified')) {
$elementNS = " xmlns=\"$ns\"";
} else {
if ($unqualified) {
$elementNS = " xmlns=\"\"";
} else {
$elementNS = '';
}
}
if ($use == 'literal') {
if ($forceType) {
$xml = "<$name$elementNS xsi:type=\"" .
$this->getPrefixFromNamespace($ns) . ":$uqType\">$value</$name>";
} else {
$xml = "<$name$elementNS>$value</$name>"
;
}
} else {
$xml = "<$name$elementNS xsi:type=\"" . $this->g
etPrefixFromNamespace($ns) . ":$uqType\"$encodingStyle>$value</$name>";
}
}
$this->debug("in serializeType: returning: $xml");
return $xml;
}
/**
* serializes the attributes for a complexType
*
* @param array $typeDef our internal representation of an XML schema ty
pe (or element)
* @param mixed $value a native PHP value (parameter value)
* @param string $ns the namespace of the type
* @param string $uqType the local part of the type
* @return string value serialized as an XML string
* @access private
*/
function serializeComplexTypeAttributes($typeDef, $value, $ns, $uqType)
{
$xml = '';
if (isset($typeDef['attrs']) && is_array($typeDef['attrs'])) {
$this->debug("serialize attributes for XML Schema type $
ns:$uqType");
if (is_array($value)) {
$xvalue = $value;
} elseif (is_object($value)) {
$xvalue = get_object_vars($value);
} else {
$this->debug("value is neither an array nor an o
bject for XML Schema type $ns:$uqType");
$xvalue = array();
}
foreach ($typeDef['attrs'] as $aName => $attrs) {
if (isset($xvalue['!' . $aName])) {
$xname = '!' . $aName;
$this->debug("value provided for attribu
te $aName with key $xname");
} elseif (isset($xvalue[$aName])) {
$xname = $aName;
$this->debug("value provided for attribu
te $aName with key $xname");
} elseif (isset($attrs['default'])) {
$xname = '!' . $aName;
$xvalue[$xname] = $attrs['default'];
$this->debug('use default value of ' . $
xvalue[$aName] . ' for attribute ' . $aName);
} else {
$xname = '';
$this->debug("no value provided for attr
ibute $aName");
}
if ($xname) {
$xml .= " $aName=\"" . $this->expandEnt
ities($xvalue[$xname]) . "\"";
}
}
} else {
$this->debug("no attributes to serialize for XML Schema
type $ns:$uqType");
}
if (isset($typeDef['extensionBase'])) {
$ns = $this->getPrefix($typeDef['extensionBase']);
$uqType = $this->getLocalPart($typeDef['extensionBase'])
;
if ($this->getNamespaceFromPrefix($ns)) {
$ns = $this->getNamespaceFromPrefix($ns);
}
if ($typeDef = $this->getTypeDef($uqType, $ns)) {
$this->debug("serialize attributes for extension
base $ns:$uqType");
$xml .= $this->serializeComplexTypeAttributes($t
ypeDef, $value, $ns, $uqType);
} else {
$this->debug("extension base $ns:$uqType is not
a supported type");
}
}
return $xml;
}
/**
* serializes the elements for a complexType
*
* @param array $typeDef our internal representation of an XML schema ty
pe (or element)
* @param mixed $value a native PHP value (parameter value)
* @param string $ns the namespace of the type
* @param string $uqType the local part of the type
* @param string $use use for part (encoded|literal)
* @param string $encodingStyle SOAP encoding style for the value (if di
fferent than the enclosing style)
* @return string value serialized as an XML string
* @access private
*/
function serializeComplexTypeElements($typeDef, $value, $ns, $uqType, $u
se='encoded', $encodingStyle=false) {
$xml = '';
if (isset($typeDef['elements']) && is_array($typeDef['elements']
)) {
$this->debug("in serializeComplexTypeElements, serialize
elements for XML Schema type $ns:$uqType");
if (is_array($value)) {
$xvalue = $value;
} elseif (is_object($value)) {
$xvalue = get_object_vars($value);
} else {
$this->debug("value is neither an array nor an o
bject for XML Schema type $ns:$uqType");
$xvalue = array();
}
// toggle whether all elements are present - ideally sho
uld validate against schema
if (count($typeDef['elements']) != count($xvalue)){
$optionals = true;
}
foreach ($typeDef['elements'] as $eName => $attrs) {
if (!isset($xvalue[$eName])) {
if (isset($attrs['default'])) {
$xvalue[$eName] = $attrs['defaul
t'];
$this->debug('use default value
of ' . $xvalue[$eName] . ' for element ' . $eName);
}
}
// if user took advantage of a minOccurs=0, then
only serialize named parameters
if (isset($optionals)
&& (!isset($xvalue[$eName]))
&& ( (!isset($attrs['nillable'])) || $at
trs['nillable'] != 'true')
){
if (isset($attrs['minOccurs']) && $attrs
['minOccurs'] <> '0') {
$this->debug("apparent error: no
value provided for element $eName with minOccurs=" . $attrs['minOccurs']);
}
// do nothing
$this->debug("no value provided for comp
lexType element $eName and element is not nillable, so serialize nothing");
} else {
// get value
if (isset($xvalue[$eName])) {
$v = $xvalue[$eName];
} else {
$v = null;
}
if (isset($attrs['form'])) {
$unqualified = ($attrs['form'] =
= 'unqualified');
} else {
$unqualified = false;
}
if (isset($attrs['maxOccurs']) && ($attr
s['maxOccurs'] == 'unbounded' || $attrs['maxOccurs'] > 1) && isset($v) && is_arr
ay($v) && $this->isArraySimpleOrStruct($v) == 'arraySimple') {
$vv = $v;
foreach ($vv as $k => $v) {
if (isset($attrs['type']
) || isset($attrs['ref'])) {
// serialize sch
ema-defined type
$xml .= $this->seria
lizeType($eName, isset($attrs['type']) ? $attrs['type'] : $attrs['ref'], $v, $us
e, $encodingStyle, $unqualified);
} else {
// serialize gen
eric type (can this ever really happen?)
$this->debug("callin
g serialize_val() for $v, $eName, false, false, false, false, $use");
$xml .= $this->seria
lize_val($v, $eName, false, false, false, false, $use);
}
}
} else {
if (isset($attrs['type']) || iss
et($attrs['ref'])) {
// serialize schema-defi
ned type
$xml .= $this->serializeType
($eName, isset($attrs['type']) ? $attrs['type'] : $attrs['ref'], $v, $use, $enco
dingStyle, $unqualified);
} else {
// serialize generic typ
e (can this ever really happen?)
$this->debug("calling serial
ize_val() for $v, $eName, false, false, false, false, $use");
$xml .= $this->serialize_val
($v, $eName, false, false, false, false, $use);
}
}
}
}
} else {
$this->debug("no elements to serialize for XML Schema ty
pe $ns:$uqType");
}
if (isset($typeDef['extensionBase'])) {
$ns = $this->getPrefix($typeDef['extensionBase']);
$uqType = $this->getLocalPart($typeDef['extensionBase'])
;
if ($this->getNamespaceFromPrefix($ns)) {
$ns = $this->getNamespaceFromPrefix($ns);
}
if ($typeDef = $this->getTypeDef($uqType, $ns)) {
$this->debug("serialize elements for extension b
ase $ns:$uqType");
$xml .= $this->serializeComplexTypeElements($typ
eDef, $value, $ns, $uqType, $use, $encodingStyle);
} else {
$this->debug("extension base $ns:$uqType is not
a supported type");
}
}
return $xml;
}
/**
* adds an XML Schema complex type to the WSDL types
*
* @param string name
* @param string typeClass (complexType|simpleType|attribute)
* @param string phpType: currently supported are array and struct (php a
ssoc array)
* @param string compositor (all|sequence|choice)
* @param string restrictionBase namespace:name (http://schemas.xmlsoap.o
rg/soap/encoding/:Array)
* @param array elements = array ( name => array(name=>'',type=>'') )
* @param array attrs = array(array('ref'=>'SOAP-ENC:arrayType','wsdl:ar
rayType'=>'xsd:string[]'))
* @param string arrayType: namespace:name (xsd:string)
* @see xmlschema
* @access public
*/
function addComplexType($name,$typeClass='complexType',$phpType='array',
$compositor='',$restrictionBase='',$elements=array(),$attrs=array(),$arrayType='
') {
if (count($elements) > 0) {
foreach($elements as $n => $e){
// expand each element
foreach ($e as $k => $v) {
$k = strpos($k,':') ? $this->expandQname($k) : $k;
$v = strpos($v,':') ? $this->expandQname($v) : $v;
$ee[$k] = $v;
}
$eElements[$n] = $ee;
}
$elements = $eElements;
}
if (count($attrs) > 0) {
foreach($attrs as $n => $a){
// expand each attribute
foreach ($a as $k => $v) {
$k = strpos($k,':') ? $this->expandQname($k) : $k;
$v = strpos($v,':') ? $this->expandQname($v) : $v;
$aa[$k] = $v;
}
$eAttrs[$n] = $aa;
}
$attrs = $eAttrs;
}
$restrictionBase = strpos($restrictionBase,':') ? $this->expandQ
name($restrictionBase) : $restrictionBase;
$arrayType = strpos($arrayType,':') ? $this->expandQname($arrayT
ype) : $arrayType;
$typens = isset($this->namespaces['types']) ? $this->namespaces[
'types'] : $this->namespaces['tns'];
$this->schemas[$typens][0]->addComplexType($name,$typeClass,$php
Type,$compositor,$restrictionBase,$elements,$attrs,$arrayType);
}
/**
* adds an XML Schema simple type to the WSDL types
*
* @param string $name
* @param string $restrictionBase namespace:name (http://schemas.xmlsoap.
org/soap/encoding/:Array)
* @param string $typeClass (should always be simpleType)
* @param string $phpType (should always be scalar)
* @param array $enumeration array of values
* @see xmlschema
* @access public
*/
function addSimpleType($name, $restrictionBase='', $typeClass='simpleTyp
e', $phpType='scalar', $enumeration=array()) {
$restrictionBase = strpos($restrictionBase,':') ? $this->expandQ
name($restrictionBase) : $restrictionBase;
$typens = isset($this->namespaces['types']) ? $this->namespaces[
'types'] : $this->namespaces['tns'];
$this->schemas[$typens][0]->addSimpleType($name, $restrictionBas
e, $typeClass, $phpType, $enumeration);
}
/**
* adds an element to the WSDL types
*
* @param array $attrs attributes that must include name and type
* @see xmlschema
* @access public
*/
function addElement($attrs) {
$typens = isset($this->namespaces['types']) ? $this->namespaces[
'types'] : $this->namespaces['tns'];
$this->schemas[$typens][0]->addElement($attrs);
}
/**
* register an operation with the server
*
* @param string $name operation (method) name
* @param array $in assoc array of input values: key = param name, value
= param type
* @param array $out assoc array of output values: key = param name, valu
e = param type
* @param string $namespace optional The namespace for the operation
* @param string $soapaction optional The soapaction for the operation
* @param string $style (rpc|document) optional The style for the operati
on Note: when 'document' is specified, parameter and return wrappers are created
for you automatically
* @param string $use (encoded|literal) optional The use for the paramete
rs (cannot mix right now)
* @param string $documentation optional The description to include in th
e WSDL
* @param string $encodingStyle optional (usually 'http://schemas.xmlsoap
.org/soap/encoding/' for encoded)
* @access public
*/
function addOperation($name, $in = false, $out = false, $namespace = fal
se, $soapaction = false, $style = 'rpc', $use = 'encoded', $documentation = '',
$encodingStyle = ''){
if ($use == 'encoded' && $encodingStyle == '') {
$encodingStyle = 'http://schemas.xmlsoap.org/soap/encodi
ng/';
}
if ($style == 'document') {
$elements = array();
foreach ($in as $n => $t) {
$elements[$n] = array('name' => $n, 'type' => $t
);
}
$this->addComplexType($name . 'RequestType', 'complexTyp
e', 'struct', 'all', '', $elements);
$this->addElement(array('name' => $name, 'type' => $name
. 'RequestType'));
$in = array('parameters' => 'tns:' . $name);
$elements = array();
foreach ($out as $n => $t) {
$elements[$n] = array('name' => $n, 'type' => $t
);
}
$this->addComplexType($name . 'ResponseType', 'complexTy
pe', 'struct', 'all', '', $elements);
$this->addElement(array('name' => $name . 'Response', 't
ype' => $name . 'ResponseType'));
$out = array('parameters' => 'tns:' . $name . 'Response'
);
}
// get binding
$this->bindings[ $this->serviceName . 'Binding' ]['operations'][
$name] =
array(
'name' => $name,
'binding' => $this->serviceName . 'Binding',
'endpoint' => $this->endpoint,
'soapAction' => $soapaction,
'style' => $style,
'input' => array(
'use' => $use,
'namespace' => $namespace,
'encodingStyle' => $encodingStyle,
'message' => $name . 'Request',
'parts' => $in),
'output' => array(
'use' => $use,
'namespace' => $namespace,
'encodingStyle' => $encodingStyle,
'message' => $name . 'Response',
'parts' => $out),
'namespace' => $namespace,
'transport' => 'http://schemas.xmlsoap.org/soap/http',
'documentation' => $documentation);
// add portTypes
// add messages
if($in)
{
foreach($in as $pName => $pType)
{
if(strpos($pType,':')) {
$pType = $this->getNamespaceFromPrefix($
this->getPrefix($pType)).":".$this->getLocalPart($pType);
}
$this->messages[$name.'Request'][$pName] = $pTyp
e;
}
} else {
$this->messages[$name.'Request']= '0';
}
if($out)
{
foreach($out as $pName => $pType)
{
if(strpos($pType,':')) {
$pType = $this->getNamespaceFromPrefix($
this->getPrefix($pType)).":".$this->getLocalPart($pType);
}
$this->messages[$name.'Response'][$pName] = $pTy
pe;
}
} else {
$this->messages[$name.'Response']= '0';
}
return true;
}
}
?><?php

/**
*
* soap_parser class parses SOAP XML messages into native PHP values
*
* @author Dietrich Ayala <[email protected]>
* @version $Id: nusoap.php,v 1.94 2005/08/04 01:27:42 snichol Exp $
* @access public
*/
class soap_parser extends nusoap_base {
var $xml = '';
var $xml_encoding = '';
var $method = '';
var $root_struct = '';
var $root_struct_name = '';
var $root_struct_namespace = '';
var $root_header = '';
var $document = ''; // incoming SOAP body (text)
// determines where in the message we are (envelope,header,body,method)
var $status = '';
var $position = 0;
var $depth = 0;
var $default_namespace = '';
var $namespaces = array();
var $message = array();
var $parent = '';
var $fault = false;
var $fault_code = '';
var $fault_str = '';
var $fault_detail = '';
var $depth_array = array();
var $debug_flag = true;
var $soapresponse = NULL;
var $responseHeaders = ''; // incoming SOAP headers (text)
var $body_position = 0;
// for multiref parsing:
// array of id => pos
var $ids = array();
// array of id => hrefs => pos
var $multirefs = array();
// toggle for auto-decoding element content
var $decode_utf8 = true;
/**
* constructor that actually does the parsing
*
* @param string $xml SOAP message
* @param string $encoding character encoding scheme of message
* @param string $method method for which XML is parsed (unused?)
* @param string $decode_utf8 whether to decode UTF-8 to ISO-8859-1
* @access public
*/
function soap_parser($xml,$encoding='UTF-8',$method='',$decode_utf8=true
){
parent::nusoap_base();
$this->xml = $xml;
$this->xml_encoding = $encoding;
$this->method = $method;
$this->decode_utf8 = $decode_utf8;
// Check whether content has been read.
if(!empty($xml)){
// Check XML encoding
$pos_xml = strpos($xml, '<?xml');
if ($pos_xml !== FALSE) {
$xml_decl = substr($xml, $pos_xml, strpos($xml,
'?>', $pos_xml + 2) - $pos_xml + 1);
if (preg_match("/encoding=[\"']([^\"']*)[\"']/",
$xml_decl, $res)) {
$xml_encoding = $res[1];
if (strtoupper($xml_encoding) != $encodi
ng) {
$err = "Charset from HTTP Conten
t-Type '" . $encoding . "' does not match encoding from XML declaration '" . $xm
l_encoding . "'";
$this->debug($err);
if ($encoding != 'ISO-8859-1' ||
strtoupper($xml_encoding) != 'UTF-8') {
$this->setError($err);
return;
}
// when HTTP says ISO-8859-1 (th
e default) and XML says UTF-8 (the typical), assume the other endpoint is just s
loppy and proceed
} else {
$this->debug('Charset from HTTP
Content-Type matches encoding from XML declaration');
}
} else {
$this->debug('No encoding specified in X
ML declaration');
}
} else {
$this->debug('No XML declaration');
}
$this->debug('Entering soap_parser(), length='.strlen($x
ml).', encoding='.$encoding);
// Create an XML parser - why not xml_parser_create_ns?
$this->parser = xml_parser_create($this->xml_encoding);
// Set the options for parsing the XML data.
//xml_parser_set_option($parser, XML_OPTION_SKIP_WHITE,
1);
xml_parser_set_option($this->parser, XML_OPTION_CASE_FOL
DING, 0);
xml_parser_set_option($this->parser, XML_OPTION_TARGET_E
NCODING, $this->xml_encoding);
// Set the object for the parser.
xml_set_object($this->parser, $this);
// Set the element handlers for the parser.
xml_set_element_handler($this->parser, 'start_element','
end_element');
xml_set_character_data_handler($this->parser,'character_
data');
// Parse the XML file.
if(!xml_parse($this->parser,$xml,true)){
// Display an error message.
$err = sprintf('XML error parsing SOAP payload on li
ne %d: %s',
xml_get_current_line_number($this->parser),
xml_error_string(xml_get_error_code($this->parser)))
;
$this->debug($err);
$this->debug("XML payload:\n" . $xml);
$this->setError($err);
} else {
$this->debug('parsed successfully, found root st
ruct: '.$this->root_struct.' of name '.$this->root_struct_name);
// get final value
$this->soapresponse = $this->message[$this->root
_struct]['result'];
// get header value: no, because this is documen
ted as XML string
// if($this->root_header != '' && isset($this->mess
age[$this->root_header]['result'])){
// $this->responseHeaders = $this->message[
$this->root_header]['result'];
// }
// resolve hrefs/ids
if(sizeof($this->multirefs) > 0){
foreach($this->multirefs as $id => $href
s){
$this->debug('resolving multiref
s for id: '.$id);
$idVal = $this->buildVal($this->
ids[$id]);
if (is_array($idVal) && isset($i
dVal['!id'])) {
unset($idVal['!id']);
}
foreach($hrefs as $refPos => $re
f){
$this->debug('resolving
href at pos '.$refPos);
$this->multirefs[$id][$r
efPos] = $idVal;
}
}
}
}
xml_parser_free($this->parser);
} else {
$this->debug('xml was empty, didn\'t parse!');
$this->setError('xml was empty, didn\'t parse!');
}
}
/**
* start-element handler
*
* @param resource $parser XML parser object
* @param string $name element name
* @param array $attrs associative array of attributes
* @access private
*/
function start_element($parser, $name, $attrs) {
// position in a total number of elements, starting from 0
// update class level pos
$pos = $this->position++;
// and set mine
$this->message[$pos] = array('pos' => $pos,'children'=>'','cdata
'=>'');
// depth = how many levels removed from root?
// set mine as current global depth and increment global depth v
alue
$this->message[$pos]['depth'] = $this->depth++;
// else add self as child to whoever the current parent is
if($pos != 0){
$this->message[$this->parent]['children'] .= '|'.$pos;
}
// set my parent
$this->message[$pos]['parent'] = $this->parent;
// set self as current parent
$this->parent = $pos;
// set self as current value for this depth
$this->depth_array[$this->depth] = $pos;
// get element prefix
if(strpos($name,':')){
// get ns prefix
$prefix = substr($name,0,strpos($name,':'));
// get unqualified name
$name = substr(strstr($name,':'),1);
}
// set status
if($name == 'Envelope'){
$this->status = 'envelope';
} elseif($name == 'Header'){
$this->root_header = $pos;
$this->status = 'header';
} elseif($name == 'Body'){
$this->status = 'body';
$this->body_position = $pos;
// set method
} elseif($this->status == 'body' && $pos == ($this->body_positio
n+1)){
$this->status = 'method';
$this->root_struct_name = $name;
$this->root_struct = $pos;
$this->message[$pos]['type'] = 'struct';
$this->debug("found root struct $this->root_struct_name,
pos $this->root_struct");
}
// set my status
$this->message[$pos]['status'] = $this->status;
// set name
$this->message[$pos]['name'] = htmlspecialchars($name);
// set attrs
$this->message[$pos]['attrs'] = $attrs;
// loop through atts, logging ns and type declarations
$attstr = '';
foreach($attrs as $key => $value){
$key_prefix = $this->getPrefix($key);
$key_localpart = $this->getLocalPart($key);
// if ns declarations, add to class level array of valid
namespaces
if($key_prefix == 'xmlns'){
if(ereg('^http://www.w3.org/[0-9]{4}/XMLSchema$'
,$value)){
$this->XMLSchemaVersion = $value;
$this->namespaces['xsd'] = $this->XMLSch
emaVersion;
$this->namespaces['xsi'] = $this->XMLSch
emaVersion.'-instance';
}
$this->namespaces[$key_localpart] = $value;
// set method namespace
if($name == $this->root_struct_name){
$this->methodNamespace = $value;
}
// if it's a type declaration, set type
} elseif($key_localpart == 'type'){
$value_prefix = $this->getPrefix($value);
$value_localpart = $this->getLocalPart($value);
$this->message[$pos]['type'] = $value_localpart;
$this->message[$pos]['typePrefix'] = $value_pref
ix;
if(isset($this->namespaces[$value_prefix])){
$this->message[$pos]['type_namespace'] = $this->namespac
es[$value_prefix];
} else if(isset($attrs['xmlns:'.$value_prefix])) {
$this->message[$pos]['type_namespace'] =
$attrs['xmlns:'.$value_prefix];
}
// should do something here with the namespace o
f specified type?
} elseif($key_localpart == 'arrayType'){
$this->message[$pos]['type'] = 'array';
/* do arrayType ereg here
[1] arrayTypeValue ::= atype asize
[2] atype ::= QName rank*
[3] rank ::= '[' (',')* ']'
[4] asize ::= '[' length~ ']'
[5] length ::= nextDimension* Digit+
[6] nextDimension ::= Digit+ ','
*/
$expr = '([A-Za-z0-9_]+):([A-Za-z]+[A-Za-z0-9_]+
)\[([0-9]+),?([0-9]*)\]';
if(ereg($expr,$value,$regs)){
$this->message[$pos]['typePrefix'] = $re
gs[1];
$this->message[$pos]['arrayTypePrefix']
= $regs[1];
if (isset($this->namespaces[$regs[1]])) {
$this->message[$pos]['arrayTypeNamespace'] = $th
is->namespaces[$regs[1]];
} else if (isset($attrs['xmlns:'.$regs[1]])) {
$this->message[$pos]['arrayTypeN
amespace'] = $attrs['xmlns:'.$regs[1]];
}
$this->message[$pos]['arrayType'] = $reg
s[2];
$this->message[$pos]['arraySize'] = $reg
s[3];
$this->message[$pos]['arrayCols'] = $reg
s[4];
}
// specifies nil value (or not)
} elseif ($key_localpart == 'nil'){
$this->message[$pos]['nil'] = ($value == 'true'
|| $value == '1');
// some other attribute
} elseif ($key != 'href' && $key != 'xmlns' && $key_loca
lpart != 'encodingStyle' && $key_localpart != 'root') {
$this->message[$pos]['xattrs']['!' . $key] = $va
lue;
}
if ($key == 'xmlns') {
$this->default_namespace = $value;
}
// log id
if($key == 'id'){
$this->ids[$value] = $pos;
}
// root
if($key_localpart == 'root' && $value == 1){
$this->status = 'method';
$this->root_struct_name = $name;
$this->root_struct = $pos;
$this->debug("found root struct $this->root_stru
ct_name, pos $pos");
}
// for doclit
$attstr .= " $key=\"$value\"";
}
// get namespace - must be done after namespace atts are processed
if(isset($prefix)){
$this->message[$pos]['namespace'] = $this->namespaces[$p
refix];
$this->default_namespace = $this->namespaces[$prefix];
} else {
$this->message[$pos]['namespace'] = $this->default_names
pace;
}
if($this->status == 'header'){
if ($this->root_header != $pos) {
$this->responseHeaders .= "<" . (isset($prefix) ? $prefi
x . ':' : '') . "$name$attstr>";
}
} elseif($this->root_struct_name != ''){
$this->document .= "<" . (isset($prefix) ? $prefix . ':' : '') .
"$name$attstr>";
}
}
/**
* end-element handler
*
* @param resource $parser XML parser object
* @param string $name element name
* @access private
*/
function end_element($parser, $name) {
// position of current element is equal to the last value left i
n depth_array for my depth
$pos = $this->depth_array[$this->depth--];
// get element prefix
if(strpos($name,':')){
// get ns prefix
$prefix = substr($name,0,strpos($name,':'));
// get unqualified name
$name = substr(strstr($name,':'),1);
}
// build to native type
if(isset($this->body_position) && $pos > $this->body_position){
// deal w/ multirefs
if(isset($this->message[$pos]['attrs']['href'])){
// get id
$id = substr($this->message[$pos]['attrs']['href
'],1);
// add placeholder to href array
$this->multirefs[$id][$pos] = 'placeholder';
// add set a reference to it as the result value
$this->message[$pos]['result'] =& $this->multire
fs[$id][$pos];
// build complexType values
} elseif($this->message[$pos]['children'] != ''){
// if result has already been generated (struct/
array)
if(!isset($this->message[$pos]['result'])){
$this->message[$pos]['result'] = $this->
buildVal($pos);
}
// build complexType values of attributes and possibly s
impleContent
} elseif (isset($this->message[$pos]['xattrs'])) {
if (isset($this->message[$pos]['nil']) && $this-
>message[$pos]['nil']) {
$this->message[$pos]['xattrs']['!'] = nu
ll;
} elseif (isset($this->message[$pos]['cdata']) &
& trim($this->message[$pos]['cdata']) != '') {
if (isset($this->message[$pos]['type'])) {
$this->message[$pos]['xattrs']['
!'] = $this->decodeSimple($this->message[$pos]['cdata'], $this->message[$pos]['t
ype'], isset($this->message[$pos]['type_namespace']) ? $this->message[$pos]['typ
e_namespace'] : '');
} else {
$parent = $this->message[$pos]['
parent'];
if (isset($this->message[$parent
]['type']) && ($this->message[$parent]['type'] == 'array') && isset($this->messa
ge[$parent]['arrayType'])) {
$this->message[$pos]['xa
ttrs']['!'] = $this->decodeSimple($this->message[$pos]['cdata'], $this->message[
$parent]['arrayType'], isset($this->message[$parent]['arrayTypeNamespace']) ? $t
his->message[$parent]['arrayTypeNamespace'] : '');
} else {
$this->message[$pos]['xa
ttrs']['!'] = $this->message[$pos]['cdata'];
}
}
}
$this->message[$pos]['result'] = $this->message[
$pos]['xattrs'];
// set value of simpleType (or nil complexType)
} else {
//$this->debug('adding data for scalar value '.$this->message[$p
os]['name'].' of value '.$this->message[$pos]['cdata']);
if (isset($this->message[$pos]['nil']) && $this-
>message[$pos]['nil']) {
$this->message[$pos]['xattrs']['!'] = nu
ll;
} elseif (isset($this->message[$pos]['type'])) {
$this->message[$pos]['result'] = $this->
decodeSimple($this->message[$pos]['cdata'], $this->message[$pos]['type'], isset(
$this->message[$pos]['type_namespace']) ? $this->message[$pos]['type_namespace']
: '');
} else {
$parent = $this->message[$pos]['parent']
;
if (isset($this->message[$parent]['type'
]) && ($this->message[$parent]['type'] == 'array') && isset($this->message[$pare
nt]['arrayType'])) {
$this->message[$pos]['result'] =
$this->decodeSimple($this->message[$pos]['cdata'], $this->message[$parent]['arr
ayType'], isset($this->message[$parent]['arrayTypeNamespace']) ? $this->message[
$parent]['arrayTypeNamespace'] : '');
} else {
$this->message[$pos]['result'] =
$this->message[$pos]['cdata'];
}
}
/* add value to parent's result, if parent is st
ruct/array
$parent = $this->message[$pos]['parent'];
if($this->message[$parent]['type'] != 'map'){
if(strtolower($this->message[$parent]['t
ype']) == 'array'){
$this->message[$parent]['result'
][] = $this->message[$pos]['result'];
} else {
$this->message[$parent]['result'
][$this->message[$pos]['name']] = $this->message[$pos]['result'];
}
}
*/
}
}
// for doclit
if($this->status == 'header'){
if ($this->root_header != $pos) {
$this->responseHeaders .= "</" . (isset($prefix) ? $pref
ix . ':' : '') . "$name>";
}
} elseif($pos >= $this->root_struct){
$this->document .= "</" . (isset($prefix) ? $prefix . ':' : '')
. "$name>";
}
// switch status
if($pos == $this->root_struct){
$this->status = 'body';
$this->root_struct_namespace = $this->message[$pos]['nam
espace'];
} elseif($name == 'Body'){
$this->status = 'envelope';
} elseif($name == 'Header'){
$this->status = 'envelope';
} elseif($name == 'Envelope'){
//
}
// set parent back to my parent
$this->parent = $this->message[$pos]['parent'];
}
/**
* element content handler
*
* @param resource $parser XML parser object
* @param string $data element content
* @access private
*/
function character_data($parser, $data){
$pos = $this->depth_array[$this->depth];
if ($this->xml_encoding=='UTF-8'){
// TODO: add an option to disable this for folks who wan
t
// raw UTF-8 that, e.g., might not map to iso-8859-1
// TODO: this can also be handled with xml_parser_set_op
tion($this->parser, XML_OPTION_TARGET_ENCODING, "ISO-8859-1");
if($this->decode_utf8){
$data = utf8_decode($data);
}
}
$this->message[$pos]['cdata'] .= $data;
// for doclit
if($this->status == 'header'){
$this->responseHeaders .= $data;
} else {
$this->document .= $data;
}
}
/**
* get the parsed message
*
* @return mixed
* @access public
*/
function get_response(){
return $this->soapresponse;
}
/**
* get the parsed headers
*
* @return string XML or empty if no headers
* @access public
*/
function getHeaders(){
return $this->responseHeaders;
}
/**
* decodes simple types into PHP variables
*
* @param string $value value to decode
* @param string $type XML type to decode
* @param string $typens XML type namespace to decode
* @return mixed PHP value
* @access private
*/
function decodeSimple($value, $type, $typens) {
// TODO: use the namespace!
if ((!isset($type)) || $type == 'string' || $type == 'long' || $
type == 'unsignedLong') {
return (string) $value;
}
if ($type == 'int' || $type == 'integer' || $type == 'short' ||
$type == 'byte') {
return (int) $value;
}
if ($type == 'float' || $type == 'double' || $type == 'decimal')
{
return (double) $value;
}
if ($type == 'boolean') {
if (strtolower($value) == 'false' || strtolower($value)
== 'f') {
return false;
}
return (boolean) $value;
}
if ($type == 'base64' || $type == 'base64Binary') {
$this->debug('Decode base64 value');
return base64_decode($value);
}
// obscure numeric types
if ($type == 'nonPositiveInteger' || $type == 'negativeInteger'
|| $type == 'nonNegativeInteger' || $type == 'positiveIn
teger'
|| $type == 'unsignedInt'
|| $type == 'unsignedShort' || $type == 'unsignedByte')
{
return (int) $value;
}
// bogus: parser treats array with no elements as a simple type
if ($type == 'array') {
return array();
}
// everything else
return (string) $value;
}
/**
* builds response structures for compound values (arrays/structs)
* and scalars
*
* @param integer $pos position in node tree
* @return mixed PHP value
* @access private
*/
function buildVal($pos){
if(!isset($this->message[$pos]['type'])){
$this->message[$pos]['type'] = '';
}
$this->debug('in buildVal() for '.$this->message[$pos]['name']."
(pos $pos) of type ".$this->message[$pos]['type']);
// if there are children...
if($this->message[$pos]['children'] != ''){
$this->debug('in buildVal, there are children');
$children = explode('|',$this->message[$pos]['children']
);
array_shift($children); // knock off empty
// md array
if(isset($this->message[$pos]['arrayCols']) && $this->me
ssage[$pos]['arrayCols'] != ''){
$r=0; // rowcount
$c=0; // colcount
foreach($children as $child_pos){
$this->debug("in buildVal, got an MD arr
ay element: $r, $c");
$params[$r][] = $this->message[$child_po
s]['result'];
$c++;
if($c == $this->message[$pos]['arrayCols']){
$c = 0;
$r++;
}
}
// array
} elseif($this->message[$pos]['type'] == 'array' || $thi
s->message[$pos]['type'] == 'Array'){
$this->debug('in buildVal, adding array '.$this->message[$pos]['
name']);
foreach($children as $child_pos){
$params[] = &$this->message[$child_pos]['result'];
}
// apache Map type: java hashtable
} elseif($this->message[$pos]['type'] == 'Map' && $this->message[$po
s]['type_namespace'] == 'http://xml.apache.org/xml-soap'){
$this->debug('in buildVal, Java Map '.$this->message[$pos]['name
']);
foreach($children as $child_pos){
$kv = explode("|",$this->message[$child_pos]['children']
);
$params[$this->message[$kv[1]]['result']] = &$this->mess
age[$kv[2]]['result'];
}
// generic compound type
//} elseif($this->message[$pos]['type'] == 'SOAPStruct' || $this->me
ssage[$pos]['type'] == 'struct') {
} else {
// Apache Vector type: treat as an array
$this->debug('in buildVal, adding Java Vector '.$this->message[$
pos]['name']);
if ($this->message[$pos]['type'] == 'Vector' &&
$this->message[$pos]['type_namespace'] == 'http://xml.apache.org/xml-soap') {
$notstruct = 1;
} else {
$notstruct = 0;
}
//
foreach($children as $child_pos){
if($notstruct){
$params[] = &$this->message[$child_pos]['result'
];
} else {
if (isset($params[$this->message[$child_pos]['na
me']])) {
// de-serialize repeated element name in
to an array
if ((!is_array($params[$this->message[$c
hild_pos]['name']])) || (!isset($params[$this->message[$child_pos]['name']][0]))
) {
$params[$this->message[$child_po
s]['name']] = array($params[$this->message[$child_pos]['name']]);
}
$params[$this->message[$child_pos]['name
']][] = &$this->message[$child_pos]['result'];
} else {
$params[$this->message[$child_po
s]['name']] = &$this->message[$child_pos]['result'];
}
}
}
}
if (isset($this->message[$pos]['xattrs'])) {
$this->debug('in buildVal, handling attributes');
foreach ($this->message[$pos]['xattrs'] as $n =>
$v) {
$params[$n] = $v;
}
}
// handle simpleContent
if (isset($this->message[$pos]['cdata']) && trim($this->
message[$pos]['cdata']) != '') {
$this->debug('in buildVal, handling simpleContent');
if (isset($this->message[$pos]['type'])) {
$params['!'] = $this->decodeSimple($this
->message[$pos]['cdata'], $this->message[$pos]['type'], isset($this->message[$po
s]['type_namespace']) ? $this->message[$pos]['type_namespace'] : '');
} else {
$parent = $this->message[$pos]['parent']
;
if (isset($this->message[$parent]['type'
]) && ($this->message[$parent]['type'] == 'array') && isset($this->message[$pare
nt]['arrayType'])) {
$params['!'] = $this->decodeSimp
le($this->message[$pos]['cdata'], $this->message[$parent]['arrayType'], isset($t
his->message[$parent]['arrayTypeNamespace']) ? $this->message[$parent]['arrayTyp
eNamespace'] : '');
} else {
$params['!'] = $this->message[$p
os]['cdata'];
}
}
}
return is_array($params) ? $params : array();
} else {
$this->debug('in buildVal, no children, building scalar');
$cdata = isset($this->message[$pos]['cdata']) ? $this->m
essage[$pos]['cdata'] : '';
if (isset($this->message[$pos]['type'])) {
return $this->decodeSimple($cdata, $this->messag
e[$pos]['type'], isset($this->message[$pos]['type_namespace']) ? $this->message[
$pos]['type_namespace'] : '');
}
$parent = $this->message[$pos]['parent'];
if (isset($this->message[$parent]['type']) && ($this->me
ssage[$parent]['type'] == 'array') && isset($this->message[$parent]['arrayType']
)) {
return $this->decodeSimple($cdata, $this->messag
e[$parent]['arrayType'], isset($this->message[$parent]['arrayTypeNamespace']) ?
$this->message[$parent]['arrayTypeNamespace'] : '');
}
return $this->message[$pos]['cdata'];
}
}
}

?><?php

/**
*
* soapclient higher level class for easy usage.
*
* usage:
*
* // instantiate client with server info
* $soapclient = new soapclient( string path [ ,boolean wsdl] );
*
* // call method, get results
* echo $soapclient->call( string methodname [ ,array parameters] );
*
* // bye bye client
* unset($soapclient);
*
* @author Dietrich Ayala <[email protected]>
* @version $Id: nusoap.php,v 1.94 2005/08/04 01:27:42 snichol Exp $
* @access public
*/
class soapclient extends nusoap_base {
var $username = '';
var $password = '';
var $authtype = '';
var $certRequest = array();
var $requestHeaders = false; // SOAP headers in request (text)
var $responseHeaders = ''; // SOAP headers from response (i
ncomplete namespace resolution) (text)
var $document = ''; // SOAP body response po
rtion (incomplete namespace resolution) (text)
var $endpoint;
var $forceEndpoint = ''; // overrides WSDL endpoint
var $proxyhost = '';
var $proxyport = '';
var $proxyusername = '';
var $proxypassword = '';
var $xml_encoding = ''; // character set encoding of inc
oming (response) messages
var $http_encoding = false;
var $timeout = 0; // HTTP connection timeo
ut
var $response_timeout = 30; // HTTP response timeout
var $endpointType = ''; // soap|wsdl, empty for WSDL ini
tialization error
var $persistentConnection = false;
var $defaultRpcParams = false; // This is no longer used
var $request = ''; // HTTP request
var $response = ''; // HTTP response
var $responseData = ''; // SOAP payload of response
var $cookies = array(); // Cookies from response or for
request
var $decode_utf8 = true; // toggles whether the parser decodes el
ement content w/ utf8_decode()
var $operations = array(); // WSDL operations, empty for WS
DL initialization error
/*
* fault related variables
*/
/**
* @var fault
* @access public
*/
var $fault;
/**
* @var faultcode
* @access public
*/
var $faultcode;
/**
* @var faultstring
* @access public
*/
var $faultstring;
/**
* @var faultdetail
* @access public
*/
var $faultdetail;
/**
* constructor
*
* @param mixed $endpoint SOAP server or WSDL URL (string), or wsdl in
stance (object)
* @param bool $wsdl optional, set to true if using WSDL
* @param int $portName optional portName in WSDL document
* @param string $proxyhost
* @param string $proxyport
* @param string $proxyusername
* @param string $proxypassword
* @param integer $timeout set the connection timeout
* @param integer $response_timeout set the response timeout
* @access public
*/
function soapclient($endpoint,$wsdl = false,$proxyhost = false,$proxypor
t = false,$proxyusername = false, $proxypassword = false, $timeout = 0, $respons
e_timeout = 30){
parent::nusoap_base();
$this->endpoint = $endpoint;
$this->proxyhost = $proxyhost;
$this->proxyport = $proxyport;
$this->proxyusername = $proxyusername;
$this->proxypassword = $proxypassword;
$this->timeout = $timeout;
$this->response_timeout = $response_timeout;
// make values
if($wsdl){
if (is_object($endpoint) && (get_class($endpoint) == 'ws
dl')) {
$this->wsdl = $endpoint;
$this->endpoint = $this->wsdl->wsdl;
$this->wsdlFile = $this->endpoint;
$this->debug('existing wsdl instance created fro
m ' . $this->endpoint);
} else {
$this->wsdlFile = $this->endpoint;
// instantiate wsdl object and parse wsdl file
$this->debug('instantiating wsdl class with doc:
'.$endpoint);
$this->wsdl =& new wsdl($this->wsdlFile,$this->p
roxyhost,$this->proxyport,$this->proxyusername,$this->proxypassword,$this->timeo
ut,$this->response_timeout);
}
$this->appendDebug($this->wsdl->getDebug());
$this->wsdl->clearDebug();
// catch errors
if($errstr = $this->wsdl->getError()){
$this->debug('got wsdl error: '.$errstr);
$this->setError('wsdl error: '.$errstr);
} elseif($this->operations = $this->wsdl->getOperations(
)){
$this->debug( 'got '.count($this->operations).'
operations from wsdl '.$this->wsdlFile);
$this->endpointType = 'wsdl';
} else {
$this->debug( 'getOperations returned false');
$this->setError('no operations defined in the WS
DL document!');
}
} else {
$this->debug("instantiate SOAP with endpoint at $endpoin
t");
$this->endpointType = 'soap';
}
}
/**
* calls method, returns PHP native type
*
* @param string $method SOAP server URL or path
* @param mixed $params An array, associative or simple, of the parame
ters
* for the method call, or a string t
hat is the XML
* for the call. For rpc style, this
call will
* wrap the XML in a tag named after
the method, as
* well as the SOAP Envelope and Body
. For document
* style, this will only wrap with th
e Envelope and Body.
* IMPORTANT: when using an array wit
h document style,
* in which case there
* is really one parameter, the root of the fragm
ent
* used in the call, which encloses what programm
ers
* normally think of parameters. A parameter arr
ay
* *must* include the wrapper.
* @param string $namespace optional method namespace (WSDL can ov
erride)
* @param string $soapAction optional SOAPAction value (WSDL can o
verride)
* @param mixed $headers optional string of XML with SOAP header c
ontent, or array of soapval objects for SOAP headers
* @param boolean $rpcParams optional (no longer used)
* @param string $style optional (rpc|document) the style to use
when serializing parameters (WSDL can override)
* @param string $use optional (encoded|literal) the use when ser
ializing parameters (WSDL can override)
* @return mixed response from SOAP call
* @access public
*/
function call($operation,$params=array(),$namespace='http://tempuri.org'
,$soapAction='',$headers=false,$rpcParams=null,$style='rpc',$use='encoded'){
$this->operation = $operation;
$this->fault = false;
$this->setError('');
$this->request = '';
$this->response = '';
$this->responseData = '';
$this->faultstring = '';
$this->faultcode = '';
$this->opData = array();
$this->debug("call: operation=$operation, namespace=$namespace,
soapAction=$soapAction, rpcParams=$rpcParams, style=$style, use=$use, endpointTy
pe=$this->endpointType");
$this->appendDebug('params=' . $this->varDump($params));
$this->appendDebug('headers=' . $this->varDump($headers));
if ($headers) {
$this->requestHeaders = $headers;
}
// serialize parameters
if($this->endpointType == 'wsdl' && $opData = $this->getOperatio
nData($operation)){
// use WSDL for operation
$this->opData = $opData;
$this->debug("found operation");
$this->appendDebug('opData=' . $this->varDump($opData));
if (isset($opData['soapAction'])) {
$soapAction = $opData['soapAction'];
}
if (! $this->forceEndpoint) {
$this->endpoint = $opData['endpoint'];
} else {
$this->endpoint = $this->forceEndpoint;
}
$namespace = isset($opData['input']['namespace']) ? $opD
ata['input']['namespace'] : $namespace;
$style = $opData['style'];
$use = $opData['input']['use'];
// add ns to ns array
if($namespace != '' && !isset($this->wsdl->namespaces[$n
amespace])){
$nsPrefix = 'ns' . rand(1000, 9999);
$this->wsdl->namespaces[$nsPrefix] = $namespace;
}
$nsPrefix = $this->wsdl->getPrefixFromNamespace($namespace);
// serialize payload
if (is_string($params)) {
$this->debug("serializing param string for WSDL
operation $operation");
$payload = $params;
} elseif (is_array($params)) {
$this->debug("serializing param array for WSDL o
peration $operation");
$payload = $this->wsdl->serializeRPCParameters($
operation,'input',$params);
} else {
$this->debug('params must be array or string');
$this->setError('params must be array or string'
);
return false;
}
$usedNamespaces = $this->wsdl->usedNamespaces;
if (isset($opData['input']['encodingStyle'])) {
$encodingStyle = $opData['input']['encodingStyle
'];
} else {
$encodingStyle = '';
}
$this->appendDebug($this->wsdl->getDebug());
$this->wsdl->clearDebug();
if ($errstr = $this->wsdl->getError()) {
$this->debug('got wsdl error: '.$errstr);
$this->setError('wsdl error: '.$errstr);
return false;
}
} elseif($this->endpointType == 'wsdl') {
// operation not in WSDL
$this->appendDebug($this->wsdl->getDebug());
$this->wsdl->clearDebug();
$this->setError( 'operation '.$operation.' not present.'
);
$this->debug("operation '$operation' not present.");
return false;
} else {
// no WSDL
//$this->namespaces['ns1'] = $namespace;
$nsPrefix = 'ns' . rand(1000, 9999);
// serialize
$payload = '';
if (is_string($params)) {
$this->debug("serializing param string for opera
tion $operation");
$payload = $params;
} elseif (is_array($params)) {
$this->debug("serializing param array for operat
ion $operation");
foreach($params as $k => $v){
$payload .= $this->serialize_val($v,$k,f
alse,false,false,false,$use);
}
} else {
$this->debug('params must be array or string');
$this->setError('params must be array or string'
);
return false;
}
$usedNamespaces = array();
if ($use == 'encoded') {
$encodingStyle = 'http://schemas.xmlsoap.org/soa
p/encoding/';
} else {
$encodingStyle = '';
}
}
// wrap RPC calls with method element
if ($style == 'rpc') {
if ($use == 'literal') {
$this->debug("wrapping RPC request with literal
method element");
if ($namespace) {
$payload = "<$operation xmlns=\"$namespa
ce\">" . $payload . "</$operation>";
} else {
$payload = "<$operation>" . $payload . "
</$operation>";
}
} else {
$this->debug("wrapping RPC request with encoded
method element");
if ($namespace) {
$payload = "<$nsPrefix:$operation xmlns:
$nsPrefix=\"$namespace\">" .
$payload .
"</$nsPrefix:$op
eration>";
} else {
$payload = "<$operation>" .
$payload .
"</$operation>";
}
}
}
// serialize envelope
$soapmsg = $this->serializeEnvelope($payload,$this->requestHeade
rs,$usedNamespaces,$style,$use,$encodingStyle);
$this->debug("endpoint=$this->endpoint, soapAction=$soapAction,
namespace=$namespace, style=$style, use=$use, encodingStyle=$encodingStyle");
$this->debug('SOAP message length=' . strlen($soapmsg) . ' conte
nts (max 1000 bytes)=' . substr($soapmsg, 0, 1000));
// send
$return = $this->send($this->getHTTPBody($soapmsg),$soapAction,$
this->timeout,$this->response_timeout);
if($errstr = $this->getError()){
$this->debug('Error: '.$errstr);
return false;
} else {
$this->return = $return;
$this->debug('sent message successfully and got a(n) '.g
ettype($return));
$this->appendDebug('return=' . $this->varDump($return));
// fault?
if(is_array($return) && isset($return['faultcode'])){
$this->debug('got fault');
$this->setError($return['faultcode'].': '.$retur
n['faultstring']);
$this->fault = true;
foreach($return as $k => $v){
$this->$k = $v;
$this->debug("$k = $v<br>");
}
return $return;
} elseif ($style == 'document') {
// NOTE: if the response is defined to have mult
iple parts (i.e. unwrapped),
// we are only going to return the first part he
re...sorry about that
return $return;
} else {
// array of return values
if(is_array($return)){
// multiple 'out' parameters, which we r
eturn wrapped up
// in the array
if(sizeof($return) > 1){
return $return;
}
// single 'out' parameter (normally the
return value)
$return = array_shift($return);
$this->debug('return shifted value: ');
$this->appendDebug($this->varDump($retur
n));
return $return;
// nothing returned (ie, echoVoid)
} else {
return "";
}
}
}
}
/**
* get available data pertaining to an operation
*
* @param string $operation operation name
* @return array array of data pertaining to the operation
* @access public
*/
function getOperationData($operation){
if(isset($this->operations[$operation])){
return $this->operations[$operation];
}
$this->debug("No data for operation: $operation");
}
/**
* send the SOAP message
*
* Note: if the operation has multiple return values
* the return value of this method will be an array
* of those values.
*
* @param string $msg a SOAPx4 soapmsg object
* @param string $soapaction SOAPAction value
* @param integer $timeout set connection timeout in seconds
* @param integer $response_timeout set response timeout in second
s
* @return mixed native PHP types.
* @access private
*/
function send($msg, $soapaction = '', $timeout=0, $response_timeout=30)
{
$this->checkCookies();
// detect transport
switch(true){
// http(s)
case ereg('^http',$this->endpoint):
$this->debug('transporting via HTTP');
if($this->persistentConnection == true && is_obj
ect($this->persistentConnection)){
$http =& $this->persistentConnection;
} else {
$http = new soap_transport_http($this->e
ndpoint);
if ($this->persistentConnection) {
$http->usePersistentConnection()
;
}
}
$http->setContentType($this->getHTTPContentType(
), $this->getHTTPContentTypeCharset());
$http->setSOAPAction($soapaction);
if($this->proxyhost && $this->proxyport){
$http->setProxy($this->proxyhost,$this->
proxyport,$this->proxyusername,$this->proxypassword);
}
if($this->authtype != '') {
$http->setCredentials($this->username, $
this->password, $this->authtype, array(), $this->certRequest);
}
if($this->http_encoding != ''){
$http->setEncoding($this->http_encoding)
;
}
$this->debug('sending message, length='.strlen($
msg));
if(ereg('^http:',$this->endpoint)){
//if(strpos($this->endpoint,'http:')){
$this->responseData = $http->send($msg,$
timeout,$response_timeout,$this->cookies);
} elseif(ereg('^https',$this->endpoint)){
//} elseif(strpos($this->endpoint,'https:')){
//if(phpversion() == '4.3.0-dev'){
//$response = $http->send($msg,$
timeout,$response_timeout);
//$this->request = $http->outgoing_payload;
//$this->response = $http->incom
ing_payload;
//} else
$this->responseData = $http->sendHTTPS($
msg,$timeout,$response_timeout,$this->cookies);
} else {
$this->setError('no http/s in endpoint u
rl');
}
$this->request = $http->outgoing_payload;
$this->response = $http->incoming_payload;
$this->appendDebug($http->getDebug());
$this->UpdateCookies($http->incoming_cookies);
// save transport object if using persistent con
nections
if ($this->persistentConnection) {
$http->clearDebug();
if (!is_object($this->persistentConnecti
on)) {
$this->persistentConnection = $h
ttp;
}
}
if($err = $http->getError()){
$this->setError('HTTP Error: '.$err);
return false;
} elseif($this->getError()){
return false;
} else {
$this->debug('got response, length='. st
rlen($this->responseData).' type='.$http->incoming_headers['content-type']);
return $this->parseResponse($http->incom
ing_headers, $this->responseData);
}
break;
default:
$this->setError('no transport found, or selected
transport is not yet supported!');
return false;
break;
}
}
/**
* processes SOAP message returned from server
*
* @param array $headers The HTTP headers
* @param string $data unprocessed response data from s
erver
* @return mixed value of the message, decoded into a PHP type
* @access private
*/
function parseResponse($headers, $data) {
$this->debug('Entering parseResponse() for data of length ' . st
rlen($data) . ' and type ' . $headers['content-type']);
if (!strstr($headers['content-type'], 'text/xml')) {
$this->setError('Response not of type text/xml');
return false;
}
if (strpos($headers['content-type'], '=')) {
$enc = str_replace('"', '', substr(strstr($headers["cont
ent-type"], '='), 1));
$this->debug('Got response encoding: ' . $enc);
if(eregi('^(ISO-8859-1|US-ASCII|UTF-8)$',$enc)){
$this->xml_encoding = strtoupper($enc);
} else {
$this->xml_encoding = 'US-ASCII';
}
} else {
// should be US-ASCII for HTTP 1.0 or ISO-8859-1 for HTT
P 1.1
$this->xml_encoding = 'ISO-8859-1';
}
$this->debug('Use encoding: ' . $this->xml_encoding . ' when cre
ating soap_parser');
$parser = new soap_parser($data,$this->xml_encoding,$this->opera
tion,$this->decode_utf8);
// add parser debug data to our debug
$this->appendDebug($parser->getDebug());
// if parse errors
if($errstr = $parser->getError()){
$this->setError( $errstr);
// destroy the parser object
unset($parser);
return false;
} else {
// get SOAP headers
$this->responseHeaders = $parser->getHeaders();
// get decoded message
$return = $parser->get_response();
// add document for doclit support
$this->document = $parser->document;
// destroy the parser object
unset($parser);
// return decode message
return $return;
}
}
/**
* sets the SOAP endpoint, which can override WSDL
*
* @param $endpoint string The endpoint URL to use, or empty strin
g or false to prevent override
* @access public
*/
function setEndpoint($endpoint) {
$this->forceEndpoint = $endpoint;
}
/**
* set the SOAP headers
*
* @param $headers mixed String of XML with SOAP header content, o
r array of soapval objects for SOAP headers
* @access public
*/
function setHeaders($headers){
$this->requestHeaders = $headers;
}
/**
* get the SOAP response headers (namespace resolution incomplete)
*
* @return string
* @access public
*/
function getHeaders(){
return $this->responseHeaders;
}
/**
* set proxy info here
*
* @param string $proxyhost
* @param string $proxyport
* @param string $proxyusername
* @param string $proxypassword
* @access public
*/
function setHTTPProxy($proxyhost, $proxyport, $proxyusername = '', $prox
ypassword = '') {
$this->proxyhost = $proxyhost;
$this->proxyport = $proxyport;
$this->proxyusername = $proxyusername;
$this->proxypassword = $proxypassword;
}
/**
* if authenticating, set user credentials here
*
* @param string $username
* @param string $password
* @param string $authtype (basic|digest|certificate)
* @param array $certRequest (keys must be cainfofile (optional),
sslcertfile, sslkeyfile, passphrase, verifypeer (optional), verifyhost (optional
): see corresponding options in cURL docs)
* @access public
*/
function setCredentials($username, $password, $authtype = 'basic', $cert
Request = array()) {
$this->username = $username;
$this->password = $password;
$this->authtype = $authtype;
$this->certRequest = $certRequest;
}
/**
* use HTTP encoding
*
* @param string $enc
* @access public
*/
function setHTTPEncoding($enc='gzip, deflate'){
$this->http_encoding = $enc;
}
/**
* use HTTP persistent connections if possible
*
* @access public
*/
function useHTTPPersistentConnection(){
$this->persistentConnection = true;
}
/**
* gets the default RPC parameter setting.
* If true, default is that call params are like RPC even for document st
yle.
* Each call() can override this value.
*
* This is no longer used.
*
* @return boolean
* @access public
* @deprecated
*/
function getDefaultRpcParams() {
return $this->defaultRpcParams;
}
/**
* sets the default RPC parameter setting.
* If true, default is that call params are like RPC even for document st
yle
* Each call() can override this value.
*
* This is no longer used.
*
* @param boolean $rpcParams
* @access public
* @deprecated
*/
function setDefaultRpcParams($rpcParams) {
$this->defaultRpcParams = $rpcParams;
}
/**
* dynamically creates an instance of a proxy class,
* allowing user to directly call methods from wsdl
*
* @return object soap_proxy object
* @access public
*/
function getProxy(){
$r = rand();
$evalStr = $this->_getProxyClassCode($r);
//$this->debug("proxy class: $evalStr";
// eval the class
eval($evalStr);
// instantiate proxy object
eval("\$proxy = new soap_proxy_$r('');");
// transfer current wsdl data to the proxy thereby avoiding pars
ing the wsdl twice
$proxy->endpointType = 'wsdl';
$proxy->wsdlFile = $this->wsdlFile;
$proxy->wsdl = $this->wsdl;
$proxy->operations = $this->operations;
$proxy->defaultRpcParams = $this->defaultRpcParams;
// transfer other state
$proxy->username = $this->username;
$proxy->password = $this->password;
$proxy->authtype = $this->authtype;
$proxy->proxyhost = $this->proxyhost;
$proxy->proxyport = $this->proxyport;
$proxy->proxyusername = $this->proxyusername;
$proxy->proxypassword = $this->proxypassword;
$proxy->timeout = $this->timeout;
$proxy->response_timeout = $this->response_timeout;
$proxy->http_encoding = $this->http_encoding;
$proxy->persistentConnection = $this->persistentConnection;
$proxy->requestHeaders = $this->requestHeaders;
$proxy->soap_defencoding = $this->soap_defencoding;
$proxy->endpoint = $this->endpoint;
$proxy->forceEndpoint = $this->forceEndpoint;
return $proxy;
}
/**
* dynamically creates proxy class code
*
* @return string PHP/NuSOAP code for the proxy class
* @access private
*/
function _getProxyClassCode($r) {
if ($this->endpointType != 'wsdl') {
$evalStr = 'A proxy can only be created for a WSDL clien
t';
$this->setError($evalStr);
return $evalStr;
}
$evalStr = '';
foreach ($this->operations as $operation => $opData) {
if ($operation != '') {
// create param string and param comment string
if (sizeof($opData['input']['parts']) > 0) {
$paramStr = '';
$paramArrayStr = '';
$paramCommentStr = '';
foreach ($opData['input']['parts'] as $n
ame => $type) {
$paramStr .= "\$$name, ";
$paramArrayStr .= "'$name' => \$
$name, ";
$paramCommentStr .= "$type \$$na
me, ";
}
$paramStr = substr($paramStr, 0, strlen(
$paramStr)-2);
$paramArrayStr = substr($paramArrayStr,
0, strlen($paramArrayStr)-2);
$paramCommentStr = substr($paramCommentS
tr, 0, strlen($paramCommentStr)-2);
} else {
$paramStr = '';
$paramCommentStr = 'void';
}
$opData['namespace'] = !isset($opData['namespace
']) ? 'http://testuri.com' : $opData['namespace'];
$evalStr .= "// $paramCommentStr
function " . str_replace('.', '__', $operation) . "($paramStr) {
\$params = array($paramArrayStr);
return \$this->call('$operation', \$params, '".$opData['namespac
e']."', '".(isset($opData['soapAction']) ? $opData['soapAction'] : '')."');
}
";
unset($paramStr);
unset($paramCommentStr);
}
}
$evalStr = 'class soap_proxy_'.$r.' extends soapclient {
'.$evalStr.'
}';
return $evalStr;
}
/**
* dynamically creates proxy class code
*
* @return string PHP/NuSOAP code for the proxy class
* @access public
*/
function getProxyClassCode() {
$r = rand();
return $this->_getProxyClassCode($r);
}
/**
* gets the HTTP body for the current request.
*
* @param string $soapmsg The SOAP payload
* @return string The HTTP body, which includes the SOAP payload
* @access private
*/
function getHTTPBody($soapmsg) {
return $soapmsg;
}
/**
* gets the HTTP content type for the current request.
*
* Note: getHTTPBody must be called before this.
*
* @return string the HTTP content type for the current request.
* @access private
*/
function getHTTPContentType() {
return 'text/xml';
}
/**
* gets the HTTP content type charset for the current request.
* returns false for non-text content types.
*
* Note: getHTTPBody must be called before this.
*
* @return string the HTTP content type charset for the current request.
* @access private
*/
function getHTTPContentTypeCharset() {
return $this->soap_defencoding;
}
/*
* whether or not parser should decode utf8 element content
*
* @return always returns true
* @access public
*/
function decodeUTF8($bool){
$this->decode_utf8 = $bool;
return true;
}
/**
* adds a new Cookie into $this->cookies array
*
* @param string $name Cookie Name
* @param string $value Cookie Value
* @return if cookie-set was successful returns true, else false
* @access public
*/
function setCookie($name, $value) {
if (strlen($name) == 0) {
return false;
}
$this->cookies[] = array('name' => $name, 'value' => $value);
return true;
}
/**
* gets all Cookies
*
* @return array with all internal cookies
* @access public
*/
function getCookies() {
return $this->cookies;
}
/**
* checks all Cookies and delete those which are expired
*
* @return always return true
* @access private
*/
function checkCookies() {
if (sizeof($this->cookies) == 0) {
return true;
}
$this->debug('checkCookie: check ' . sizeof($this->cookies) . '
cookies');
$curr_cookies = $this->cookies;
$this->cookies = array();
foreach ($curr_cookies as $cookie) {
if (! is_array($cookie)) {
$this->debug('Remove cookie that is not an array
');
continue;
}
if ((isset($cookie['expires'])) && (! empty($cookie['exp
ires']))) {
if (strtotime($cookie['expires']) > time()) {
$this->cookies[] = $cookie;
} else {
$this->debug('Remove expired cookie ' .
$cookie['name']);
}
} else {
$this->cookies[] = $cookie;
}
}
$this->debug('checkCookie: '.sizeof($this->cookies).' cookies le
ft in array');
return true;
}
/**
* updates the current cookies with a new set
*
* @param array $cookies new cookies with which to update current
ones
* @return always return true
* @access private
*/
function UpdateCookies($cookies) {
if (sizeof($this->cookies) == 0) {
// no existing cookies: take whatever is new
if (sizeof($cookies) > 0) {
$this->debug('Setting new cookie(s)');
$this->cookies = $cookies;
}
return true;
}
if (sizeof($cookies) == 0) {
// no new cookies: keep what we've got
return true;
}
// merge
foreach ($cookies as $newCookie) {
if (!is_array($newCookie)) {
continue;
}
if ((!isset($newCookie['name'])) || (!isset($newCookie['
value']))) {
continue;
}
$newName = $newCookie['name'];
$found = false;
for ($i = 0; $i < count($this->cookies); $i++) {
$cookie = $this->cookies[$i];
if (!is_array($cookie)) {
continue;
}
if (!isset($cookie['name'])) {
continue;
}
if ($newName != $cookie['name']) {
continue;
}
$newDomain = isset($newCookie['domain']) ? $newC
ookie['domain'] : 'NODOMAIN';
$domain = isset($cookie['domain']) ? $cookie['do
main'] : 'NODOMAIN';
if ($newDomain != $domain) {
continue;
}
$newPath = isset($newCookie['path']) ? $newCooki
e['path'] : 'NOPATH';
$path = isset($cookie['path']) ? $cookie['path']
: 'NOPATH';
if ($newPath != $path) {
continue;
}
$this->cookies[$i] = $newCookie;
$found = true;
$this->debug('Update cookie ' . $newName . '=' .
$newCookie['value']);
break;
}
if (! $found) {
$this->debug('Add cookie ' . $newName . '=' . $n
ewCookie['value']);
$this->cookies[] = $newCookie;
}
}
return true;
}
}
?>

webservicesclientproductlist.php
<html>
<head><title>Array of Struct</title>
<link href="admin-style.css" rel="stylesheet" type="text/css">
</head>
<body>
<?php
require("nusoap.php");
$url="http://localhost/TB_XML/webservices_produk.php";
$client=new soapclient($url);
$result=$client->call("getProductList",array());
$err=$client->getError();
if($err){
echo "<p><b>ERROR! ".$client->getError()."</p></b>";
}
else{
if($result!=null){
echo '<table width="66%" border="0" align="left" class="
brd_kiri_kanan_bawah">
<tr bgcolor="#993300" class="text_table" >
<td width="9%" align="center" valign="middle" bgcolor="#993300">produk I
D</td>
<td width="14%" align="center" valign="middle" bgcolor="#993300">Merk</t
d>
<td width="17%" align="center" valign="middle" bgcolor="#993300">Tipe</t
d>
<td width="14%" align="center" valign="middle" bgcolor="#993300">Harga</
td>
</tr>';
for($i=0;$i<sizeof($result);$i++){
echo '<tr class=text_normal onmouseover=this.cla
ssName="active";
onmouseout=this.className="inactive";>
<td align="left" valign="middle">'.$result[$i]['
produk_id'].'</td>
<td align="left" valign="middle">'.$result[$i]['
merk'].'</td>
<td align="left" valign="middle">'.$result[$i]['
tipe'].'</td>
<td align="left" valign="middle">'.$result[$i]['
harga'].'</td>
</tr>';
}
echo '</table>';
}
else{
echo "<p><b>Kode buku tidak ditemukan!</b></p>";
}
}
?>
</body>
</html>

You might also like