+++ /dev/null
-<?php\r
-\r
-/*\r
-$Id: nusoap.php,v 1.114 2007/11/06 15:17:46 snichol Exp $\r
-\r
-NuSOAP - Web Services Toolkit for PHP\r
-\r
-Copyright (c) 2002 NuSphere Corporation\r
-\r
-This library is free software; you can redistribute it and/or\r
-modify it under the terms of the GNU Lesser General Public\r
-License as published by the Free Software Foundation; either\r
-version 2.1 of the License, or (at your option) any later version.\r
-\r
-This library is distributed in the hope that it will be useful,\r
-but WITHOUT ANY WARRANTY; without even the implied warranty of\r
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU\r
-Lesser General Public License for more details.\r
-\r
-You should have received a copy of the GNU Lesser General Public\r
-License along with this library; if not, write to the Free Software\r
-Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA\r
-\r
-The NuSOAP project home is:\r
-http://sourceforge.net/projects/nusoap/\r
-\r
-The primary support for NuSOAP is the mailing list:\r
-nusoap-general@lists.sourceforge.net\r
-\r
-If you have any questions or comments, please email:\r
-\r
-Dietrich Ayala\r
-dietrich@ganx4.com\r
-http://dietrich.ganx4.com/nusoap\r
-\r
-NuSphere Corporation\r
-http://www.nusphere.com\r
-\r
-*/\r
-\r
-/*\r
- * Some of the standards implmented in whole or part by NuSOAP:\r
- *\r
- * SOAP 1.1 (http://www.w3.org/TR/2000/NOTE-SOAP-20000508/)\r
- * WSDL 1.1 (http://www.w3.org/TR/2001/NOTE-wsdl-20010315)\r
- * SOAP Messages With Attachments (http://www.w3.org/TR/SOAP-attachments)\r
- * XML 1.0 (http://www.w3.org/TR/2006/REC-xml-20060816/)\r
- * Namespaces in XML 1.0 (http://www.w3.org/TR/2006/REC-xml-names-20060816/)\r
- * XML Schema 1.0 (http://www.w3.org/TR/xmlschema-0/)\r
- * RFC 2045 Multipurpose Internet Mail Extensions (MIME) Part One: Format of Internet Message Bodies\r
- * RFC 2068 Hypertext Transfer Protocol -- HTTP/1.1\r
- * RFC 2617 HTTP Authentication: Basic and Digest Access Authentication\r
- */\r
- \r
-/*\r
- * \r
- * This is a modified version of nusoap for usage of Axis2\r
- * for some reason it does not marshall the SOAP Body correct for Axis2 on Linux Platforms\r
- * \r
- */\r
-\r
-/* load classes\r
-\r
-// necessary classes\r
-require_once('class.soapclient.php');\r
-require_once('class.soap_val.php');\r
-require_once('class.soap_parser.php');\r
-require_once('class.soap_fault.php');\r
-\r
-// transport classes\r
-require_once('class.soap_transport_http.php');\r
-\r
-// optional add-on classes\r
-require_once('class.xmlschema.php');\r
-require_once('class.wsdl.php');\r
-\r
-// server class\r
-require_once('class.soap_server.php');*/\r
-\r
-// class variable emulation\r
-// cf. http://www.webkreator.com/php/techniques/php-static-class-variables.html\r
-$GLOBALS['_transient']['static']['nusoap_base']->globalDebugLevel = 9;\r
-\r
-/**\r
-*\r
-* nusoap_base\r
-*\r
-* @author Dietrich Ayala <dietrich@ganx4.com>\r
-* @author Scott Nichol <snichol@users.sourceforge.net>\r
-* @version $Id: nusoap.php,v 1.114 2007/11/06 15:17:46 snichol Exp $\r
-* @access public\r
-*/\r
-class nusoap_base {\r
- /**\r
- * Identification for HTTP headers.\r
- *\r
- * @var string\r
- * @access private\r
- */\r
- var $title = 'NuSOAP';\r
- /**\r
- * Version for HTTP headers.\r
- *\r
- * @var string\r
- * @access private\r
- */\r
- var $version = '0.7.3';\r
- /**\r
- * CVS revision for HTTP headers.\r
- *\r
- * @var string\r
- * @access private\r
- */\r
- var $revision = '$Revision: 1.114 $';\r
- /**\r
- * Current error string (manipulated by getError/setError)\r
- *\r
- * @var string\r
- * @access private\r
- */\r
- var $error_str = '';\r
- /**\r
- * Current debug string (manipulated by debug/appendDebug/clearDebug/getDebug/getDebugAsXMLComment)\r
- *\r
- * @var string\r
- * @access private\r
- */\r
- var $debug_str = '';\r
- /**\r
- * toggles automatic encoding of special characters as entities\r
- * (should always be true, I think)\r
- *\r
- * @var boolean\r
- * @access private\r
- */\r
- var $charencoding = true;\r
- /**\r
- * the debug level for this instance\r
- *\r
- * @var integer\r
- * @access private\r
- */\r
- var $debugLevel;\r
-\r
- /**\r
- * set schema version\r
- *\r
- * @var string\r
- * @access public\r
- */\r
- var $XMLSchemaVersion = 'http://www.w3.org/2001/XMLSchema';\r
- \r
- /**\r
- * charset encoding for outgoing messages\r
- *\r
- * @var string\r
- * @access public\r
- */\r
- var $soap_defencoding = 'ISO-8859-1';\r
- //var $soap_defencoding = 'UTF-8';\r
-\r
- /**\r
- * namespaces in an array of prefix => uri\r
- *\r
- * this is "seeded" by a set of constants, but it may be altered by code\r
- *\r
- * @var array\r
- * @access public\r
- */\r
- var $namespaces = array(\r
- 'SOAP-ENV' => 'http://schemas.xmlsoap.org/soap/envelope/',\r
- 'xsd' => 'http://www.w3.org/2001/XMLSchema',\r
- 'xsi' => 'http://www.w3.org/2001/XMLSchema-instance',\r
- 'SOAP-ENC' => 'http://schemas.xmlsoap.org/soap/encoding/'\r
- );\r
-\r
- /**\r
- * namespaces used in the current context, e.g. during serialization\r
- *\r
- * @var array\r
- * @access private\r
- */\r
- var $usedNamespaces = array();\r
-\r
- /**\r
- * XML Schema types in an array of uri => (array of xml type => php type)\r
- * is this legacy yet?\r
- * no, this is used by the nusoap_xmlschema class to verify type => namespace mappings.\r
- * @var array\r
- * @access public\r
- */\r
- var $typemap = array(\r
- 'http://www.w3.org/2001/XMLSchema' => array(\r
- 'string'=>'string','boolean'=>'boolean','float'=>'double','double'=>'double','decimal'=>'double',\r
- 'duration'=>'','dateTime'=>'string','time'=>'string','date'=>'string','gYearMonth'=>'',\r
- 'gYear'=>'','gMonthDay'=>'','gDay'=>'','gMonth'=>'','hexBinary'=>'string','base64Binary'=>'string',\r
- // abstract "any" types\r
- 'anyType'=>'string','anySimpleType'=>'string',\r
- // derived datatypes\r
- 'normalizedString'=>'string','token'=>'string','language'=>'','NMTOKEN'=>'','NMTOKENS'=>'','Name'=>'','NCName'=>'','ID'=>'',\r
- 'IDREF'=>'','IDREFS'=>'','ENTITY'=>'','ENTITIES'=>'','integer'=>'integer','nonPositiveInteger'=>'integer',\r
- 'negativeInteger'=>'integer','long'=>'integer','int'=>'integer','short'=>'integer','byte'=>'integer','nonNegativeInteger'=>'integer',\r
- 'unsignedLong'=>'','unsignedInt'=>'','unsignedShort'=>'','unsignedByte'=>'','positiveInteger'=>''),\r
- 'http://www.w3.org/2000/10/XMLSchema' => array(\r
- 'i4'=>'','int'=>'integer','boolean'=>'boolean','string'=>'string','double'=>'double',\r
- 'float'=>'double','dateTime'=>'string',\r
- 'timeInstant'=>'string','base64Binary'=>'string','base64'=>'string','ur-type'=>'array'),\r
- 'http://www.w3.org/1999/XMLSchema' => array(\r
- 'i4'=>'','int'=>'integer','boolean'=>'boolean','string'=>'string','double'=>'double',\r
- 'float'=>'double','dateTime'=>'string',\r
- 'timeInstant'=>'string','base64Binary'=>'string','base64'=>'string','ur-type'=>'array'),\r
- 'http://soapinterop.org/xsd' => array('SOAPStruct'=>'struct'),\r
- 'http://schemas.xmlsoap.org/soap/encoding/' => array('base64'=>'string','array'=>'array','Array'=>'array'),\r
- 'http://xml.apache.org/xml-soap' => array('Map')\r
- );\r
-\r
- /**\r
- * XML entities to convert\r
- *\r
- * @var array\r
- * @access public\r
- * @deprecated\r
- * @see expandEntities\r
- */\r
- var $xmlEntities = array('quot' => '"','amp' => '&',\r
- 'lt' => '<','gt' => '>','apos' => "'");\r
-\r
- /**\r
- * constructor\r
- *\r
- * @access public\r
- */\r
- function nusoap_base() {\r
- $this->debugLevel = $GLOBALS['_transient']['static']['nusoap_base']->globalDebugLevel;\r
- }\r
-\r
- /**\r
- * gets the global debug level, which applies to future instances\r
- *\r
- * @return integer Debug level 0-9, where 0 turns off\r
- * @access public\r
- */\r
- function getGlobalDebugLevel() {\r
- return $GLOBALS['_transient']['static']['nusoap_base']->globalDebugLevel;\r
- }\r
-\r
- /**\r
- * sets the global debug level, which applies to future instances\r
- *\r
- * @param int $level Debug level 0-9, where 0 turns off\r
- * @access public\r
- */\r
- function setGlobalDebugLevel($level) {\r
- $GLOBALS['_transient']['static']['nusoap_base']->globalDebugLevel = $level;\r
- }\r
-\r
- /**\r
- * gets the debug level for this instance\r
- *\r
- * @return int Debug level 0-9, where 0 turns off\r
- * @access public\r
- */\r
- function getDebugLevel() {\r
- return $this->debugLevel;\r
- }\r
-\r
- /**\r
- * sets the debug level for this instance\r
- *\r
- * @param int $level Debug level 0-9, where 0 turns off\r
- * @access public\r
- */\r
- function setDebugLevel($level) {\r
- $this->debugLevel = $level;\r
- }\r
-\r
- /**\r
- * adds debug data to the instance debug string with formatting\r
- *\r
- * @param string $string debug data\r
- * @access private\r
- */\r
- function debug($string){\r
- if ($this->debugLevel > 0) {\r
- $this->appendDebug($this->getmicrotime().' '.get_class($this).": $string\n");\r
- }\r
- }\r
-\r
- /**\r
- * adds debug data to the instance debug string without formatting\r
- *\r
- * @param string $string debug data\r
- * @access public\r
- */\r
- function appendDebug($string){\r
- //echo "## appendDebug: ".$string."<br/>";\r
- if ($this->debugLevel > 0) {\r
- // it would be nice to use a memory stream here to use\r
- // memory more efficiently\r
- $this->debug_str .= $string;\r
- }\r
- }\r
-\r
- /**\r
- * clears the current debug data for this instance\r
- *\r
- * @access public\r
- */\r
- function clearDebug() {\r
- // it would be nice to use a memory stream here to use\r
- // memory more efficiently\r
- $this->debug_str = '';\r
- }\r
-\r
- /**\r
- * gets the current debug data for this instance\r
- *\r
- * @return debug data\r
- * @access public\r
- */\r
- function &getDebug() {\r
- // it would be nice to use a memory stream here to use\r
- // memory more efficiently\r
- return $this->debug_str;\r
- }\r
-\r
- /**\r
- * gets the current debug data for this instance as an XML comment\r
- * this may change the contents of the debug data\r
- *\r
- * @return debug data as an XML comment\r
- * @access public\r
- */\r
- function &getDebugAsXMLComment() {\r
- // it would be nice to use a memory stream here to use\r
- // memory more efficiently\r
- while (strpos($this->debug_str, '--')) {\r
- $this->debug_str = str_replace('--', '- -', $this->debug_str);\r
- }\r
- $ret = "<!--\n" . $this->debug_str . "\n-->";\r
- return $ret;\r
- }\r
-\r
- /**\r
- * expands entities, e.g. changes '<' to '<'.\r
- *\r
- * @param string $val The string in which to expand entities.\r
- * @access private\r
- */\r
- function expandEntities($val) {\r
- if ($this->charencoding) {\r
- $val = str_replace('&', '&', $val);\r
- $val = str_replace("'", ''', $val);\r
- $val = str_replace('"', '"', $val);\r
- $val = str_replace('<', '<', $val);\r
- $val = str_replace('>', '>', $val);\r
- }\r
- return $val;\r
- }\r
-\r
- /**\r
- * returns error string if present\r
- *\r
- * @return mixed error string or false\r
- * @access public\r
- */\r
- function getError(){\r
- if($this->error_str != ''){\r
- return $this->error_str;\r
- }\r
- return false;\r
- }\r
-\r
- /**\r
- * sets error string\r
- *\r
- * @return boolean $string error string\r
- * @access private\r
- */\r
- function setError($str){\r
- $this->error_str = $str;\r
- }\r
-\r
- /**\r
- * detect if array is a simple array or a struct (associative array)\r
- *\r
- * @param mixed $val The PHP array\r
- * @return string (arraySimple|arrayStruct)\r
- * @access private\r
- */\r
- function isArraySimpleOrStruct($val) {\r
- $keyList = array_keys($val);\r
- foreach ($keyList as $keyListValue) {\r
- if (!is_int($keyListValue)) {\r
- return 'arrayStruct';\r
- }\r
- }\r
- return 'arraySimple';\r
- }\r
-\r
- /**\r
- * serializes PHP values in accordance w/ section 5. Type information is\r
- * not serialized if $use == 'literal'.\r
- *\r
- * @param mixed $val The value to serialize\r
- * @param string $name The name (local part) of the XML element\r
- * @param string $type The XML schema type (local part) for the element\r
- * @param string $name_ns The namespace for the name of the XML element\r
- * @param string $type_ns The namespace for the type of the element\r
- * @param array $attributes The attributes to serialize as name=>value pairs\r
- * @param string $use The WSDL "use" (encoded|literal)\r
- * @param boolean $soapval Whether this is called from soapval.\r
- * @return string The serialized element, possibly with child elements\r
- * @access public\r
- */\r
- function serialize_val($val,$name=false,$type=false,$name_ns=false,$type_ns=false,$attributes=false,$use='encoded',$soapval=false) {\r
- $this->debug("in serialize_val: name=$name, type=$type, name_ns=$name_ns, type_ns=$type_ns, use=$use, soapval=$soapval");\r
- $this->appendDebug('value=' . $this->varDump($val));\r
- $this->appendDebug('attributes=' . $this->varDump($attributes));\r
- \r
- if (is_object($val) && get_class($val) == 'soapval' && (! $soapval)) {\r
- $this->debug("serialize_val: serialize soapval");\r
- $xml = $val->serialize($use);\r
- $this->appendDebug($val->getDebug());\r
- $val->clearDebug();\r
- $this->debug("serialize_val of soapval returning $xml");\r
- return $xml;\r
- }\r
- // force valid name if necessary\r
- if (is_numeric($name)) {\r
- $name = '__numeric_' . $name;\r
- } elseif (! $name) {\r
- $name = 'noname';\r
- }\r
- // if name has ns, add ns prefix to name\r
- $xmlns = '';\r
- if($name_ns){\r
- $prefix = 'nu'.rand(1000,9999);\r
- $name = $prefix.':'.$name;\r
- $xmlns .= " xmlns:$prefix=\"$name_ns\"";\r
- }\r
- // if type is prefixed, create type prefix\r
- if($type_ns != '' && $type_ns == $this->namespaces['xsd']){\r
- // need to fix this. shouldn't default to xsd if no ns specified\r
- // w/o checking against typemap\r
- $type_prefix = 'xsd';\r
- } elseif($type_ns){\r
- $type_prefix = 'ns'.rand(1000,9999);\r
- $xmlns .= " xmlns:$type_prefix=\"$type_ns\"";\r
- }\r
- // serialize attributes if present\r
- $atts = '';\r
- if($attributes){\r
- foreach($attributes as $k => $v){\r
- $atts .= " $k=\"".$this->expandEntities($v).'"';\r
- }\r
- }\r
- // serialize null value\r
- if (is_null($val)) {\r
- $this->debug("serialize_val: serialize null");\r
- if ($use == 'literal') {\r
- // TODO: depends on minOccurs\r
- $xml = "<$name$xmlns$atts/>";\r
- $this->debug("serialize_val returning $xml");\r
- return $xml;\r
- } else {\r
- if (isset($type) && isset($type_prefix)) {\r
- $type_str = " xsi:type=\"$type_prefix:$type\"";\r
- } else {\r
- $type_str = '';\r
- }\r
- $xml = "<$name$xmlns$type_str$atts xsi:nil=\"true\"/>";\r
- $this->debug("serialize_val returning $xml");\r
- return $xml;\r
- }\r
- }\r
- // serialize if an xsd built-in primitive type\r
- if($type != '' && isset($this->typemap[$this->XMLSchemaVersion][$type])){\r
- $this->debug("serialize_val: serialize xsd built-in primitive type");\r
- if (is_bool($val)) {\r
- if ($type == 'boolean') {\r
- $val = $val ? 'true' : 'false';\r
- } elseif (! $val) {\r
- $val = 0;\r
- }\r
- } else if (is_string($val)) {\r
- $val = $this->expandEntities($val);\r
- }\r
- if ($use == 'literal') {\r
- $xml = "<$name$xmlns$atts>$val</$name>";\r
- $this->debug("serialize_val returning $xml");\r
- return $xml;\r
- } else {\r
- $xml = "<$name$xmlns xsi:type=\"xsd:$type\"$atts>$val</$name>";\r
- $this->debug("serialize_val returning $xml");\r
- return $xml;\r
- }\r
- }\r
- // detect type and serialize\r
- $xml = '';\r
- switch(true) {\r
- case (is_bool($val) || $type == 'boolean'):\r
- $this->debug("serialize_val: serialize boolean");\r
- if ($type == 'boolean') {\r
- $val = $val ? 'true' : 'false';\r
- } elseif (! $val) {\r
- $val = 0;\r
- }\r
- if ($use == 'literal') {\r
- $xml .= "<$name$xmlns$atts>$val</$name>";\r
- } else {\r
- $xml .= "<$name$xmlns xsi:type=\"xsd:boolean\"$atts>$val</$name>";\r
- }\r
- break;\r
- case (is_int($val) || is_long($val) || $type == 'int'):\r
- $this->debug("serialize_val: serialize int");\r
- if ($use == 'literal') {\r
- $xml .= "<$name$xmlns$atts>$val</$name>";\r
- } else {\r
- $xml .= "<$name$xmlns xsi:type=\"xsd:int\"$atts>$val</$name>";\r
- }\r
- break;\r
- case (is_float($val)|| is_double($val) || $type == 'float'):\r
- $this->debug("serialize_val: serialize float");\r
- if ($use == 'literal') {\r
- $xml .= "<$name$xmlns$atts>$val</$name>";\r
- } else {\r
- $xml .= "<$name$xmlns xsi:type=\"xsd:float\"$atts>$val</$name>";\r
- }\r
- break;\r
- case (is_string($val) || $type == 'string'):\r
- $this->debug("serialize_val: serialize string");\r
- $val = $this->expandEntities($val);\r
- if ($use == 'literal') {\r
- $xml .= "<$name$xmlns$atts>$val</$name>";\r
- } else {\r
- $xml .= "<$name$xmlns xsi:type=\"xsd:string\"$atts>$val</$name>";\r
- }\r
- break;\r
- case is_object($val):\r
- $this->debug("serialize_val: serialize object");\r
- if (get_class($val) == 'soapval') {\r
- $this->debug("serialize_val: serialize soapval object");\r
- $pXml = $val->serialize($use);\r
- $this->appendDebug($val->getDebug());\r
- $val->clearDebug();\r
- } else {\r
- if (! $name) {\r
- $name = get_class($val);\r
- $this->debug("In serialize_val, used class name $name as element name");\r
- } else {\r
- $this->debug("In serialize_val, do not override name $name for element name for class " . get_class($val));\r
- }\r
- foreach(get_object_vars($val) as $k => $v){\r
- $pXml = isset($pXml) ? $pXml.$this->serialize_val($v,$k,false,false,false,false,$use) : $this->serialize_val($v,$k,false,false,false,false,$use);\r
- }\r
- }\r
- if(isset($type) && isset($type_prefix)){\r
- $type_str = " xsi:type=\"$type_prefix:$type\"";\r
- } else {\r
- $type_str = '';\r
- }\r
- if ($use == 'literal') {\r
- $xml .= "<$name$xmlns$atts>$pXml</$name>";\r
- } else {\r
- $xml .= "<$name$xmlns$type_str$atts>$pXml</$name>";\r
- }\r
- break;\r
- break;\r
- case (is_array($val) || $type):\r
- // detect if struct or array\r
- $valueType = $this->isArraySimpleOrStruct($val);\r
- if($valueType=='arraySimple' || ereg('^ArrayOf',$type)){\r
- $this->debug("serialize_val: serialize array");\r
- $i = 0;\r
- if(is_array($val) && count($val)> 0){\r
- foreach($val as $v){\r
- if(is_object($v) && get_class($v) == 'soapval'){\r
- $tt_ns = $v->type_ns;\r
- $tt = $v->type;\r
- } elseif (is_array($v)) {\r
- $tt = $this->isArraySimpleOrStruct($v);\r
- } else {\r
- $tt = gettype($v);\r
- }\r
- $array_types[$tt] = 1;\r
- // TODO: for literal, the name should be $name\r
- $xml .= $this->serialize_val($v,'item',false,false,false,false,$use);\r
- ++$i;\r
- }\r
- if(count($array_types) > 1){\r
- $array_typename = 'xsd:anyType';\r
- } elseif(isset($tt) && isset($this->typemap[$this->XMLSchemaVersion][$tt])) {\r
- if ($tt == 'integer') {\r
- $tt = 'int';\r
- }\r
- $array_typename = 'xsd:'.$tt;\r
- } elseif(isset($tt) && $tt == 'arraySimple'){\r
- $array_typename = 'SOAP-ENC:Array';\r
- } elseif(isset($tt) && $tt == 'arrayStruct'){\r
- $array_typename = 'unnamed_struct_use_soapval';\r
- } else {\r
- // if type is prefixed, create type prefix\r
- if ($tt_ns != '' && $tt_ns == $this->namespaces['xsd']){\r
- $array_typename = 'xsd:' . $tt;\r
- } elseif ($tt_ns) {\r
- $tt_prefix = 'ns' . rand(1000, 9999);\r
- $array_typename = "$tt_prefix:$tt";\r
- $xmlns .= " xmlns:$tt_prefix=\"$tt_ns\"";\r
- } else {\r
- $array_typename = $tt;\r
- }\r
- }\r
- $array_type = $i;\r
- if ($use == 'literal') {\r
- $type_str = '';\r
- } else if (isset($type) && isset($type_prefix)) {\r
- $type_str = " xsi:type=\"$type_prefix:$type\"";\r
- } else {\r
- $type_str = " xsi:type=\"SOAP-ENC:Array\" SOAP-ENC:arrayType=\"".$array_typename."[$array_type]\"";\r
- }\r
- // empty array\r
- } else {\r
- if ($use == 'literal') {\r
- $type_str = '';\r
- } else if (isset($type) && isset($type_prefix)) {\r
- $type_str = " xsi:type=\"$type_prefix:$type\"";\r
- } else {\r
- $type_str = " xsi:type=\"SOAP-ENC:Array\" SOAP-ENC:arrayType=\"xsd:anyType[0]\"";\r
- }\r
- }\r
- // TODO: for array in literal, there is no wrapper here\r
- $xml = "<$name$xmlns$type_str$atts>".$xml."</$name>";\r
- } else {\r
- // got a struct\r
- $this->debug("serialize_val: serialize struct");\r
- if(isset($type) && isset($type_prefix)){\r
- $type_str = " xsi:type=\"$type_prefix:$type\"";\r
- } else {\r
- $type_str = '';\r
- }\r
- if ($use == 'literal') {\r
- $xml .= "<$name$xmlns$atts>";\r
- } else {\r
- $xml .= "<$name$xmlns$type_str$atts>";\r
- }\r
- foreach($val as $k => $v){\r
- // Apache Map\r
- if ($type == 'Map' && $type_ns == 'http://xml.apache.org/xml-soap') {\r
- $xml .= '<item>';\r
- $xml .= $this->serialize_val($k,'key',false,false,false,false,$use);\r
- $xml .= $this->serialize_val($v,'value',false,false,false,false,$use);\r
- $xml .= '</item>';\r
- } else {\r
- $xml .= $this->serialize_val($v,$k,false,false,false,false,$use);\r
- }\r
- }\r
- $xml .= "</$name>";\r
- }\r
- break;\r
- default:\r
- $this->debug("serialize_val: serialize unknown");\r
- $xml .= 'not detected, got '.gettype($val).' for '.$val;\r
- break;\r
- }\r
- $this->debug("serialize_val returning $xml");\r
- return $xml;\r
- }\r
-\r
- /**\r
- * serializes a message\r
- *\r
- * @param string $body the XML of the SOAP body\r
- * @param mixed $headers optional string of XML with SOAP header content, or array of soapval objects for SOAP headers, or associative array\r
- * @param array $namespaces optional the namespaces used in generating the body and headers\r
- * @param string $style optional (rpc|document)\r
- * @param string $use optional (encoded|literal)\r
- * @param string $encodingStyle optional (usually 'http://schemas.xmlsoap.org/soap/encoding/' for encoded)\r
- * @return string the message\r
- * @access public\r
- */\r
- function serializeEnvelope($body,$headers=false,$namespaces=array(),$style='rpc',$use='encoded',$encodingStyle='http://schemas.xmlsoap.org/soap/encoding/'){\r
- // TODO: add an option to automatically run utf8_encode on $body and $headers\r
- // if $this->soap_defencoding is UTF-8. Not doing this automatically allows\r
- // one to send arbitrary UTF-8 characters, not just characters that map to ISO-8859-1\r
-\r
- $this->debug("In serializeEnvelope length=" . strlen($body) . " body (max 1000 characters)=" . substr($body, 0, 1000) . " style=$style use=$use encodingStyle=$encodingStyle");\r
- $this->debug("headers:");\r
- $this->appendDebug($this->varDump($headers));\r
- $this->debug("namespaces:");\r
- $this->appendDebug($this->varDump($namespaces));\r
-\r
- // serialize namespaces\r
- $ns_string = '';\r
- foreach(array_merge($this->namespaces,$namespaces) as $k => $v){\r
- $ns_string .= " xmlns:$k=\"$v\"";\r
- }\r
- if($encodingStyle) {\r
- $ns_string = " SOAP-ENV:encodingStyle=\"$encodingStyle\"$ns_string";\r
- }\r
-\r
- // serialize headers\r
- if($headers){\r
- if (is_array($headers)) {\r
- $xml = '';\r
- foreach ($headers as $k => $v) {\r
- if (is_object($v) && get_class($v) == 'soapval') {\r
- $xml .= $this->serialize_val($v, false, false, false, false, false, $use);\r
- } else {\r
- $xml .= $this->serialize_val($v, $k, false, false, false, false, $use);\r
- }\r
- }\r
- $headers = $xml;\r
- $this->debug("In serializeEnvelope, serialized array of headers to $headers");\r
- }\r
- $headers = "<SOAP-ENV:Header>".$headers."</SOAP-ENV:Header>";\r
- }\r
- //echo "####<br/>";\r
- //echo $body;\r
- //echo "<br/>####<br/>";\r
- // serialize envelope\r
- return\r
- '<?xml version="1.0" encoding="'.$this->soap_defencoding .'"?'.">".\r
- '<SOAP-ENV:Envelope'.$ns_string.">".\r
- $headers.\r
- "<SOAP-ENV:Body>".\r
- $body.\r
- "</SOAP-ENV:Body>".\r
- "</SOAP-ENV:Envelope>";\r
- }\r
-\r
- /**\r
- * formats a string to be inserted into an HTML stream\r
- *\r
- * @param string $str The string to format\r
- * @return string The formatted string\r
- * @access public\r
- * @deprecated\r
- */\r
- function formatDump($str){\r
- $str = htmlspecialchars($str);\r
- return nl2br($str);\r
- }\r
-\r
- /**\r
- * contracts (changes namespace to prefix) a qualified name\r
- *\r
- * @param string $qname qname\r
- * @return string contracted qname\r
- * @access private\r
- */\r
- function contractQname($qname){\r
- // get element namespace\r
- //$this->xdebug("Contract $qname");\r
- if (strrpos($qname, ':')) {\r
- // get unqualified name\r
- $name = substr($qname, strrpos($qname, ':') + 1);\r
- // get ns\r
- $ns = substr($qname, 0, strrpos($qname, ':'));\r
- $p = $this->getPrefixFromNamespace($ns);\r
- if ($p) {\r
- return $p . ':' . $name;\r
- }\r
- return $qname;\r
- } else {\r
- return $qname;\r
- }\r
- }\r
-\r
- /**\r
- * expands (changes prefix to namespace) a qualified name\r
- *\r
- * @param string $qname qname\r
- * @return string expanded qname\r
- * @access private\r
- */\r
- function expandQname($qname){\r
- // get element prefix\r
- if(strpos($qname,':') && !ereg('^http://',$qname)){\r
- // get unqualified name\r
- $name = substr(strstr($qname,':'),1);\r
- // get ns prefix\r
- $prefix = substr($qname,0,strpos($qname,':'));\r
- if(isset($this->namespaces[$prefix])){\r
- return $this->namespaces[$prefix].':'.$name;\r
- } else {\r
- return $qname;\r
- }\r
- } else {\r
- return $qname;\r
- }\r
- }\r
-\r
- /**\r
- * returns the local part of a prefixed string\r
- * returns the original string, if not prefixed\r
- *\r
- * @param string $str The prefixed string\r
- * @return string The local part\r
- * @access public\r
- */\r
- function getLocalPart($str){\r
- if($sstr = strrchr($str,':')){\r
- // get unqualified name\r
- return substr( $sstr, 1 );\r
- } else {\r
- return $str;\r
- }\r
- }\r
-\r
- /**\r
- * returns the prefix part of a prefixed string\r
- * returns false, if not prefixed\r
- *\r
- * @param string $str The prefixed string\r
- * @return mixed The prefix or false if there is no prefix\r
- * @access public\r
- */\r
- function getPrefix($str){\r
- if($pos = strrpos($str,':')){\r
- // get prefix\r
- return substr($str,0,$pos);\r
- }\r
- return false;\r
- }\r
-\r
- /**\r
- * pass it a prefix, it returns a namespace\r
- *\r
- * @param string $prefix The prefix\r
- * @return mixed The namespace, false if no namespace has the specified prefix\r
- * @access public\r
- */\r
- function getNamespaceFromPrefix($prefix){\r
- if (isset($this->namespaces[$prefix])) {\r
- return $this->namespaces[$prefix];\r
- }\r
- //$this->setError("No namespace registered for prefix '$prefix'");\r
- return false;\r
- }\r
-\r
- /**\r
- * returns the prefix for a given namespace (or prefix)\r
- * or false if no prefixes registered for the given namespace\r
- *\r
- * @param string $ns The namespace\r
- * @return mixed The prefix, false if the namespace has no prefixes\r
- * @access public\r
- */\r
- function getPrefixFromNamespace($ns) {\r
- foreach ($this->namespaces as $p => $n) {\r
- if ($ns == $n || $ns == $p) {\r
- $this->usedNamespaces[$p] = $n;\r
- return $p;\r
- }\r
- }\r
- return false;\r
- }\r
-\r
- /**\r
- * returns the time in ODBC canonical form with microseconds\r
- *\r
- * @return string The time in ODBC canonical form with microseconds\r
- * @access public\r
- */\r
- function getmicrotime() {\r
- if (function_exists('gettimeofday')) {\r
- $tod = gettimeofday();\r
- $sec = $tod['sec'];\r
- $usec = $tod['usec'];\r
- } else {\r
- $sec = time();\r
- $usec = 0;\r
- }\r
- return strftime('%Y-%m-%d %H:%M:%S', $sec) . '.' . sprintf('%06d', $usec);\r
- }\r
-\r
- /**\r
- * Returns a string with the output of var_dump\r
- *\r
- * @param mixed $data The variable to var_dump\r
- * @return string The output of var_dump\r
- * @access public\r
- */\r
- function varDump($data) {\r
- ob_start();\r
- var_dump($data);\r
- $ret_val = ob_get_contents();\r
- ob_end_clean();\r
- return $ret_val;\r
- }\r
-\r
- /**\r
- * represents the object as a string\r
- *\r
- * @return string\r
- * @access public\r
- */\r
- function __toString() {\r
- return $this->varDump($this);\r
- }\r
-}\r
-\r
-// XML Schema Datatype Helper Functions\r
-\r
-//xsd:dateTime helpers\r
-\r
-/**\r
-* convert unix timestamp to ISO 8601 compliant date string\r
-*\r
-* @param string $timestamp Unix time stamp\r
-* @param boolean $utc Whether the time stamp is UTC or local\r
-* @access public\r
-*/\r
-function timestamp_to_iso8601($timestamp,$utc=true){\r
- $datestr = date('Y-m-d\TH:i:sO',$timestamp);\r
- if($utc){\r
- $eregStr =\r
- '([0-9]{4})-'. // centuries & years CCYY-\r
- '([0-9]{2})-'. // months MM-\r
- '([0-9]{2})'. // days DD\r
- 'T'. // separator T\r
- '([0-9]{2}):'. // hours hh:\r
- '([0-9]{2}):'. // minutes mm:\r
- '([0-9]{2})(\.[0-9]*)?'. // seconds ss.ss...\r
- '(Z|[+\-][0-9]{2}:?[0-9]{2})?'; // Z to indicate UTC, -/+HH:MM:SS.SS... for local tz's\r
-\r
- if(ereg($eregStr,$datestr,$regs)){\r
- return sprintf('%04d-%02d-%02dT%02d:%02d:%02dZ',$regs[1],$regs[2],$regs[3],$regs[4],$regs[5],$regs[6]);\r
- }\r
- return false;\r
- } else {\r
- return $datestr;\r
- }\r
-}\r
-\r
-/**\r
-* convert ISO 8601 compliant date string to unix timestamp\r
-*\r
-* @param string $datestr ISO 8601 compliant date string\r
-* @access public\r
-*/\r
-function iso8601_to_timestamp($datestr){\r
- $eregStr =\r
- '([0-9]{4})-'. // centuries & years CCYY-\r
- '([0-9]{2})-'. // months MM-\r
- '([0-9]{2})'. // days DD\r
- 'T'. // separator T\r
- '([0-9]{2}):'. // hours hh:\r
- '([0-9]{2}):'. // minutes mm:\r
- '([0-9]{2})(\.[0-9]+)?'. // seconds ss.ss...\r
- '(Z|[+\-][0-9]{2}:?[0-9]{2})?'; // Z to indicate UTC, -/+HH:MM:SS.SS... for local tz's\r
- if(ereg($eregStr,$datestr,$regs)){\r
- // not utc\r
- if($regs[8] != 'Z'){\r
- $op = substr($regs[8],0,1);\r
- $h = substr($regs[8],1,2);\r
- $m = substr($regs[8],strlen($regs[8])-2,2);\r
- if($op == '-'){\r
- $regs[4] = $regs[4] + $h;\r
- $regs[5] = $regs[5] + $m;\r
- } elseif($op == '+'){\r
- $regs[4] = $regs[4] - $h;\r
- $regs[5] = $regs[5] - $m;\r
- }\r
- }\r
- return gmmktime($regs[4], $regs[5], $regs[6], $regs[2], $regs[3], $regs[1]);\r
-// return strtotime("$regs[1]-$regs[2]-$regs[3] $regs[4]:$regs[5]:$regs[6]Z");\r
- } else {\r
- return false;\r
- }\r
-}\r
-\r
-/**\r
-* sleeps some number of microseconds\r
-*\r
-* @param string $usec the number of microseconds to sleep\r
-* @access public\r
-* @deprecated\r
-*/\r
-function usleepWindows($usec)\r
-{\r
- $start = gettimeofday();\r
- \r
- do\r
- {\r
- $stop = gettimeofday();\r
- $timePassed = 1000000 * ($stop['sec'] - $start['sec'])\r
- + $stop['usec'] - $start['usec'];\r
- }\r
- while ($timePassed < $usec);\r
-}\r
-\r
-?><?php\r
-\r
-\r
-\r
-/**\r
-* Contains information for a SOAP fault.\r
-* Mainly used for returning faults from deployed functions\r
-* in a server instance.\r
-* @author Dietrich Ayala <dietrich@ganx4.com>\r
-* @version $Id: nusoap.php,v 1.114 2007/11/06 15:17:46 snichol Exp $\r
-* @access public\r
-*/\r
-class nusoap_fault extends nusoap_base {\r
- /**\r
- * The fault code (client|server)\r
- * @var string\r
- * @access private\r
- */\r
- var $faultcode;\r
- /**\r
- * The fault actor\r
- * @var string\r
- * @access private\r
- */\r
- var $faultactor;\r
- /**\r
- * The fault string, a description of the fault\r
- * @var string\r
- * @access private\r
- */\r
- var $faultstring;\r
- /**\r
- * The fault detail, typically a string or array of string\r
- * @var mixed\r
- * @access private\r
- */\r
- var $faultdetail;\r
-\r
- /**\r
- * constructor\r
- *\r
- * @param string $faultcode (SOAP-ENV:Client | SOAP-ENV:Server)\r
- * @param string $faultactor only used when msg routed between multiple actors\r
- * @param string $faultstring human readable error message\r
- * @param mixed $faultdetail detail, typically a string or array of string\r
- */\r
- function nusoap_fault($faultcode,$faultactor='',$faultstring='',$faultdetail=''){\r
- parent::nusoap_base();\r
- $this->faultcode = $faultcode;\r
- $this->faultactor = $faultactor;\r
- $this->faultstring = $faultstring;\r
- $this->faultdetail = $faultdetail;\r
- }\r
-\r
- /**\r
- * serialize a fault\r
- *\r
- * @return string The serialization of the fault instance.\r
- * @access public\r
- */\r
- function serialize(){\r
- $ns_string = '';\r
- foreach($this->namespaces as $k => $v){\r
- $ns_string .= "\n xmlns:$k=\"$v\"";\r
- }\r
- $return_msg =\r
- '<?xml version="1.0" encoding="'.$this->soap_defencoding.'"?>'.\r
- '<SOAP-ENV:Envelope SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"'.$ns_string.">\n".\r
- '<SOAP-ENV:Body>'.\r
- '<SOAP-ENV:Fault>'.\r
- $this->serialize_val($this->faultcode, 'faultcode').\r
- $this->serialize_val($this->faultactor, 'faultactor').\r
- $this->serialize_val($this->faultstring, 'faultstring').\r
- $this->serialize_val($this->faultdetail, 'detail').\r
- '</SOAP-ENV:Fault>'.\r
- '</SOAP-ENV:Body>'.\r
- '</SOAP-ENV:Envelope>';\r
- return $return_msg;\r
- }\r
-}\r
-\r
-/**\r
- * Backward compatibility\r
- */\r
-class soap_fault extends nusoap_fault {\r
-}\r
-\r
-?><?php\r
-\r
-\r
-\r
-/**\r
-* parses an XML Schema, allows access to it's data, other utility methods.\r
-* imperfect, no validation... yet, but quite functional.\r
-*\r
-* @author Dietrich Ayala <dietrich@ganx4.com>\r
-* @author Scott Nichol <snichol@users.sourceforge.net>\r
-* @version $Id: nusoap.php,v 1.114 2007/11/06 15:17:46 snichol Exp $\r
-* @access public\r
-*/\r
-class nusoap_xmlschema extends nusoap_base {\r
- \r
- // files\r
- var $schema = '';\r
- var $xml = '';\r
- // namespaces\r
- var $enclosingNamespaces;\r
- // schema info\r
- var $schemaInfo = array();\r
- var $schemaTargetNamespace = '';\r
- // types, elements, attributes defined by the schema\r
- var $attributes = array();\r
- var $complexTypes = array();\r
- var $complexTypeStack = array();\r
- var $currentComplexType = null;\r
- var $elements = array();\r
- var $elementStack = array();\r
- var $currentElement = null;\r
- var $simpleTypes = array();\r
- var $simpleTypeStack = array();\r
- var $currentSimpleType = null;\r
- // imports\r
- var $imports = array();\r
- // parser vars\r
- var $parser;\r
- var $position = 0;\r
- var $depth = 0;\r
- var $depth_array = array();\r
- var $message = array();\r
- var $defaultNamespace = array();\r
- \r
- /**\r
- * constructor\r
- *\r
- * @param string $schema schema document URI\r
- * @param string $xml xml document URI\r
- * @param string $namespaces namespaces defined in enclosing XML\r
- * @access public\r
- */\r
- function nusoap_xmlschema($schema='',$xml='',$namespaces=array()){\r
- parent::nusoap_base();\r
- $this->debug('nusoap_xmlschema class instantiated, inside constructor');\r
- // files\r
- $this->schema = $schema;\r
- $this->xml = $xml;\r
-\r
- // namespaces\r
- $this->enclosingNamespaces = $namespaces;\r
- $this->namespaces = array_merge($this->namespaces, $namespaces);\r
-\r
- // parse schema file\r
- if($schema != ''){\r
- $this->debug('initial schema file: '.$schema);\r
- $this->parseFile($schema, 'schema');\r
- }\r
-\r
- // parse xml file\r
- if($xml != ''){\r
- $this->debug('initial xml file: '.$xml);\r
- $this->parseFile($xml, 'xml');\r
- }\r
-\r
- }\r
-\r
- /**\r
- * parse an XML file\r
- *\r
- * @param string $xml path/URL to XML file\r
- * @param string $type (schema | xml)\r
- * @return boolean\r
- * @access public\r
- */\r
- function parseFile($xml,$type){\r
- // parse xml file\r
- if($xml != ""){\r
- $xmlStr = @join("",@file($xml));\r
- if($xmlStr == ""){\r
- $msg = 'Error reading XML from '.$xml;\r
- $this->setError($msg);\r
- $this->debug($msg);\r
- return false;\r
- } else {\r
- $this->debug("parsing $xml");\r
- $this->parseString($xmlStr,$type);\r
- $this->debug("done parsing $xml");\r
- return true;\r
- }\r
- }\r
- return false;\r
- }\r
-\r
- /**\r
- * parse an XML string\r
- *\r
- * @param string $xml path or URL\r
- * @param string $type (schema|xml)\r
- * @access private\r
- */\r
- function parseString($xml,$type){\r
- // parse xml string\r
- if($xml != ""){\r
-\r
- // Create an XML parser.\r
- $this->parser = xml_parser_create();\r
- // Set the options for parsing the XML data.\r
- xml_parser_set_option($this->parser, XML_OPTION_CASE_FOLDING, 0);\r
-\r
- // Set the object for the parser.\r
- xml_set_object($this->parser, $this);\r
-\r
- // Set the element handlers for the parser.\r
- if($type == "schema"){\r
- xml_set_element_handler($this->parser, 'schemaStartElement','schemaEndElement');\r
- xml_set_character_data_handler($this->parser,'schemaCharacterData');\r
- } elseif($type == "xml"){\r
- xml_set_element_handler($this->parser, 'xmlStartElement','xmlEndElement');\r
- xml_set_character_data_handler($this->parser,'xmlCharacterData');\r
- }\r
-\r
- // Parse the XML file.\r
- if(!xml_parse($this->parser,$xml,true)){\r
- // Display an error message.\r
- $errstr = sprintf('XML error parsing XML schema on line %d: %s',\r
- xml_get_current_line_number($this->parser),\r
- xml_error_string(xml_get_error_code($this->parser))\r
- );\r
- $this->debug($errstr);\r
- $this->debug("XML payload:\n" . $xml);\r
- $this->setError($errstr);\r
- }\r
- \r
- xml_parser_free($this->parser);\r
- } else{\r
- $this->debug('no xml passed to parseString()!!');\r
- $this->setError('no xml passed to parseString()!!');\r
- }\r
- }\r
-\r
- /**\r
- * gets a type name for an unnamed type\r
- *\r
- * @param string Element name\r
- * @return string A type name for an unnamed type\r
- * @access private\r
- */\r
- function CreateTypeName($ename) {\r
- $scope = '';\r
- for ($i = 0; $i < count($this->complexTypeStack); $i++) {\r
- $scope .= $this->complexTypeStack[$i] . '_';\r
- }\r
- return $scope . $ename . '_ContainedType';\r
- }\r
- \r
- /**\r
- * start-element handler\r
- *\r
- * @param string $parser XML parser object\r
- * @param string $name element name\r
- * @param string $attrs associative array of attributes\r
- * @access private\r
- */\r
- function schemaStartElement($parser, $name, $attrs) {\r
- \r
- // position in the total number of elements, starting from 0\r
- $pos = $this->position++;\r
- $depth = $this->depth++;\r
- // set self as current value for this depth\r
- $this->depth_array[$depth] = $pos;\r
- $this->message[$pos] = array('cdata' => ''); \r
- if ($depth > 0) {\r
- $this->defaultNamespace[$pos] = $this->defaultNamespace[$this->depth_array[$depth - 1]];\r
- } else {\r
- $this->defaultNamespace[$pos] = false;\r
- }\r
-\r
- // get element prefix\r
- if($prefix = $this->getPrefix($name)){\r
- // get unqualified name\r
- $name = $this->getLocalPart($name);\r
- } else {\r
- $prefix = '';\r
- }\r
- \r
- // loop thru attributes, expanding, and registering namespace declarations\r
- if(count($attrs) > 0){\r
- foreach($attrs as $k => $v){\r
- // if ns declarations, add to class level array of valid namespaces\r
- if(ereg("^xmlns",$k)){\r
- //$this->xdebug("$k: $v");\r
- //$this->xdebug('ns_prefix: '.$this->getPrefix($k));\r
- if($ns_prefix = substr(strrchr($k,':'),1)){\r
- //$this->xdebug("Add namespace[$ns_prefix] = $v");\r
- $this->namespaces[$ns_prefix] = $v;\r
- } else {\r
- $this->defaultNamespace[$pos] = $v;\r
- if (! $this->getPrefixFromNamespace($v)) {\r
- $this->namespaces['ns'.(count($this->namespaces)+1)] = $v;\r
- }\r
- }\r
- if($v == 'http://www.w3.org/2001/XMLSchema' || $v == 'http://www.w3.org/1999/XMLSchema' || $v == 'http://www.w3.org/2000/10/XMLSchema'){\r
- $this->XMLSchemaVersion = $v;\r
- $this->namespaces['xsi'] = $v.'-instance';\r
- }\r
- }\r
- }\r
- foreach($attrs as $k => $v){\r
- // expand each attribute\r
- $k = strpos($k,':') ? $this->expandQname($k) : $k;\r
- $v = strpos($v,':') ? $this->expandQname($v) : $v;\r
- $eAttrs[$k] = $v;\r
- }\r
- $attrs = $eAttrs;\r
- } else {\r
- $attrs = array();\r
- }\r
- // find status, register data\r
- switch($name){\r
- case 'all': // (optional) compositor content for a complexType\r
- case 'choice':\r
- case 'group':\r
- case 'sequence':\r
- //$this->xdebug("compositor $name for currentComplexType: $this->currentComplexType and currentElement: $this->currentElement");\r
- $this->complexTypes[$this->currentComplexType]['compositor'] = $name;\r
- //if($name == 'all' || $name == 'sequence'){\r
- // $this->complexTypes[$this->currentComplexType]['phpType'] = 'struct';\r
- //}\r
- break;\r
- case 'attribute': // complexType attribute\r
- //$this->xdebug("parsing attribute $attrs[name] $attrs[ref] of value: ".$attrs['http://schemas.xmlsoap.org/wsdl/:arrayType']);\r
- $this->xdebug("parsing attribute:");\r
- $this->appendDebug($this->varDump($attrs));\r
- if (!isset($attrs['form'])) {\r
- $attrs['form'] = $this->schemaInfo['attributeFormDefault'];\r
- }\r
- if (isset($attrs['http://schemas.xmlsoap.org/wsdl/:arrayType'])) {\r
- $v = $attrs['http://schemas.xmlsoap.org/wsdl/:arrayType'];\r
- if (!strpos($v, ':')) {\r
- // no namespace in arrayType attribute value...\r
- if ($this->defaultNamespace[$pos]) {\r
- // ...so use the default\r
- $attrs['http://schemas.xmlsoap.org/wsdl/:arrayType'] = $this->defaultNamespace[$pos] . ':' . $attrs['http://schemas.xmlsoap.org/wsdl/:arrayType'];\r
- }\r
- }\r
- }\r
- if(isset($attrs['name'])){\r
- $this->attributes[$attrs['name']] = $attrs;\r
- $aname = $attrs['name'];\r
- } elseif(isset($attrs['ref']) && $attrs['ref'] == 'http://schemas.xmlsoap.org/soap/encoding/:arrayType'){\r
- if (isset($attrs['http://schemas.xmlsoap.org/wsdl/:arrayType'])) {\r
- $aname = $attrs['http://schemas.xmlsoap.org/wsdl/:arrayType'];\r
- } else {\r
- $aname = '';\r
- }\r
- } elseif(isset($attrs['ref'])){\r
- $aname = $attrs['ref'];\r
- $this->attributes[$attrs['ref']] = $attrs;\r
- }\r
- \r
- if($this->currentComplexType){ // This should *always* be\r
- $this->complexTypes[$this->currentComplexType]['attrs'][$aname] = $attrs;\r
- }\r
- // arrayType attribute\r
- if(isset($attrs['http://schemas.xmlsoap.org/wsdl/:arrayType']) || $this->getLocalPart($aname) == 'arrayType'){\r
- $this->complexTypes[$this->currentComplexType]['phpType'] = 'array';\r
- $prefix = $this->getPrefix($aname);\r
- if(isset($attrs['http://schemas.xmlsoap.org/wsdl/:arrayType'])){\r
- $v = $attrs['http://schemas.xmlsoap.org/wsdl/:arrayType'];\r
- } else {\r
- $v = '';\r
- }\r
- if(strpos($v,'[,]')){\r
- $this->complexTypes[$this->currentComplexType]['multidimensional'] = true;\r
- }\r
- $v = substr($v,0,strpos($v,'[')); // clip the []\r
- if(!strpos($v,':') && isset($this->typemap[$this->XMLSchemaVersion][$v])){\r
- $v = $this->XMLSchemaVersion.':'.$v;\r
- }\r
- $this->complexTypes[$this->currentComplexType]['arrayType'] = $v;\r
- }\r
- break;\r
- case 'complexContent': // (optional) content for a complexType\r
- break;\r
- case 'complexType':\r
- array_push($this->complexTypeStack, $this->currentComplexType);\r
- if(isset($attrs['name'])){\r
- // TODO: what is the scope of named complexTypes that appear\r
- // nested within other c complexTypes?\r
- $this->xdebug('processing named complexType '.$attrs['name']);\r
- //$this->currentElement = false;\r
- $this->currentComplexType = $attrs['name'];\r
- $this->complexTypes[$this->currentComplexType] = $attrs;\r
- $this->complexTypes[$this->currentComplexType]['typeClass'] = 'complexType';\r
- // This is for constructs like\r
- // <complexType name="ListOfString" base="soap:Array">\r
- // <sequence>\r
- // <element name="string" type="xsd:string"\r
- // minOccurs="0" maxOccurs="unbounded" />\r
- // </sequence>\r
- // </complexType>\r
- if(isset($attrs['base']) && ereg(':Array$',$attrs['base'])){\r
- $this->xdebug('complexType is unusual array');\r
- $this->complexTypes[$this->currentComplexType]['phpType'] = 'array';\r
- } else {\r
- $this->complexTypes[$this->currentComplexType]['phpType'] = 'struct';\r
- }\r
- } else {\r
- $name = $this->CreateTypeName($this->currentElement);\r
- $this->xdebug('processing unnamed complexType for element ' . $this->currentElement . ' named ' . $name);\r
- $this->currentComplexType = $name;\r
- //$this->currentElement = false;\r
- $this->complexTypes[$this->currentComplexType] = $attrs;\r
- $this->complexTypes[$this->currentComplexType]['typeClass'] = 'complexType';\r
- // This is for constructs like\r
- // <complexType name="ListOfString" base="soap:Array">\r
- // <sequence>\r
- // <element name="string" type="xsd:string"\r
- // minOccurs="0" maxOccurs="unbounded" />\r
- // </sequence>\r
- // </complexType>\r
- if(isset($attrs['base']) && ereg(':Array$',$attrs['base'])){\r
- $this->xdebug('complexType is unusual array');\r
- $this->complexTypes[$this->currentComplexType]['phpType'] = 'array';\r
- } else {\r
- $this->complexTypes[$this->currentComplexType]['phpType'] = 'struct';\r
- }\r
- }\r
- break;\r
- case 'element':\r
- array_push($this->elementStack, $this->currentElement);\r
- if (!isset($attrs['form'])) {\r
- $attrs['form'] = $this->schemaInfo['elementFormDefault'];\r
- }\r
- if(isset($attrs['type'])){\r
- $this->xdebug("processing typed element ".$attrs['name']." of type ".$attrs['type']);\r
- if (! $this->getPrefix($attrs['type'])) {\r
- if ($this->defaultNamespace[$pos]) {\r
- $attrs['type'] = $this->defaultNamespace[$pos] . ':' . $attrs['type'];\r
- $this->xdebug('used default namespace to make type ' . $attrs['type']);\r
- }\r
- }\r
- // This is for constructs like\r
- // <complexType name="ListOfString" base="soap:Array">\r
- // <sequence>\r
- // <element name="string" type="xsd:string"\r
- // minOccurs="0" maxOccurs="unbounded" />\r
- // </sequence>\r
- // </complexType>\r
- if ($this->currentComplexType && $this->complexTypes[$this->currentComplexType]['phpType'] == 'array') {\r
- $this->xdebug('arrayType for unusual array is ' . $attrs['type']);\r
- $this->complexTypes[$this->currentComplexType]['arrayType'] = $attrs['type'];\r
- }\r
- $this->currentElement = $attrs['name'];\r
- $ename = $attrs['name'];\r
- } elseif(isset($attrs['ref'])){\r
- $this->xdebug("processing element as ref to ".$attrs['ref']);\r
- $this->currentElement = "ref to ".$attrs['ref'];\r
- $ename = $this->getLocalPart($attrs['ref']);\r
- } else {\r
- $type = $this->CreateTypeName($this->currentComplexType . '_' . $attrs['name']);\r
- $this->xdebug("processing untyped element " . $attrs['name'] . ' type ' . $type);\r
- $this->currentElement = $attrs['name'];\r
- $attrs['type'] = $this->schemaTargetNamespace . ':' . $type;\r
- $ename = $attrs['name'];\r
- }\r
- if (isset($ename) && $this->currentComplexType) {\r
- $this->xdebug("add element $ename to complexType $this->currentComplexType");\r
- $this->complexTypes[$this->currentComplexType]['elements'][$ename] = $attrs;\r
- } elseif (!isset($attrs['ref'])) {\r
- $this->xdebug("add element $ename to elements array");\r
- $this->elements[ $attrs['name'] ] = $attrs;\r
- $this->elements[ $attrs['name'] ]['typeClass'] = 'element';\r
- }\r
- break;\r
- case 'enumeration': // restriction value list member\r
- $this->xdebug('enumeration ' . $attrs['value']);\r
- if ($this->currentSimpleType) {\r
- $this->simpleTypes[$this->currentSimpleType]['enumeration'][] = $attrs['value'];\r
- } elseif ($this->currentComplexType) {\r
- $this->complexTypes[$this->currentComplexType]['enumeration'][] = $attrs['value'];\r
- }\r
- break;\r
- case 'extension': // simpleContent or complexContent type extension\r
- $this->xdebug('extension ' . $attrs['base']);\r
- if ($this->currentComplexType) {\r
- $this->complexTypes[$this->currentComplexType]['extensionBase'] = $attrs['base'];\r
- }\r
- break;\r
- case 'import':\r
- if (isset($attrs['schemaLocation'])) {\r
- //$this->xdebug('import namespace ' . $attrs['namespace'] . ' from ' . $attrs['schemaLocation']);\r
- $this->imports[$attrs['namespace']][] = array('location' => $attrs['schemaLocation'], 'loaded' => false);\r
- } else {\r
- //$this->xdebug('import namespace ' . $attrs['namespace']);\r
- $this->imports[$attrs['namespace']][] = array('location' => '', 'loaded' => true);\r
- if (! $this->getPrefixFromNamespace($attrs['namespace'])) {\r
- $this->namespaces['ns'.(count($this->namespaces)+1)] = $attrs['namespace'];\r
- }\r
- }\r
- break;\r
- case 'list': // simpleType value list\r
- break;\r
- case 'restriction': // simpleType, simpleContent or complexContent value restriction\r
- $this->xdebug('restriction ' . $attrs['base']);\r
- if($this->currentSimpleType){\r
- $this->simpleTypes[$this->currentSimpleType]['type'] = $attrs['base'];\r
- } elseif($this->currentComplexType){\r
- $this->complexTypes[$this->currentComplexType]['restrictionBase'] = $attrs['base'];\r
- if(strstr($attrs['base'],':') == ':Array'){\r
- $this->complexTypes[$this->currentComplexType]['phpType'] = 'array';\r
- }\r
- }\r
- break;\r
- case 'schema':\r
- $this->schemaInfo = $attrs;\r
- $this->schemaInfo['schemaVersion'] = $this->getNamespaceFromPrefix($prefix);\r
- if (isset($attrs['targetNamespace'])) {\r
- $this->schemaTargetNamespace = $attrs['targetNamespace'];\r
- }\r
- if (!isset($attrs['elementFormDefault'])) {\r
- $this->schemaInfo['elementFormDefault'] = 'unqualified';\r
- }\r
- if (!isset($attrs['attributeFormDefault'])) {\r
- $this->schemaInfo['attributeFormDefault'] = 'unqualified';\r
- }\r
- break;\r
- case 'simpleContent': // (optional) content for a complexType\r
- break;\r
- case 'simpleType':\r
- array_push($this->simpleTypeStack, $this->currentSimpleType);\r
- if(isset($attrs['name'])){\r
- $this->xdebug("processing simpleType for name " . $attrs['name']);\r
- $this->currentSimpleType = $attrs['name'];\r
- $this->simpleTypes[ $attrs['name'] ] = $attrs;\r
- $this->simpleTypes[ $attrs['name'] ]['typeClass'] = 'simpleType';\r
- $this->simpleTypes[ $attrs['name'] ]['phpType'] = 'scalar';\r
- } else {\r
- $name = $this->CreateTypeName($this->currentComplexType . '_' . $this->currentElement);\r
- $this->xdebug('processing unnamed simpleType for element ' . $this->currentElement . ' named ' . $name);\r
- $this->currentSimpleType = $name;\r
- //$this->currentElement = false;\r
- $this->simpleTypes[$this->currentSimpleType] = $attrs;\r
- $this->simpleTypes[$this->currentSimpleType]['phpType'] = 'scalar';\r
- }\r
- break;\r
- case 'union': // simpleType type list\r
- break;\r
- default:\r
- //$this->xdebug("do not have anything to do for element $name");\r
- }\r
- }\r
-\r
- /**\r
- * end-element handler\r
- *\r
- * @param string $parser XML parser object\r
- * @param string $name element name\r
- * @access private\r
- */\r
- function schemaEndElement($parser, $name) {\r
- // bring depth down a notch\r
- $this->depth--;\r
- // position of current element is equal to the last value left in depth_array for my depth\r
- if(isset($this->depth_array[$this->depth])){\r
- $pos = $this->depth_array[$this->depth];\r
- }\r
- // get element prefix\r
- if ($prefix = $this->getPrefix($name)){\r
- // get unqualified name\r
- $name = $this->getLocalPart($name);\r
- } else {\r
- $prefix = '';\r
- }\r
- // move on...\r
- if($name == 'complexType'){\r
- $this->xdebug('done processing complexType ' . ($this->currentComplexType ? $this->currentComplexType : '(unknown)'));\r
- $this->currentComplexType = array_pop($this->complexTypeStack);\r
- //$this->currentElement = false;\r
- }\r
- if($name == 'element'){\r
- $this->xdebug('done processing element ' . ($this->currentElement ? $this->currentElement : '(unknown)'));\r
- $this->currentElement = array_pop($this->elementStack);\r
- }\r
- if($name == 'simpleType'){\r
- $this->xdebug('done processing simpleType ' . ($this->currentSimpleType ? $this->currentSimpleType : '(unknown)'));\r
- $this->currentSimpleType = array_pop($this->simpleTypeStack);\r
- }\r
- }\r
-\r
- /**\r
- * element content handler\r
- *\r
- * @param string $parser XML parser object\r
- * @param string $data element content\r
- * @access private\r
- */\r
- function schemaCharacterData($parser, $data){\r
- $pos = $this->depth_array[$this->depth - 1];\r
- $this->message[$pos]['cdata'] .= $data;\r
- }\r
-\r
- /**\r
- * serialize the schema\r
- *\r
- * @access public\r
- */\r
- function serializeSchema(){\r
-\r
- $schemaPrefix = $this->getPrefixFromNamespace($this->XMLSchemaVersion);\r
- $xml = '';\r
- // imports\r
- if (sizeof($this->imports) > 0) {\r
- foreach($this->imports as $ns => $list) {\r
- foreach ($list as $ii) {\r
- if ($ii['location'] != '') {\r
- $xml .= " <$schemaPrefix:import location=\"" . $ii['location'] . '" namespace="' . $ns . "\" />\n";\r
- } else {\r
- $xml .= " <$schemaPrefix:import namespace=\"" . $ns . "\" />\n";\r
- }\r
- }\r
- } \r
- } \r
- // complex types\r
- foreach($this->complexTypes as $typeName => $attrs){\r
- $contentStr = '';\r
- // serialize child elements\r
- if(isset($attrs['elements']) && (count($attrs['elements']) > 0)){\r
- foreach($attrs['elements'] as $element => $eParts){\r
- if(isset($eParts['ref'])){\r
- $contentStr .= " <$schemaPrefix:element ref=\"$element\"/>\n";\r
- } else {\r
- $contentStr .= " <$schemaPrefix:element name=\"$element\" type=\"" . $this->contractQName($eParts['type']) . "\"";\r
- foreach ($eParts as $aName => $aValue) {\r
- // handle, e.g., abstract, default, form, minOccurs, maxOccurs, nillable\r
- if ($aName != 'name' && $aName != 'type') {\r
- $contentStr .= " $aName=\"$aValue\"";\r
- }\r
- }\r
- $contentStr .= "/>\n";\r
- }\r
- }\r
- // compositor wraps elements\r
- if (isset($attrs['compositor']) && ($attrs['compositor'] != '')) {\r
- $contentStr = " <$schemaPrefix:$attrs[compositor]>\n".$contentStr." </$schemaPrefix:$attrs[compositor]>\n";\r
- }\r
- }\r
- // attributes\r
- if(isset($attrs['attrs']) && (count($attrs['attrs']) >= 1)){\r
- foreach($attrs['attrs'] as $attr => $aParts){\r
- $contentStr .= " <$schemaPrefix:attribute";\r
- foreach ($aParts as $a => $v) {\r
- if ($a == 'ref' || $a == 'type') {\r
- $contentStr .= " $a=\"".$this->contractQName($v).'"';\r
- } elseif ($a == 'http://schemas.xmlsoap.org/wsdl/:arrayType') {\r
- $this->usedNamespaces['wsdl'] = $this->namespaces['wsdl'];\r
- $contentStr .= ' wsdl:arrayType="'.$this->contractQName($v).'"';\r
- } else {\r
- $contentStr .= " $a=\"$v\"";\r
- }\r
- }\r
- $contentStr .= "/>\n";\r
- }\r
- }\r
- // if restriction\r
- if (isset($attrs['restrictionBase']) && $attrs['restrictionBase'] != ''){\r
- $contentStr = " <$schemaPrefix:restriction base=\"".$this->contractQName($attrs['restrictionBase'])."\">\n".$contentStr." </$schemaPrefix:restriction>\n";\r
- // complex or simple content\r
- if ((isset($attrs['elements']) && count($attrs['elements']) > 0) || (isset($attrs['attrs']) && count($attrs['attrs']) > 0)){\r
- $contentStr = " <$schemaPrefix:complexContent>\n".$contentStr." </$schemaPrefix:complexContent>\n";\r
- }\r
- }\r
- // finalize complex type\r
- if($contentStr != ''){\r
- $contentStr = " <$schemaPrefix:complexType name=\"$typeName\">\n".$contentStr." </$schemaPrefix:complexType>\n";\r
- } else {\r
- $contentStr = " <$schemaPrefix:complexType name=\"$typeName\"/>\n";\r
- }\r
- $xml .= $contentStr;\r
- }\r
- // simple types\r
- if(isset($this->simpleTypes) && count($this->simpleTypes) > 0){\r
- foreach($this->simpleTypes as $typeName => $eParts){\r
- $xml .= " <$schemaPrefix:simpleType name=\"$typeName\">\n <$schemaPrefix:restriction base=\"".$this->contractQName($eParts['type'])."\">\n";\r
- if (isset($eParts['enumeration'])) {\r
- foreach ($eParts['enumeration'] as $e) {\r
- $xml .= " <$schemaPrefix:enumeration value=\"$e\"/>\n";\r
- }\r
- }\r
- $xml .= " </$schemaPrefix:restriction>\n </$schemaPrefix:simpleType>";\r
- }\r
- }\r
- // elements\r
- if(isset($this->elements) && count($this->elements) > 0){\r
- foreach($this->elements as $element => $eParts){\r
- $xml .= " <$schemaPrefix:element name=\"$element\" type=\"".$this->contractQName($eParts['type'])."\"/>\n";\r
- }\r
- }\r
- // attributes\r
- if(isset($this->attributes) && count($this->attributes) > 0){\r
- foreach($this->attributes as $attr => $aParts){\r
- $xml .= " <$schemaPrefix:attribute name=\"$attr\" type=\"".$this->contractQName($aParts['type'])."\"\n/>";\r
- }\r
- }\r
- // finish 'er up\r
- $attr = '';\r
- foreach ($this->schemaInfo as $k => $v) {\r
- if ($k == 'elementFormDefault' || $k == 'attributeFormDefault') {\r
- $attr .= " $k=\"$v\"";\r
- }\r
- }\r
- $el = "<$schemaPrefix:schema$attr targetNamespace=\"$this->schemaTargetNamespace\"\n";\r
- foreach (array_diff($this->usedNamespaces, $this->enclosingNamespaces) as $nsp => $ns) {\r
- $el .= " xmlns:$nsp=\"$ns\"";\r
- }\r
- $xml = $el . ">\n".$xml."</$schemaPrefix:schema>\n";\r
- return $xml;\r
- }\r
-\r
- /**\r
- * adds debug data to the clas level debug string\r
- *\r
- * @param string $string debug data\r
- * @access private\r
- */\r
- function xdebug($string){\r
- $this->debug('<' . $this->schemaTargetNamespace . '> '.$string);\r
- }\r
-\r
- /**\r
- * get the PHP type of a user defined type in the schema\r
- * PHP type is kind of a misnomer since it actually returns 'struct' for assoc. arrays\r
- * returns false if no type exists, or not w/ the given namespace\r
- * else returns a string that is either a native php type, or 'struct'\r
- *\r
- * @param string $type name of defined type\r
- * @param string $ns namespace of type\r
- * @return mixed\r
- * @access public\r
- * @deprecated\r
- */\r
- function getPHPType($type,$ns){\r
- if(isset($this->typemap[$ns][$type])){\r
- //print "found type '$type' and ns $ns in typemap<br>";\r
- return $this->typemap[$ns][$type];\r
- } elseif(isset($this->complexTypes[$type])){\r
- //print "getting type '$type' and ns $ns from complexTypes array<br>";\r
- return $this->complexTypes[$type]['phpType'];\r
- }\r
- return false;\r
- }\r
-\r
- /**\r
- * returns an associative array of information about a given type\r
- * returns false if no type exists by the given name\r
- *\r
- * For a complexType typeDef = array(\r
- * 'restrictionBase' => '',\r
- * 'phpType' => '',\r
- * 'compositor' => '(sequence|all)',\r
- * 'elements' => array(), // refs to elements array\r
- * 'attrs' => array() // refs to attributes array\r
- * ... and so on (see addComplexType)\r
- * )\r
- *\r
- * For simpleType or element, the array has different keys.\r
- *\r
- * @param string $type\r
- * @return mixed\r
- * @access public\r
- * @see addComplexType\r
- * @see addSimpleType\r
- * @see addElement\r
- */\r
- function getTypeDef($type){\r
- //$this->debug("in getTypeDef for type $type");\r
- if (substr($type, -1) == '^') {\r
- $is_element = 1;\r
- $type = substr($type, 0, -1);\r
- } else {\r
- $is_element = 0;\r
- }\r
-\r
- if((! $is_element) && isset($this->complexTypes[$type])){\r
- $this->xdebug("in getTypeDef, found complexType $type");\r
- return $this->complexTypes[$type];\r
- } elseif((! $is_element) && isset($this->simpleTypes[$type])){\r
- $this->xdebug("in getTypeDef, found simpleType $type");\r
- if (!isset($this->simpleTypes[$type]['phpType'])) {\r
- // get info for type to tack onto the simple type\r
- // TODO: can this ever really apply (i.e. what is a simpleType really?)\r
- $uqType = substr($this->simpleTypes[$type]['type'], strrpos($this->simpleTypes[$type]['type'], ':') + 1);\r
- $ns = substr($this->simpleTypes[$type]['type'], 0, strrpos($this->simpleTypes[$type]['type'], ':'));\r
- $etype = $this->getTypeDef($uqType);\r
- if ($etype) {\r
- $this->xdebug("in getTypeDef, found type for simpleType $type:");\r
- $this->xdebug($this->varDump($etype));\r
- if (isset($etype['phpType'])) {\r
- $this->simpleTypes[$type]['phpType'] = $etype['phpType'];\r
- }\r
- if (isset($etype['elements'])) {\r
- $this->simpleTypes[$type]['elements'] = $etype['elements'];\r
- }\r
- }\r
- }\r
- return $this->simpleTypes[$type];\r
- } elseif(isset($this->elements[$type])){\r
- $this->xdebug("in getTypeDef, found element $type");\r
- if (!isset($this->elements[$type]['phpType'])) {\r
- // get info for type to tack onto the element\r
- $uqType = substr($this->elements[$type]['type'], strrpos($this->elements[$type]['type'], ':') + 1);\r
- $ns = substr($this->elements[$type]['type'], 0, strrpos($this->elements[$type]['type'], ':'));\r
- $etype = $this->getTypeDef($uqType);\r
- if ($etype) {\r
- $this->xdebug("in getTypeDef, found type for element $type:");\r
- $this->xdebug($this->varDump($etype));\r
- if (isset($etype['phpType'])) {\r
- $this->elements[$type]['phpType'] = $etype['phpType'];\r
- }\r
- if (isset($etype['elements'])) {\r
- $this->elements[$type]['elements'] = $etype['elements'];\r
- }\r
- } elseif ($ns == 'http://www.w3.org/2001/XMLSchema') {\r
- $this->xdebug("in getTypeDef, element $type is an XSD type");\r
- $this->elements[$type]['phpType'] = 'scalar';\r
- }\r
- }\r
- return $this->elements[$type];\r
- } elseif(isset($this->attributes[$type])){\r
- $this->xdebug("in getTypeDef, found attribute $type");\r
- return $this->attributes[$type];\r
- } elseif (ereg('_ContainedType$', $type)) {\r
- $this->xdebug("in getTypeDef, have an untyped element $type");\r
- $typeDef['typeClass'] = 'simpleType';\r
- $typeDef['phpType'] = 'scalar';\r
- $typeDef['type'] = 'http://www.w3.org/2001/XMLSchema:string';\r
- return $typeDef;\r
- }\r
- $this->xdebug("in getTypeDef, did not find $type");\r
- return false;\r
- }\r
-\r
- /**\r
- * returns a sample serialization of a given type, or false if no type by the given name\r
- *\r
- * @param string $type name of type\r
- * @return mixed\r
- * @access public\r
- * @deprecated\r
- */\r
- function serializeTypeDef($type){\r
- //print "in sTD() for type $type<br>";\r
- if($typeDef = $this->getTypeDef($type)){\r
- $str .= '<'.$type;\r
- if(is_array($typeDef['attrs'])){\r
- foreach($typeDef['attrs'] as $attName => $data){\r
- $str .= " $attName=\"{type = ".$data['type']."}\"";\r
- }\r
- }\r
- $str .= " xmlns=\"".$this->schema['targetNamespace']."\"";\r
- if(count($typeDef['elements']) > 0){\r
- $str .= ">";\r
- foreach($typeDef['elements'] as $element => $eData){\r
- $str .= $this->serializeTypeDef($element);\r
- }\r
- $str .= "</$type>";\r
- } elseif($typeDef['typeClass'] == 'element') {\r
- $str .= "></$type>";\r
- } else {\r
- $str .= "/>";\r
- }\r
- return $str;\r
- }\r
- return false;\r
- }\r
-\r
- /**\r
- * returns HTML form elements that allow a user\r
- * to enter values for creating an instance of the given type.\r
- *\r
- * @param string $name name for type instance\r
- * @param string $type name of type\r
- * @return string\r
- * @access public\r
- * @deprecated\r
- */\r
- function typeToForm($name,$type){\r
- // get typedef\r
- if($typeDef = $this->getTypeDef($type)){\r
- // if struct\r
- if($typeDef['phpType'] == 'struct'){\r
- $buffer .= '<table>';\r
- foreach($typeDef['elements'] as $child => $childDef){\r
- $buffer .= "\r
- <tr><td align='right'>$childDef[name] (type: ".$this->getLocalPart($childDef['type'])."):</td>\r
- <td><input type='text' name='parameters[".$name."][$childDef[name]]'></td></tr>";\r
- }\r
- $buffer .= '</table>';\r
- // if array\r
- } elseif($typeDef['phpType'] == 'array'){\r
- $buffer .= '<table>';\r
- for($i=0;$i < 3; $i++){\r
- $buffer .= "\r
- <tr><td align='right'>array item (type: $typeDef[arrayType]):</td>\r
- <td><input type='text' name='parameters[".$name."][]'></td></tr>";\r
- }\r
- $buffer .= '</table>';\r
- // if scalar\r
- } else {\r
- $buffer .= "<input type='text' name='parameters[$name]'>";\r
- }\r
- } else {\r
- $buffer .= "<input type='text' name='parameters[$name]'>";\r
- }\r
- return $buffer;\r
- }\r
- \r
- /**\r
- * adds a complex type to the schema\r
- * \r
- * example: array\r
- * \r
- * addType(\r
- * 'ArrayOfstring',\r
- * 'complexType',\r
- * 'array',\r
- * '',\r
- * 'SOAP-ENC:Array',\r
- * array('ref'=>'SOAP-ENC:arrayType','wsdl:arrayType'=>'string[]'),\r
- * 'xsd:string'\r
- * );\r
- * \r
- * example: PHP associative array ( SOAP Struct )\r
- * \r
- * addType(\r
- * 'SOAPStruct',\r
- * 'complexType',\r
- * 'struct',\r
- * 'all',\r
- * array('myVar'=> array('name'=>'myVar','type'=>'string')\r
- * );\r
- * \r
- * @param name\r
- * @param typeClass (complexType|simpleType|attribute)\r
- * @param phpType: currently supported are array and struct (php assoc array)\r
- * @param compositor (all|sequence|choice)\r
- * @param restrictionBase namespace:name (http://schemas.xmlsoap.org/soap/encoding/:Array)\r
- * @param elements = array ( name = array(name=>'',type=>'') )\r
- * @param attrs = array(\r
- * array(\r
- * 'ref' => "http://schemas.xmlsoap.org/soap/encoding/:arrayType",\r
- * "http://schemas.xmlsoap.org/wsdl/:arrayType" => "string[]"\r
- * )\r
- * )\r
- * @param arrayType: namespace:name (http://www.w3.org/2001/XMLSchema:string)\r
- * @access public\r
- * @see getTypeDef\r
- */\r
- function addComplexType($name,$typeClass='complexType',$phpType='array',$compositor='',$restrictionBase='',$elements=array(),$attrs=array(),$arrayType=''){\r
- $this->complexTypes[$name] = array(\r
- 'name' => $name,\r
- 'typeClass' => $typeClass,\r
- 'phpType' => $phpType,\r
- 'compositor'=> $compositor,\r
- 'restrictionBase' => $restrictionBase,\r
- 'elements' => $elements,\r
- 'attrs' => $attrs,\r
- 'arrayType' => $arrayType\r
- );\r
- \r
- $this->xdebug("addComplexType $name:");\r
- $this->appendDebug($this->varDump($this->complexTypes[$name]));\r
- }\r
- \r
- /**\r
- * adds a simple type to the schema\r
- *\r
- * @param string $name\r
- * @param string $restrictionBase namespace:name (http://schemas.xmlsoap.org/soap/encoding/:Array)\r
- * @param string $typeClass (should always be simpleType)\r
- * @param string $phpType (should always be scalar)\r
- * @param array $enumeration array of values\r
- * @access public\r
- * @see nusoap_xmlschema\r
- * @see getTypeDef\r
- */\r
- function addSimpleType($name, $restrictionBase='', $typeClass='simpleType', $phpType='scalar', $enumeration=array()) {\r
- $this->simpleTypes[$name] = array(\r
- 'name' => $name,\r
- 'typeClass' => $typeClass,\r
- 'phpType' => $phpType,\r
- 'type' => $restrictionBase,\r
- 'enumeration' => $enumeration\r
- );\r
- \r
- $this->xdebug("addSimpleType $name:");\r
- $this->appendDebug($this->varDump($this->simpleTypes[$name]));\r
- }\r
-\r
- /**\r
- * adds an element to the schema\r
- *\r
- * @param array $attrs attributes that must include name and type\r
- * @see nusoap_xmlschema\r
- * @access public\r
- */\r
- function addElement($attrs) {\r
- if (! $this->getPrefix($attrs['type'])) {\r
- $attrs['type'] = $this->schemaTargetNamespace . ':' . $attrs['type'];\r
- }\r
- $this->elements[ $attrs['name'] ] = $attrs;\r
- $this->elements[ $attrs['name'] ]['typeClass'] = 'element';\r
- \r
- $this->xdebug("addElement " . $attrs['name']);\r
- $this->appendDebug($this->varDump($this->elements[ $attrs['name'] ]));\r
- }\r
-}\r
-\r
-/**\r
- * Backward compatibility\r
- */\r
-class XMLSchema extends nusoap_xmlschema {\r
-}\r
-\r
-?><?php\r
-\r
-\r
-\r
-/**\r
-* For creating serializable abstractions of native PHP types. This class\r
-* allows element name/namespace, XSD type, and XML attributes to be\r
-* associated with a value. This is extremely useful when WSDL is not\r
-* used, but is also useful when WSDL is used with polymorphic types, including\r
-* xsd:anyType and user-defined types.\r
-*\r
-* @author Dietrich Ayala <dietrich@ganx4.com>\r
-* @version $Id: nusoap.php,v 1.114 2007/11/06 15:17:46 snichol Exp $\r
-* @access public\r
-*/\r
-class soapval extends nusoap_base {\r
- /**\r
- * The XML element name\r
- *\r
- * @var string\r
- * @access private\r
- */\r
- var $name;\r
- /**\r
- * The XML type name (string or false)\r
- *\r
- * @var mixed\r
- * @access private\r
- */\r
- var $type;\r
- /**\r
- * The PHP value\r
- *\r
- * @var mixed\r
- * @access private\r
- */\r
- var $value;\r
- /**\r
- * The XML element namespace (string or false)\r
- *\r
- * @var mixed\r
- * @access private\r
- */\r
- var $element_ns;\r
- /**\r
- * The XML type namespace (string or false)\r
- *\r
- * @var mixed\r
- * @access private\r
- */\r
- var $type_ns;\r
- /**\r
- * The XML element attributes (array or false)\r
- *\r
- * @var mixed\r
- * @access private\r
- */\r
- var $attributes;\r
-\r
- /**\r
- * constructor\r
- *\r
- * @param string $name optional name\r
- * @param mixed $type optional type name\r
- * @param mixed $value optional value\r
- * @param mixed $element_ns optional namespace of value\r
- * @param mixed $type_ns optional namespace of type\r
- * @param mixed $attributes associative array of attributes to add to element serialization\r
- * @access public\r
- */\r
- function soapval($name='soapval',$type=false,$value=-1,$element_ns=false,$type_ns=false,$attributes=false) {\r
- parent::nusoap_base();\r
- $this->name = $name;\r
- $this->type = $type;\r
- $this->value = $value;\r
- $this->element_ns = $element_ns;\r
- $this->type_ns = $type_ns;\r
- $this->attributes = $attributes;\r
- }\r
-\r
- /**\r
- * return serialized value\r
- *\r
- * @param string $use The WSDL use value (encoded|literal)\r
- * @return string XML data\r
- * @access public\r
- */\r
- function serialize($use='encoded') {\r
- return $this->serialize_val($this->value, $this->name, $this->type, $this->element_ns, $this->type_ns, $this->attributes, $use, true);\r
- }\r
-\r
- /**\r
- * decodes a soapval object into a PHP native type\r
- *\r
- * @return mixed\r
- * @access public\r
- */\r
- function decode(){\r
- return $this->value;\r
- }\r
-}\r
-\r
-\r
-\r
-?><?php\r
-\r
-\r
-\r
-/**\r
-* transport class for sending/receiving data via HTTP and HTTPS\r
-* NOTE: PHP must be compiled with the CURL extension for HTTPS support\r
-*\r
-* @author Dietrich Ayala <dietrich@ganx4.com>\r
-* @author Scott Nichol <snichol@users.sourceforge.net>\r
-* @version $Id: nusoap.php,v 1.114 2007/11/06 15:17:46 snichol Exp $\r
-* @access public\r
-*/\r
-class soap_transport_http extends nusoap_base {\r
-\r
- var $url = '';\r
- var $uri = '';\r
- var $digest_uri = '';\r
- var $scheme = '';\r
- var $host = '';\r
- var $port = '';\r
- var $path = '';\r
- var $request_method = 'POST';\r
- var $protocol_version = '1.0';\r
- var $encoding = '';\r
- var $outgoing_headers = array();\r
- var $incoming_headers = array();\r
- var $incoming_cookies = array();\r
- var $outgoing_payload = '';\r
- var $incoming_payload = '';\r
- var $response_status_line; // HTTP response status line\r
- var $useSOAPAction = true;\r
- var $persistentConnection = false;\r
- var $ch = false; // cURL handle\r
- var $ch_options = array(); // cURL custom options\r
- var $use_curl = false; // force cURL use\r
- var $proxy = null; // proxy information (associative array)\r
- var $username = '';\r
- var $password = '';\r
- var $authtype = '';\r
- var $digestRequest = array();\r
- var $certRequest = array(); // keys must be cainfofile (optional), sslcertfile, sslkeyfile, passphrase, certpassword (optional), verifypeer (optional), verifyhost (optional)\r
- // cainfofile: certificate authority file, e.g. '$pathToPemFiles/rootca.pem'\r
- // sslcertfile: SSL certificate file, e.g. '$pathToPemFiles/mycert.pem'\r
- // sslkeyfile: SSL key file, e.g. '$pathToPemFiles/mykey.pem'\r
- // passphrase: SSL key password/passphrase\r
- // certpassword: SSL certificate password\r
- // verifypeer: default is 1\r
- // verifyhost: default is 1\r
-\r
- /**\r
- * constructor\r
- *\r
- * @param string $url The URL to which to connect\r
- * @param array $curl_options User-specified cURL options\r
- * @param boolean $use_curl Whether to try to force cURL use\r
- * @access public\r
- */\r
- function soap_transport_http($url, $curl_options = NULL, $use_curl = false){\r
- parent::nusoap_base();\r
- $this->debug("ctor url=$url use_curl=$use_curl curl_options:");\r
- $this->appendDebug($this->varDump($curl_options));\r
- $this->setURL($url);\r
- if (is_array($curl_options)) {\r
- $this->ch_options = $curl_options;\r
- }\r
- $this->use_curl = $use_curl;\r
- ereg('\$Revisio' . 'n: ([^ ]+)', $this->revision, $rev);\r
- $this->setHeader('User-Agent', $this->title.'/'.$this->version.' ('.$rev[1].')');\r
- }\r
-\r
- /**\r
- * sets a cURL option\r
- *\r
- * @param mixed $option The cURL option (always integer?)\r
- * @param mixed $value The cURL option value\r
- * @access private\r
- */\r
- function setCurlOption($option, $value) {\r
- $this->debug("setCurlOption option=$option, value=");\r
- $this->appendDebug($this->varDump($value));\r
- curl_setopt($this->ch, $option, $value);\r
- }\r
-\r
- /**\r
- * sets an HTTP header\r
- *\r
- * @param string $name The name of the header\r
- * @param string $value The value of the header\r
- * @access private\r
- */\r
- function setHeader($name, $value) {\r
- $this->outgoing_headers[$name] = $value;\r
- $this->debug("set header $name: $value");\r
- }\r
-\r
- /**\r
- * unsets an HTTP header\r
- *\r
- * @param string $name The name of the header\r
- * @access private\r
- */\r
- function unsetHeader($name) {\r
- if (isset($this->outgoing_headers[$name])) {\r
- $this->debug("unset header $name");\r
- unset($this->outgoing_headers[$name]);\r
- }\r
- }\r
-\r
- /**\r
- * sets the URL to which to connect\r
- *\r
- * @param string $url The URL to which to connect\r
- * @access private\r
- */\r
- function setURL($url) {\r
- $this->url = $url;\r
-\r
- $u = parse_url($url);\r
- foreach($u as $k => $v){\r
- $this->debug("parsed URL $k = $v");\r
- $this->$k = $v;\r
- }\r
- \r
- // add any GET params to path\r
- if(isset($u['query']) && $u['query'] != ''){\r
- $this->path .= '?' . $u['query'];\r
- }\r
- \r
- // set default port\r
- if(!isset($u['port'])){\r
- if($u['scheme'] == 'https'){\r
- $this->port = 443;\r
- } else {\r
- $this->port = 80;\r
- }\r
- }\r
- \r
- $this->uri = $this->path;\r
- $this->digest_uri = $this->uri;\r
- \r
- // build headers\r
- if (!isset($u['port'])) {\r
- $this->setHeader('Host', $this->host);\r
- } else {\r
- $this->setHeader('Host', $this->host.':'.$this->port);\r
- }\r
-\r
- if (isset($u['user']) && $u['user'] != '') {\r
- $this->setCredentials(urldecode($u['user']), isset($u['pass']) ? urldecode($u['pass']) : '');\r
- }\r
- }\r
-\r
- /**\r
- * gets the I/O method to use\r
- *\r
- * @return string I/O method to use (socket|curl|unknown)\r
- * @access private\r
- */\r
- function io_method() {\r
- if ($this->use_curl || ($this->scheme == 'https') || ($this->scheme == 'http' && $this->authtype == 'ntlm') || ($this->scheme == 'http' && is_array($this->proxy) && $this->proxy['authtype'] == 'ntlm'))\r
- return 'curl';\r
- if (($this->scheme == 'http' || $this->scheme == 'ssl') && $this->authtype != 'ntlm' && (!is_array($this->proxy) || $this->proxy['authtype'] != 'ntlm'))\r
- return 'socket';\r
- return 'unknown';\r
- }\r
-\r
- /**\r
- * establish an HTTP connection\r
- *\r
- * @param integer $timeout set connection timeout in seconds\r
- * @param integer $response_timeout set response timeout in seconds\r
- * @return boolean true if connected, false if not\r
- * @access private\r
- */\r
- function connect($connection_timeout=0,$response_timeout=30){\r
- // For PHP 4.3 with OpenSSL, change https scheme to ssl, then treat like\r
- // "regular" socket.\r
- // TODO: disabled for now because OpenSSL must be *compiled* in (not just\r
- // loaded), and until PHP5 stream_get_wrappers is not available.\r
-// if ($this->scheme == 'https') {\r
-// if (version_compare(phpversion(), '4.3.0') >= 0) {\r
-// if (extension_loaded('openssl')) {\r
-// $this->scheme = 'ssl';\r
-// $this->debug('Using SSL over OpenSSL');\r
-// }\r
-// }\r
-// }\r
- $this->debug("connect connection_timeout $connection_timeout, response_timeout $response_timeout, scheme $this->scheme, host $this->host, port $this->port");\r
- if ($this->io_method() == 'socket') {\r
- if (!is_array($this->proxy)) {\r
- $host = $this->host;\r
- $port = $this->port;\r
- } else {\r
- $host = $this->proxy['host'];\r
- $port = $this->proxy['port'];\r
- }\r
-\r
- // use persistent connection\r
- if($this->persistentConnection && isset($this->fp) && is_resource($this->fp)){\r
- if (!feof($this->fp)) {\r
- $this->debug('Re-use persistent connection');\r
- return true;\r
- }\r
- fclose($this->fp);\r
- $this->debug('Closed persistent connection at EOF');\r
- }\r
-\r
- // munge host if using OpenSSL\r
- if ($this->scheme == 'ssl') {\r
- $host = 'ssl://' . $host;\r
- }\r
- $this->debug('calling fsockopen with host ' . $host . ' connection_timeout ' . $connection_timeout);\r
-\r
- // open socket\r
- if($connection_timeout > 0){\r
- $this->fp = @fsockopen( $host, $this->port, $this->errno, $this->error_str, $connection_timeout);\r
- } else {\r
- $this->fp = @fsockopen( $host, $this->port, $this->errno, $this->error_str);\r
- }\r
- \r
- // test pointer\r
- if(!$this->fp) {\r
- $msg = 'Couldn\'t open socket connection to server ' . $this->url;\r
- if ($this->errno) {\r
- $msg .= ', Error ('.$this->errno.'): '.$this->error_str;\r
- } else {\r
- $msg .= ' prior to connect(). This is often a problem looking up the host name.';\r
- }\r
- $this->debug($msg);\r
- $this->setError($msg);\r
- return false;\r
- }\r
- \r
- // set response timeout\r
- $this->debug('set response timeout to ' . $response_timeout);\r
- socket_set_timeout( $this->fp, $response_timeout);\r
-\r
- $this->debug('socket connected');\r
- return true;\r
- } else if ($this->io_method() == 'curl') {\r
- if (!extension_loaded('curl')) {\r
-// $this->setError('cURL Extension, or OpenSSL extension w/ PHP version >= 4.3 is required for HTTPS');\r
- $this->setError('The PHP cURL Extension is required for HTTPS or NLTM. You will need to re-build or update your PHP to included cURL.');\r
- return false;\r
- }\r
- // Avoid warnings when PHP does not have these options\r
- if (defined('CURLOPT_CONNECTIONTIMEOUT'))\r
- $CURLOPT_CONNECTIONTIMEOUT = CURLOPT_CONNECTIONTIMEOUT;\r
- else\r
- $CURLOPT_CONNECTIONTIMEOUT = 78;\r
- if (defined('CURLOPT_HTTPAUTH'))\r
- $CURLOPT_HTTPAUTH = CURLOPT_HTTPAUTH;\r
- else\r
- $CURLOPT_HTTPAUTH = 107;\r
- if (defined('CURLOPT_PROXYAUTH'))\r
- $CURLOPT_PROXYAUTH = CURLOPT_PROXYAUTH;\r
- else\r
- $CURLOPT_PROXYAUTH = 111;\r
- if (defined('CURLAUTH_BASIC'))\r
- $CURLAUTH_BASIC = CURLAUTH_BASIC;\r
- else\r
- $CURLAUTH_BASIC = 1;\r
- if (defined('CURLAUTH_DIGEST'))\r
- $CURLAUTH_DIGEST = CURLAUTH_DIGEST;\r
- else\r
- $CURLAUTH_DIGEST = 2;\r
- if (defined('CURLAUTH_NTLM'))\r
- $CURLAUTH_NTLM = CURLAUTH_NTLM;\r
- else\r
- $CURLAUTH_NTLM = 8;\r
-\r
- $this->debug('connect using cURL');\r
- // init CURL\r
- $this->ch = curl_init();\r
- // set url\r
- $hostURL = ($this->port != '') ? "$this->scheme://$this->host:$this->port" : "$this->scheme://$this->host";\r
- // add path\r
- $hostURL .= $this->path;\r
- $this->setCurlOption(CURLOPT_URL, $hostURL);\r
- // follow location headers (re-directs)\r
- if (ini_get('safe_mode') || ini_get('open_basedir')) {\r
- $this->debug('safe_mode or open_basedir set, so do not set CURLOPT_FOLLOWLOCATION');\r
- $this->debug('safe_mode = ');\r
- $this->appendDebug($this->varDump(ini_get('safe_mode')));\r
- $this->debug('open_basedir = ');\r
- $this->appendDebug($this->varDump(ini_get('open_basedir')));\r
- } else {\r
- $this->setCurlOption(CURLOPT_FOLLOWLOCATION, 1);\r
- }\r
- // ask for headers in the response output\r
- $this->setCurlOption(CURLOPT_HEADER, 1);\r
- // ask for the response output as the return value\r
- $this->setCurlOption(CURLOPT_RETURNTRANSFER, 1);\r
- // encode\r
- // We manage this ourselves through headers and encoding\r
-// if(function_exists('gzuncompress')){\r
-// $this->setCurlOption(CURLOPT_ENCODING, 'deflate');\r
-// }\r
- // persistent connection\r
- if ($this->persistentConnection) {\r
- // I believe the following comment is now bogus, having applied to\r
- // the code when it used CURLOPT_CUSTOMREQUEST to send the request.\r
- // The way we send data, we cannot use persistent connections, since\r
- // there will be some "junk" at the end of our request.\r
- //$this->setCurlOption(CURL_HTTP_VERSION_1_1, true);\r
- $this->persistentConnection = false;\r
- $this->setHeader('Connection', 'close');\r
- }\r
- // set timeouts\r
- if ($connection_timeout != 0) {\r
- $this->setCurlOption($CURLOPT_CONNECTIONTIMEOUT, $connection_timeout);\r
- }\r
- if ($response_timeout != 0) {\r
- $this->setCurlOption(CURLOPT_TIMEOUT, $response_timeout);\r
- }\r
-\r
- if ($this->scheme == 'https') {\r
- $this->debug('set cURL SSL verify options');\r
- // recent versions of cURL turn on peer/host checking by default,\r
- // while PHP binaries are not compiled with a default location for the\r
- // CA cert bundle, so disable peer/host checking.\r
- //$this->setCurlOption(CURLOPT_CAINFO, 'f:\php-4.3.2-win32\extensions\curl-ca-bundle.crt'); \r
- $this->setCurlOption(CURLOPT_SSL_VERIFYPEER, 0);\r
- $this->setCurlOption(CURLOPT_SSL_VERIFYHOST, 0);\r
- \r
- // support client certificates (thanks Tobias Boes, Doug Anarino, Eryan Ariobowo)\r
- if ($this->authtype == 'certificate') {\r
- $this->debug('set cURL certificate options');\r
- if (isset($this->certRequest['cainfofile'])) {\r
- $this->setCurlOption(CURLOPT_CAINFO, $this->certRequest['cainfofile']);\r
- }\r
- if (isset($this->certRequest['verifypeer'])) {\r
- $this->setCurlOption(CURLOPT_SSL_VERIFYPEER, $this->certRequest['verifypeer']);\r
- } else {\r
- $this->setCurlOption(CURLOPT_SSL_VERIFYPEER, 1);\r
- }\r
- if (isset($this->certRequest['verifyhost'])) {\r
- $this->setCurlOption(CURLOPT_SSL_VERIFYHOST, $this->certRequest['verifyhost']);\r
- } else {\r
- $this->setCurlOption(CURLOPT_SSL_VERIFYHOST, 1);\r
- }\r
- if (isset($this->certRequest['sslcertfile'])) {\r
- $this->setCurlOption(CURLOPT_SSLCERT, $this->certRequest['sslcertfile']);\r
- }\r
- if (isset($this->certRequest['sslkeyfile'])) {\r
- $this->setCurlOption(CURLOPT_SSLKEY, $this->certRequest['sslkeyfile']);\r
- }\r
- if (isset($this->certRequest['passphrase'])) {\r
- $this->setCurlOption(CURLOPT_SSLKEYPASSWD, $this->certRequest['passphrase']);\r
- }\r
- if (isset($this->certRequest['certpassword'])) {\r
- $this->setCurlOption(CURLOPT_SSLCERTPASSWD, $this->certRequest['certpassword']);\r
- }\r
- }\r
- }\r
- if ($this->authtype && ($this->authtype != 'certificate')) {\r
- if ($this->username) {\r
- $this->debug('set cURL username/password');\r
- $this->setCurlOption(CURLOPT_USERPWD, "$this->username:$this->password");\r
- }\r
- if ($this->authtype == 'basic') {\r
- $this->debug('set cURL for Basic authentication');\r
- $this->setCurlOption($CURLOPT_HTTPAUTH, $CURLAUTH_BASIC);\r
- }\r
- if ($this->authtype == 'digest') {\r
- $this->debug('set cURL for digest authentication');\r
- $this->setCurlOption($CURLOPT_HTTPAUTH, $CURLAUTH_DIGEST);\r
- }\r
- if ($this->authtype == 'ntlm') {\r
- $this->debug('set cURL for NTLM authentication');\r
- $this->setCurlOption($CURLOPT_HTTPAUTH, $CURLAUTH_NTLM);\r
- }\r
- }\r
- if (is_array($this->proxy)) {\r
- $this->debug('set cURL proxy options');\r
- if ($this->proxy['port'] != '') {\r
- $this->setCurlOption(CURLOPT_PROXY, $this->proxy['host'].':'.$this->proxy['port']);\r
- } else {\r
- $this->setCurlOption(CURLOPT_PROXY, $this->proxy['host']);\r
- }\r
- if ($this->proxy['username'] || $this->proxy['password']) {\r
- $this->debug('set cURL proxy authentication options');\r
- $this->setCurlOption(CURLOPT_PROXYUSERPWD, $this->proxy['username'].':'.$this->proxy['password']);\r
- if ($this->proxy['authtype'] == 'basic') {\r
- $this->setCurlOption($CURLOPT_PROXYAUTH, $CURLAUTH_BASIC);\r
- }\r
- if ($this->proxy['authtype'] == 'ntlm') {\r
- $this->setCurlOption($CURLOPT_PROXYAUTH, $CURLAUTH_NTLM);\r
- }\r
- }\r
- }\r
- $this->debug('cURL connection set up');\r
- return true;\r
- } else {\r
- $this->setError('Unknown scheme ' . $this->scheme);\r
- $this->debug('Unknown scheme ' . $this->scheme);\r
- return false;\r
- }\r
- }\r
-\r
- /**\r
- * sends the SOAP request and gets the SOAP response via HTTP[S]\r
- *\r
- * @param string $data message data\r
- * @param integer $timeout set connection timeout in seconds\r
- * @param integer $response_timeout set response timeout in seconds\r
- * @param array $cookies cookies to send\r
- * @return string data\r
- * @access public\r
- */\r
- function send($data, $timeout=0, $response_timeout=30, $cookies=NULL) {\r
- \r
- $this->debug('entered send() with data of length: '.strlen($data));\r
-\r
- $this->tryagain = true;\r
- $tries = 0;\r
- while ($this->tryagain) {\r
- $this->tryagain = false;\r
- if ($tries++ < 2) {\r
- // make connnection\r
- if (!$this->connect($timeout, $response_timeout)){\r
- return false;\r
- }\r
- \r
- // send request\r
- if (!$this->sendRequest($data, $cookies)){\r
- return false;\r
- }\r
- \r
- // get response\r
- $respdata = $this->getResponse();\r
- } else {\r
- $this->setError("Too many tries to get an OK response ($this->response_status_line)");\r
- }\r
- } \r
- $this->debug('end of send()');\r
- return $respdata;\r
- }\r
-\r
-\r
- /**\r
- * sends the SOAP request and gets the SOAP response via HTTPS using CURL\r
- *\r
- * @param string $data message data\r
- * @param integer $timeout set connection timeout in seconds\r
- * @param integer $response_timeout set response timeout in seconds\r
- * @param array $cookies cookies to send\r
- * @return string data\r
- * @access public\r
- * @deprecated\r
- */\r
- function sendHTTPS($data, $timeout=0, $response_timeout=30, $cookies) {\r
- return $this->send($data, $timeout, $response_timeout, $cookies);\r
- }\r
- \r
- /**\r
- * if authenticating, set user credentials here\r
- *\r
- * @param string $username\r
- * @param string $password\r
- * @param string $authtype (basic|digest|certificate|ntlm)\r
- * @param array $digestRequest (keys must be nonce, nc, realm, qop)\r
- * @param array $certRequest (keys must be cainfofile (optional), sslcertfile, sslkeyfile, passphrase, certpassword (optional), verifypeer (optional), verifyhost (optional): see corresponding options in cURL docs)\r
- * @access public\r
- */\r
- function setCredentials($username, $password, $authtype = 'basic', $digestRequest = array(), $certRequest = array()) {\r
- $this->debug("setCredentials username=$username authtype=$authtype digestRequest=");\r
- $this->appendDebug($this->varDump($digestRequest));\r
- $this->debug("certRequest=");\r
- $this->appendDebug($this->varDump($certRequest));\r
- // cf. RFC 2617\r
- if ($authtype == 'basic') {\r
- $this->setHeader('Authorization', 'Basic '.base64_encode(str_replace(':','',$username).':'.$password));\r
- } elseif ($authtype == 'digest') {\r
- if (isset($digestRequest['nonce'])) {\r
- $digestRequest['nc'] = isset($digestRequest['nc']) ? $digestRequest['nc']++ : 1;\r
- \r
- // calculate the Digest hashes (calculate code based on digest implementation found at: http://www.rassoc.com/gregr/weblog/stories/2002/07/09/webServicesSecurityHttpDigestAuthenticationWithoutActiveDirectory.html)\r
- \r
- // A1 = unq(username-value) ":" unq(realm-value) ":" passwd\r
- $A1 = $username. ':' . (isset($digestRequest['realm']) ? $digestRequest['realm'] : '') . ':' . $password;\r
- \r
- // H(A1) = MD5(A1)\r
- $HA1 = md5($A1);\r
- \r
- // A2 = Method ":" digest-uri-value\r
- $A2 = $this->request_method . ':' . $this->digest_uri;\r
- \r
- // H(A2)\r
- $HA2 = md5($A2);\r
- \r
- // KD(secret, data) = H(concat(secret, ":", data))\r
- // if qop == auth:\r
- // request-digest = <"> < KD ( H(A1), unq(nonce-value)\r
- // ":" nc-value\r
- // ":" unq(cnonce-value)\r
- // ":" unq(qop-value)\r
- // ":" H(A2)\r
- // ) <">\r
- // if qop is missing,\r
- // request-digest = <"> < KD ( H(A1), unq(nonce-value) ":" H(A2) ) > <">\r
- \r
- $unhashedDigest = '';\r
- $nonce = isset($digestRequest['nonce']) ? $digestRequest['nonce'] : '';\r
- $cnonce = $nonce;\r
- if ($digestRequest['qop'] != '') {\r
- $unhashedDigest = $HA1 . ':' . $nonce . ':' . sprintf("%08d", $digestRequest['nc']) . ':' . $cnonce . ':' . $digestRequest['qop'] . ':' . $HA2;\r
- } else {\r
- $unhashedDigest = $HA1 . ':' . $nonce . ':' . $HA2;\r
- }\r
- \r
- $hashedDigest = md5($unhashedDigest);\r
- \r
- $opaque = ''; \r
- if (isset($digestRequest['opaque'])) {\r
- $opaque = ', opaque="' . $digestRequest['opaque'] . '"';\r
- }\r
-\r
- $this->setHeader('Authorization', 'Digest username="' . $username . '", realm="' . $digestRequest['realm'] . '", nonce="' . $nonce . '", uri="' . $this->digest_uri . $opaque . '", cnonce="' . $cnonce . '", nc=' . sprintf("%08x", $digestRequest['nc']) . ', qop="' . $digestRequest['qop'] . '", response="' . $hashedDigest . '"');\r
- }\r
- } elseif ($authtype == 'certificate') {\r
- $this->certRequest = $certRequest;\r
- $this->debug('Authorization header not set for certificate');\r
- } elseif ($authtype == 'ntlm') {\r
- // do nothing\r
- $this->debug('Authorization header not set for ntlm');\r
- }\r
- $this->username = $username;\r
- $this->password = $password;\r
- $this->authtype = $authtype;\r
- $this->digestRequest = $digestRequest;\r
- }\r
- \r
- /**\r
- * set the soapaction value\r
- *\r
- * @param string $soapaction\r
- * @access public\r
- */\r
- function setSOAPAction($soapaction) {\r
- $this->setHeader('SOAPAction', '"' . $soapaction . '"');\r
- }\r
- \r
- /**\r
- * use http encoding\r
- *\r
- * @param string $enc encoding style. supported values: gzip, deflate, or both\r
- * @access public\r
- */\r
- function setEncoding($enc='gzip, deflate') {\r
- if (function_exists('gzdeflate')) {\r
- $this->protocol_version = '1.1';\r
- $this->setHeader('Accept-Encoding', $enc);\r
- if (!isset($this->outgoing_headers['Connection'])) {\r
- $this->setHeader('Connection', 'close');\r
- $this->persistentConnection = false;\r
- }\r
- set_magic_quotes_runtime(0);\r
- // deprecated\r
- $this->encoding = $enc;\r
- }\r
- }\r
- \r
- /**\r
- * set proxy info here\r
- *\r
- * @param string $proxyhost use an empty string to remove proxy\r
- * @param string $proxyport\r
- * @param string $proxyusername\r
- * @param string $proxypassword\r
- * @param string $proxyauthtype (basic|ntlm)\r
- * @access public\r
- */\r
- function setProxy($proxyhost, $proxyport, $proxyusername = '', $proxypassword = '', $proxyauthtype = 'basic') {\r
- if ($proxyhost) {\r
- $this->proxy = array(\r
- 'host' => $proxyhost,\r
- 'port' => $proxyport,\r
- 'username' => $proxyusername,\r
- 'password' => $proxypassword,\r
- 'authtype' => $proxyauthtype\r
- );\r
- if ($proxyusername != '' && $proxypassword != '' && $proxyauthtype = 'basic') {\r
- $this->setHeader('Proxy-Authorization', ' Basic '.base64_encode($proxyusername.':'.$proxypassword));\r
- }\r
- } else {\r
- $this->debug('remove proxy');\r
- $proxy = null;\r
- unsetHeader('Proxy-Authorization');\r
- }\r
- }\r
- \r
-\r
- /**\r
- * Test if the given string starts with a header that is to be skipped.\r
- * Skippable headers result from chunked transfer and proxy requests.\r
- *\r
- * @param string $data The string to check.\r
- * @returns boolean Whether a skippable header was found.\r
- * @access private\r
- */\r
- function isSkippableCurlHeader(&$data) {\r
- $skipHeaders = array( 'HTTP/1.1 100',\r
- 'HTTP/1.0 301',\r
- 'HTTP/1.1 301',\r
- 'HTTP/1.0 302',\r
- 'HTTP/1.1 302',\r
- 'HTTP/1.0 401',\r
- 'HTTP/1.1 401',\r
- 'HTTP/1.0 200 Connection established');\r
- foreach ($skipHeaders as $hd) {\r
- $prefix = substr($data, 0, strlen($hd));\r
- if ($prefix == $hd) return true;\r
- }\r
-\r
- return false;\r
- }\r
-\r
- /**\r
- * decode a string that is encoded w/ "chunked' transfer encoding\r
- * as defined in RFC2068 19.4.6\r
- *\r
- * @param string $buffer\r
- * @param string $lb\r
- * @returns string\r
- * @access public\r
- * @deprecated\r
- */\r
- function decodeChunked($buffer, $lb){\r
- // length := 0\r
- $length = 0;\r
- $new = '';\r
- \r
- // read chunk-size, chunk-extension (if any) and CRLF\r
- // get the position of the linebreak\r
- $chunkend = strpos($buffer, $lb);\r
- if ($chunkend == FALSE) {\r
- $this->debug('no linebreak found in decodeChunked');\r
- return $new;\r
- }\r
- $temp = substr($buffer,0,$chunkend);\r
- $chunk_size = hexdec( trim($temp) );\r
- $chunkstart = $chunkend + strlen($lb);\r
- // while (chunk-size > 0) {\r
- while ($chunk_size > 0) {\r
- $this->debug("chunkstart: $chunkstart chunk_size: $chunk_size");\r
- $chunkend = strpos( $buffer, $lb, $chunkstart + $chunk_size);\r
- \r
- // Just in case we got a broken connection\r
- if ($chunkend == FALSE) {\r
- $chunk = substr($buffer,$chunkstart);\r
- // append chunk-data to entity-body\r
- $new .= $chunk;\r
- $length += strlen($chunk);\r
- break;\r
- }\r
- \r
- // read chunk-data and CRLF\r
- $chunk = substr($buffer,$chunkstart,$chunkend-$chunkstart);\r
- // append chunk-data to entity-body\r
- $new .= $chunk;\r
- // length := length + chunk-size\r
- $length += strlen($chunk);\r
- // read chunk-size and CRLF\r
- $chunkstart = $chunkend + strlen($lb);\r
- \r
- $chunkend = strpos($buffer, $lb, $chunkstart) + strlen($lb);\r
- if ($chunkend == FALSE) {\r
- break; //Just in case we got a broken connection\r
- }\r
- $temp = substr($buffer,$chunkstart,$chunkend-$chunkstart);\r
- $chunk_size = hexdec( trim($temp) );\r
- $chunkstart = $chunkend;\r
- }\r
- return $new;\r
- }\r
- \r
- /**\r
- * Writes the payload, including HTTP headers, to $this->outgoing_payload.\r
- *\r
- * @param string $data HTTP body\r
- * @param string $cookie_str data for HTTP Cookie header\r
- * @return void\r
- * @access private\r
- */\r
- function buildPayload($data, $cookie_str = '') {\r
- // Note: for cURL connections, $this->outgoing_payload is ignored,\r
- // as is the Content-Length header, but these are still created as\r
- // debugging guides.\r
-\r
- // add content-length header\r
- $this->setHeader('Content-Length', strlen($data));\r
-\r
- // start building outgoing payload:\r
- if ($this->proxy) {\r
- $uri = $this->url;\r
- } else {\r
- $uri = $this->uri;\r
- }\r
- $req = "$this->request_method $uri HTTP/$this->protocol_version";\r
- $this->debug("HTTP request: $req");\r
- $this->outgoing_payload = "$req\r\n";\r
-\r
- // loop thru headers, serializing\r
- foreach($this->outgoing_headers as $k => $v){\r
- $hdr = $k.': '.$v;\r
- $this->debug("HTTP header: $hdr");\r
- $this->outgoing_payload .= "$hdr\r\n";\r
- }\r
-\r
- // add any cookies\r
- if ($cookie_str != '') {\r
- $hdr = 'Cookie: '.$cookie_str;\r
- $this->debug("HTTP header: $hdr");\r
- $this->outgoing_payload .= "$hdr\r\n";\r
- }\r
-\r
- // header/body separator\r
- $this->outgoing_payload .= "\r\n";\r
- \r
- // add data\r
- $this->outgoing_payload .= $data;\r
- }\r
-\r
- /**\r
- * sends the SOAP request via HTTP[S]\r
- *\r
- * @param string $data message data\r
- * @param array $cookies cookies to send\r
- * @return boolean true if OK, false if problem\r
- * @access private\r
- */\r
- function sendRequest($data, $cookies = NULL) {\r
- // build cookie string\r
- $cookie_str = $this->getCookiesForRequest($cookies, (($this->scheme == 'ssl') || ($this->scheme == 'https')));\r
-\r
- // build payload\r
- $this->buildPayload($data, $cookie_str);\r
-\r
- if ($this->io_method() == 'socket') {\r
- // send payload\r
- if(!fputs($this->fp, $this->outgoing_payload, strlen($this->outgoing_payload))) {\r
- $this->setError('couldn\'t write message data to socket');\r
- $this->debug('couldn\'t write message data to socket');\r
- return false;\r
- }\r
- $this->debug('wrote data to socket, length = ' . strlen($this->outgoing_payload));\r
- return true;\r
- } else if ($this->io_method() == 'curl') {\r
- // set payload\r
- // cURL does say this should only be the verb, and in fact it\r
- // turns out that the URI and HTTP version are appended to this, which\r
- // some servers refuse to work with (so we no longer use this method!)\r
- //$this->setCurlOption(CURLOPT_CUSTOMREQUEST, $this->outgoing_payload);\r
- $curl_headers = array();\r
- foreach($this->outgoing_headers as $k => $v){\r
- if ($k == 'Connection' || $k == 'Content-Length' || $k == 'Host' || $k == 'Authorization' || $k == 'Proxy-Authorization') {\r
- $this->debug("Skip cURL header $k: $v");\r
- } else {\r
- $curl_headers[] = "$k: $v";\r
- }\r
- }\r
- if ($cookie_str != '') {\r
- $curl_headers[] = 'Cookie: ' . $cookie_str;\r
- }\r
- $this->setCurlOption(CURLOPT_HTTPHEADER, $curl_headers);\r
- $this->debug('set cURL HTTP headers');\r
- if ($this->request_method == "POST") {\r
- $this->setCurlOption(CURLOPT_POST, 1);\r
- $this->setCurlOption(CURLOPT_POSTFIELDS, $data);\r
- $this->debug('set cURL POST data');\r
- } else {\r
- }\r
- // insert custom user-set cURL options\r
- foreach ($this->ch_options as $key => $val) {\r
- $this->setCurlOption($key, $val);\r
- }\r
-\r
- $this->debug('set cURL payload');\r
- return true;\r
- }\r
- }\r
-\r
- /**\r
- * gets the SOAP response via HTTP[S]\r
- *\r
- * @return string the response (also sets member variables like incoming_payload)\r
- * @access private\r
- */\r
- function getResponse(){\r
- $this->incoming_payload = '';\r
- \r
- if ($this->io_method() == 'socket') {\r
- // loop until headers have been retrieved\r
- $data = '';\r
- while (!isset($lb)){\r
-\r
- // We might EOF during header read.\r
- if(feof($this->fp)) {\r
- $this->incoming_payload = $data;\r
- $this->debug('found no headers before EOF after length ' . strlen($data));\r
- $this->debug("received before EOF:\n" . $data);\r
- $this->setError('server failed to send headers');\r
- return false;\r
- }\r
-\r
- $tmp = fgets($this->fp, 256);\r
- $tmplen = strlen($tmp);\r
- $this->debug("read line of $tmplen bytes: " . trim($tmp));\r
-\r
- if ($tmplen == 0) {\r
- $this->incoming_payload = $data;\r
- $this->debug('socket read of headers timed out after length ' . strlen($data));\r
- $this->debug("read before timeout: " . $data);\r
- $this->setError('socket read of headers timed out');\r
- return false;\r
- }\r
-\r
- $data .= $tmp;\r
- $pos = strpos($data,"\r\n\r\n");\r
- if($pos > 1){\r
- $lb = "\r\n";\r
- } else {\r
- $pos = strpos($data,"\n\n");\r
- if($pos > 1){\r
- $lb = "\n";\r
- }\r
- }\r
- // remove 100 headers\r
- if (isset($lb) && ereg('^HTTP/1.1 100',$data)) {\r
- unset($lb);\r
- $data = '';\r
- }//\r
- }\r
- // store header data\r
- $this->incoming_payload .= $data;\r
- $this->debug('found end of headers after length ' . strlen($data));\r
- // process headers\r
- $header_data = trim(substr($data,0,$pos));\r
- $header_array = explode($lb,$header_data);\r
- $this->incoming_headers = array();\r
- $this->incoming_cookies = array();\r
- foreach($header_array as $header_line){\r
- $arr = explode(':',$header_line, 2);\r
- if(count($arr) > 1){\r
- $header_name = strtolower(trim($arr[0]));\r
- $this->incoming_headers[$header_name] = trim($arr[1]);\r
- if ($header_name == 'set-cookie') {\r
- // TODO: allow multiple cookies from parseCookie\r
- $cookie = $this->parseCookie(trim($arr[1]));\r
- if ($cookie) {\r
- $this->incoming_cookies[] = $cookie;\r
- $this->debug('found cookie: ' . $cookie['name'] . ' = ' . $cookie['value']);\r
- } else {\r
- $this->debug('did not find cookie in ' . trim($arr[1]));\r
- }\r
- }\r
- } else if (isset($header_name)) {\r
- // append continuation line to previous header\r
- $this->incoming_headers[$header_name] .= $lb . ' ' . $header_line;\r
- }\r
- }\r
- \r
- // loop until msg has been received\r
- if (isset($this->incoming_headers['transfer-encoding']) && strtolower($this->incoming_headers['transfer-encoding']) == 'chunked') {\r
- $content_length = 2147483647; // ignore any content-length header\r
- $chunked = true;\r
- $this->debug("want to read chunked content");\r
- } elseif (isset($this->incoming_headers['content-length'])) {\r
- $content_length = $this->incoming_headers['content-length'];\r
- $chunked = false;\r
- $this->debug("want to read content of length $content_length");\r
- } else {\r
- $content_length = 2147483647;\r
- $chunked = false;\r
- $this->debug("want to read content to EOF");\r
- }\r
- $data = '';\r
- do {\r
- if ($chunked) {\r
- $tmp = fgets($this->fp, 256);\r
- $tmplen = strlen($tmp);\r
- $this->debug("read chunk line of $tmplen bytes");\r
- if ($tmplen == 0) {\r
- $this->incoming_payload = $data;\r
- $this->debug('socket read of chunk length timed out after length ' . strlen($data));\r
- $this->debug("read before timeout:\n" . $data);\r
- $this->setError('socket read of chunk length timed out');\r
- return false;\r
- }\r
- $content_length = hexdec(trim($tmp));\r
- $this->debug("chunk length $content_length");\r
- }\r
- $strlen = 0;\r
- while (($strlen < $content_length) && (!feof($this->fp))) {\r
- $readlen = min(8192, $content_length - $strlen);\r
- $tmp = fread($this->fp, $readlen);\r
- $tmplen = strlen($tmp);\r
- $this->debug("read buffer of $tmplen bytes");\r
- if (($tmplen == 0) && (!feof($this->fp))) {\r
- $this->incoming_payload = $data;\r
- $this->debug('socket read of body timed out after length ' . strlen($data));\r
- $this->debug("read before timeout:\n" . $data);\r
- $this->setError('socket read of body timed out');\r
- return false;\r
- }\r
- $strlen += $tmplen;\r
- $data .= $tmp;\r
- }\r
- if ($chunked && ($content_length > 0)) {\r
- $tmp = fgets($this->fp, 256);\r
- $tmplen = strlen($tmp);\r
- $this->debug("read chunk terminator of $tmplen bytes");\r
- if ($tmplen == 0) {\r
- $this->incoming_payload = $data;\r
- $this->debug('socket read of chunk terminator timed out after length ' . strlen($data));\r
- $this->debug("read before timeout:\n" . $data);\r
- $this->setError('socket read of chunk terminator timed out');\r
- return false;\r
- }\r
- }\r
- } while ($chunked && ($content_length > 0) && (!feof($this->fp)));\r
- if (feof($this->fp)) {\r
- $this->debug('read to EOF');\r
- }\r
- $this->debug('read body of length ' . strlen($data));\r
- $this->incoming_payload .= $data;\r
- $this->debug('received a total of '.strlen($this->incoming_payload).' bytes of data from server');\r
- \r
- // close filepointer\r
- if(\r
- (isset($this->incoming_headers['connection']) && strtolower($this->incoming_headers['connection']) == 'close') || \r
- (! $this->persistentConnection) || feof($this->fp)){\r
- fclose($this->fp);\r
- $this->fp = false;\r
- $this->debug('closed socket');\r
- }\r
- \r
- // connection was closed unexpectedly\r
- if($this->incoming_payload == ''){\r
- $this->setError('no response from server');\r
- return false;\r
- }\r
- \r
- // decode transfer-encoding\r
-// if(isset($this->incoming_headers['transfer-encoding']) && strtolower($this->incoming_headers['transfer-encoding']) == 'chunked'){\r
-// if(!$data = $this->decodeChunked($data, $lb)){\r
-// $this->setError('Decoding of chunked data failed');\r
-// return false;\r
-// }\r
- //print "<pre>\nde-chunked:\n---------------\n$data\n\n---------------\n</pre>";\r
- // set decoded payload\r
-// $this->incoming_payload = $header_data.$lb.$lb.$data;\r
-// }\r
- \r
- } else if ($this->io_method() == 'curl') {\r
- // send and receive\r
- $this->debug('send and receive with cURL');\r
- $this->incoming_payload = curl_exec($this->ch);\r
- $data = $this->incoming_payload;\r
-\r
- $cErr = curl_error($this->ch);\r
- if ($cErr != '') {\r
- $err = 'cURL ERROR: '.curl_errno($this->ch).': '.$cErr.'<br>';\r
- // TODO: there is a PHP bug that can cause this to SEGV for CURLINFO_CONTENT_TYPE\r
- foreach(curl_getinfo($this->ch) as $k => $v){\r
- $err .= "$k: $v<br>";\r
- }\r
- $this->debug($err);\r
- $this->setError($err);\r
- curl_close($this->ch);\r
- return false;\r
- } else {\r
- ////echo '<pre>';\r
- //var_dump(curl_getinfo($this->ch));\r
- ////echo '</pre>';\r
- }\r
- // close curl\r
- $this->debug('No cURL error, closing cURL');\r
- curl_close($this->ch);\r
- \r
- // try removing skippable headers\r
- $savedata = $data;\r
- while ($this->isSkippableCurlHeader($data)) {\r
- $this->debug("Found HTTP header to skip");\r
- if ($pos = strpos($data,"\r\n\r\n")) {\r
- $data = ltrim(substr($data,$pos));\r
- } elseif($pos = strpos($data,"\n\n") ) {\r
- $data = ltrim(substr($data,$pos));\r
- }\r
- }\r
-\r
- if ($data == '') {\r
- // have nothing left; just remove 100 header(s)\r
- $data = $savedata;\r
- while (ereg('^HTTP/1.1 100',$data)) {\r
- if ($pos = strpos($data,"\r\n\r\n")) {\r
- $data = ltrim(substr($data,$pos));\r
- } elseif($pos = strpos($data,"\n\n") ) {\r
- $data = ltrim(substr($data,$pos));\r
- }\r
- }\r
- }\r
- \r
- // separate content from HTTP headers\r
- if ($pos = strpos($data,"\r\n\r\n")) {\r
- $lb = "\r\n";\r
- } elseif( $pos = strpos($data,"\n\n")) {\r
- $lb = "\n";\r
- } else {\r
- $this->debug('no proper separation of headers and document');\r
- $this->setError('no proper separation of headers and document');\r
- return false;\r
- }\r
- $header_data = trim(substr($data,0,$pos));\r
- $header_array = explode($lb,$header_data);\r
- $data = ltrim(substr($data,$pos));\r
- $this->debug('found proper separation of headers and document');\r
- $this->debug('cleaned data, stringlen: '.strlen($data));\r
- // clean headers\r
- foreach ($header_array as $header_line) {\r
- $arr = explode(':',$header_line,2);\r
- if(count($arr) > 1){\r
- $header_name = strtolower(trim($arr[0]));\r
- $this->incoming_headers[$header_name] = trim($arr[1]);\r
- if ($header_name == 'set-cookie') {\r
- // TODO: allow multiple cookies from parseCookie\r
- $cookie = $this->parseCookie(trim($arr[1]));\r
- if ($cookie) {\r
- $this->incoming_cookies[] = $cookie;\r
- $this->debug('found cookie: ' . $cookie['name'] . ' = ' . $cookie['value']);\r
- } else {\r
- $this->debug('did not find cookie in ' . trim($arr[1]));\r
- }\r
- }\r
- } else if (isset($header_name)) {\r
- // append continuation line to previous header\r
- $this->incoming_headers[$header_name] .= $lb . ' ' . $header_line;\r
- }\r
- }\r
- }\r
-\r
- $this->response_status_line = $header_array[0];\r
- $arr = explode(' ', $this->response_status_line, 3);\r
- $http_version = $arr[0];\r
- $http_status = intval($arr[1]);\r
- $http_reason = count($arr) > 2 ? $arr[2] : '';\r
-\r
- // see if we need to resend the request with http digest authentication\r
- if (isset($this->incoming_headers['location']) && ($http_status == 301 || $http_status == 302)) {\r
- $this->debug("Got $http_status $http_reason with Location: " . $this->incoming_headers['location']);\r
- $this->setURL($this->incoming_headers['location']);\r
- $this->tryagain = true;\r
- return false;\r
- }\r
-\r
- // see if we need to resend the request with http digest authentication\r
- if (isset($this->incoming_headers['www-authenticate']) && $http_status == 401) {\r
- $this->debug("Got 401 $http_reason with WWW-Authenticate: " . $this->incoming_headers['www-authenticate']);\r
- if (strstr($this->incoming_headers['www-authenticate'], "Digest ")) {\r
- $this->debug('Server wants digest authentication');\r
- // remove "Digest " from our elements\r
- $digestString = str_replace('Digest ', '', $this->incoming_headers['www-authenticate']);\r
- \r
- // parse elements into array\r
- $digestElements = explode(',', $digestString);\r
- foreach ($digestElements as $val) {\r
- $tempElement = explode('=', trim($val), 2);\r
- $digestRequest[$tempElement[0]] = str_replace("\"", '', $tempElement[1]);\r
- }\r
-\r
- // should have (at least) qop, realm, nonce\r
- if (isset($digestRequest['nonce'])) {\r
- $this->setCredentials($this->username, $this->password, 'digest', $digestRequest);\r
- $this->tryagain = true;\r
- return false;\r
- }\r
- }\r
- $this->debug('HTTP authentication failed');\r
- $this->setError('HTTP authentication failed');\r
- return false;\r
- }\r
- \r
- if (\r
- ($http_status >= 300 && $http_status <= 307) ||\r
- ($http_status >= 400 && $http_status <= 417) ||\r
- ($http_status >= 501 && $http_status <= 505)\r
- ) {\r
- $this->setError("Unsupported HTTP response status $http_status $http_reason (soapclient->response has contents of the response)");\r
- return false;\r
- }\r
-\r
- // decode content-encoding\r
- if(isset($this->incoming_headers['content-encoding']) && $this->incoming_headers['content-encoding'] != ''){\r
- if(strtolower($this->incoming_headers['content-encoding']) == 'deflate' || strtolower($this->incoming_headers['content-encoding']) == 'gzip'){\r
- // if decoding works, use it. else assume data wasn't gzencoded\r
- if(function_exists('gzinflate')){\r
- //$timer->setMarker('starting decoding of gzip/deflated content');\r
- // IIS 5 requires gzinflate instead of gzuncompress (similar to IE 5 and gzdeflate v. gzcompress)\r
- // this means there are no Zlib headers, although there should be\r
- $this->debug('The gzinflate function exists');\r
- $datalen = strlen($data);\r
- if ($this->incoming_headers['content-encoding'] == 'deflate') {\r
- if ($degzdata = @gzinflate($data)) {\r
- $data = $degzdata;\r
- $this->debug('The payload has been inflated to ' . strlen($data) . ' bytes');\r
- if (strlen($data) < $datalen) {\r
- // test for the case that the payload has been compressed twice\r
- $this->debug('The inflated payload is smaller than the gzipped one; try again');\r
- if ($degzdata = @gzinflate($data)) {\r
- $data = $degzdata;\r
- $this->debug('The payload has been inflated again to ' . strlen($data) . ' bytes');\r
- }\r
- }\r
- } else {\r
- $this->debug('Error using gzinflate to inflate the payload');\r
- $this->setError('Error using gzinflate to inflate the payload');\r
- }\r
- } elseif ($this->incoming_headers['content-encoding'] == 'gzip') {\r
- if ($degzdata = @gzinflate(substr($data, 10))) { // do our best\r
- $data = $degzdata;\r
- $this->debug('The payload has been un-gzipped to ' . strlen($data) . ' bytes');\r
- if (strlen($data) < $datalen) {\r
- // test for the case that the payload has been compressed twice\r
- $this->debug('The un-gzipped payload is smaller than the gzipped one; try again');\r
- if ($degzdata = @gzinflate(substr($data, 10))) {\r
- $data = $degzdata;\r
- $this->debug('The payload has been un-gzipped again to ' . strlen($data) . ' bytes');\r
- }\r
- }\r
- } else {\r
- $this->debug('Error using gzinflate to un-gzip the payload');\r
- $this->setError('Error using gzinflate to un-gzip the payload');\r
- }\r
- }\r
- //$timer->setMarker('finished decoding of gzip/deflated content');\r
- //print "<xmp>\nde-inflated:\n---------------\n$data\n-------------\n</xmp>";\r
- // set decoded payload\r
- $this->incoming_payload = $header_data.$lb.$lb.$data;\r
- } else {\r
- $this->debug('The server sent compressed data. Your php install must have the Zlib extension compiled in to support this.');\r
- $this->setError('The server sent compressed data. Your php install must have the Zlib extension compiled in to support this.');\r
- }\r
- } else {\r
- $this->debug('Unsupported Content-Encoding ' . $this->incoming_headers['content-encoding']);\r
- $this->setError('Unsupported Content-Encoding ' . $this->incoming_headers['content-encoding']);\r
- }\r
- } else {\r
- $this->debug('No Content-Encoding header');\r
- }\r
- \r
- if(strlen($data) == 0){\r
- $this->debug('no data after headers!');\r
- $this->setError('no data present after HTTP headers');\r
- return false;\r
- }\r
- \r
- return $data;\r
- }\r
-\r
- /**\r
- * sets the content-type for the SOAP message to be sent\r
- *\r
- * @param string $type the content type, MIME style\r
- * @param mixed $charset character set used for encoding (or false)\r
- * @access public\r
- */\r
- function setContentType($type, $charset = false) {\r
- $this->setHeader('Content-Type', $type . ($charset ? '; charset=' . $charset : ''));\r
- }\r
-\r
- /**\r
- * specifies that an HTTP persistent connection should be used\r
- *\r
- * @return boolean whether the request was honored by this method.\r
- * @access public\r
- */\r
- function usePersistentConnection(){\r
- if (isset($this->outgoing_headers['Accept-Encoding'])) {\r
- return false;\r
- }\r
- $this->protocol_version = '1.1';\r
- $this->persistentConnection = true;\r
- $this->setHeader('Connection', 'Keep-Alive');\r
- return true;\r
- }\r
-\r
- /**\r
- * parse an incoming Cookie into it's parts\r
- *\r
- * @param string $cookie_str content of cookie\r
- * @return array with data of that cookie\r
- * @access private\r
- */\r
- /*\r
- * TODO: allow a Set-Cookie string to be parsed into multiple cookies\r
- */\r
- function parseCookie($cookie_str) {\r
- $cookie_str = str_replace('; ', ';', $cookie_str) . ';';\r
- $data = split(';', $cookie_str);\r
- $value_str = $data[0];\r
-\r
- $cookie_param = 'domain=';\r
- $start = strpos($cookie_str, $cookie_param);\r
- if ($start > 0) {\r
- $domain = substr($cookie_str, $start + strlen($cookie_param));\r
- $domain = substr($domain, 0, strpos($domain, ';'));\r
- } else {\r
- $domain = '';\r
- }\r
-\r
- $cookie_param = 'expires=';\r
- $start = strpos($cookie_str, $cookie_param);\r
- if ($start > 0) {\r
- $expires = substr($cookie_str, $start + strlen($cookie_param));\r
- $expires = substr($expires, 0, strpos($expires, ';'));\r
- } else {\r
- $expires = '';\r
- }\r
-\r
- $cookie_param = 'path=';\r
- $start = strpos($cookie_str, $cookie_param);\r
- if ( $start > 0 ) {\r
- $path = substr($cookie_str, $start + strlen($cookie_param));\r
- $path = substr($path, 0, strpos($path, ';'));\r
- } else {\r
- $path = '/';\r
- }\r
- \r
- $cookie_param = ';secure;';\r
- if (strpos($cookie_str, $cookie_param) !== FALSE) {\r
- $secure = true;\r
- } else {\r
- $secure = false;\r
- }\r
-\r
- $sep_pos = strpos($value_str, '=');\r
-\r
- if ($sep_pos) {\r
- $name = substr($value_str, 0, $sep_pos);\r
- $value = substr($value_str, $sep_pos + 1);\r
- $cookie= array( 'name' => $name,\r
- 'value' => $value,\r
- 'domain' => $domain,\r
- 'path' => $path,\r
- 'expires' => $expires,\r
- 'secure' => $secure\r
- ); \r
- return $cookie;\r
- }\r
- return false;\r
- }\r
- \r
- /**\r
- * sort out cookies for the current request\r
- *\r
- * @param array $cookies array with all cookies\r
- * @param boolean $secure is the send-content secure or not?\r
- * @return string for Cookie-HTTP-Header\r
- * @access private\r
- */\r
- function getCookiesForRequest($cookies, $secure=false) {\r
- $cookie_str = '';\r
- if ((! is_null($cookies)) && (is_array($cookies))) {\r
- foreach ($cookies as $cookie) {\r
- if (! is_array($cookie)) {\r
- continue;\r
- }\r
- $this->debug("check cookie for validity: ".$cookie['name'].'='.$cookie['value']);\r
- if ((isset($cookie['expires'])) && (! empty($cookie['expires']))) {\r
- if (strtotime($cookie['expires']) <= time()) {\r
- $this->debug('cookie has expired');\r
- continue;\r
- }\r
- }\r
- if ((isset($cookie['domain'])) && (! empty($cookie['domain']))) {\r
- $domain = preg_quote($cookie['domain']);\r
- if (! preg_match("'.*$domain$'i", $this->host)) {\r
- $this->debug('cookie has different domain');\r
- continue;\r
- }\r
- }\r
- if ((isset($cookie['path'])) && (! empty($cookie['path']))) {\r
- $path = preg_quote($cookie['path']);\r
- if (! preg_match("'^$path.*'i", $this->path)) {\r
- $this->debug('cookie is for a different path');\r
- continue;\r
- }\r
- }\r
- if ((! $secure) && (isset($cookie['secure'])) && ($cookie['secure'])) {\r
- $this->debug('cookie is secure, transport is not');\r
- continue;\r
- }\r
- $cookie_str .= $cookie['name'] . '=' . $cookie['value'] . '; ';\r
- $this->debug('add cookie to Cookie-String: ' . $cookie['name'] . '=' . $cookie['value']);\r
- }\r
- }\r
- return $cookie_str;\r
- }\r
-}\r
-\r
-?><?php\r
-\r
-\r
-\r
-/**\r
-* parses a WSDL file, allows access to it's data, other utility methods.\r
-* also builds WSDL structures programmatically.\r
-* \r
-* @author Dietrich Ayala <dietrich@ganx4.com>\r
-* @author Scott Nichol <snichol@users.sourceforge.net>\r
-* @version $Id: nusoap.php,v 1.114 2007/11/06 15:17:46 snichol Exp $\r
-* @access public \r
-*/\r
-class wsdl extends nusoap_base {\r
- // URL or filename of the root of this WSDL\r
- var $wsdl; \r
- // define internal arrays of bindings, ports, operations, messages, etc.\r
- var $schemas = array();\r
- var $currentSchema;\r
- var $message = array();\r
- var $complexTypes = array();\r
- var $messages = array();\r
- var $currentMessage;\r
- var $currentOperation;\r
- var $portTypes = array();\r
- var $currentPortType;\r
- var $bindings = array();\r
- var $currentBinding;\r
- var $ports = array();\r
- var $currentPort;\r
- var $opData = array();\r
- var $status = '';\r
- var $documentation = false;\r
- var $endpoint = ''; \r
- // array of wsdl docs to import\r
- var $import = array(); \r
- // parser vars\r
- var $parser;\r
- var $position = 0;\r
- var $depth = 0;\r
- var $depth_array = array();\r
- // for getting wsdl\r
- var $proxyhost = '';\r
- var $proxyport = '';\r
- var $proxyusername = '';\r
- var $proxypassword = '';\r
- var $timeout = 0;\r
- var $response_timeout = 30;\r
- var $curl_options = array(); // User-specified cURL options\r
- var $use_curl = false; // whether to always try to use cURL\r
- // for HTTP authentication\r
- var $username = ''; // Username for HTTP authentication\r
- var $password = ''; // Password for HTTP authentication\r
- var $authtype = ''; // Type of HTTP authentication\r
- var $certRequest = array(); // Certificate for HTTP SSL authentication\r
-\r
- /**\r
- * constructor\r
- * \r
- * @param string $wsdl WSDL document URL\r
- * @param string $proxyhost\r
- * @param string $proxyport\r
- * @param string $proxyusername\r
- * @param string $proxypassword\r
- * @param integer $timeout set the connection timeout\r
- * @param integer $response_timeout set the response timeout\r
- * @param array $curl_options user-specified cURL options\r
- * @param boolean $use_curl try to use cURL\r
- * @access public \r
- */\r
- function wsdl($wsdl = '',$proxyhost=false,$proxyport=false,$proxyusername=false,$proxypassword=false,$timeout=0,$response_timeout=30,$curl_options=null,$use_curl=false){\r
- parent::nusoap_base();\r
- $this->debug("ctor wsdl=$wsdl timeout=$timeout response_timeout=$response_timeout");\r
- $this->proxyhost = $proxyhost;\r
- $this->proxyport = $proxyport;\r
- $this->proxyusername = $proxyusername;\r
- $this->proxypassword = $proxypassword;\r
- $this->timeout = $timeout;\r
- $this->response_timeout = $response_timeout;\r
- if (is_array($curl_options))\r
- $this->curl_options = $curl_options;\r
- $this->use_curl = $use_curl;\r
- $this->fetchWSDL($wsdl);\r
- }\r
-\r
- /**\r
- * fetches the WSDL document and parses it\r
- *\r
- * @access public\r
- */\r
- function fetchWSDL($wsdl) {\r
- $this->debug("parse and process WSDL path=$wsdl");\r
- $this->wsdl = $wsdl;\r
- // parse wsdl file\r
- if ($this->wsdl != "") {\r
- $this->parseWSDL($this->wsdl);\r
- }\r
- // imports\r
- // TODO: handle imports more properly, grabbing them in-line and nesting them\r
- $imported_urls = array();\r
- $imported = 1;\r
- while ($imported > 0) {\r
- $imported = 0;\r
- // Schema imports\r
- foreach ($this->schemas as $ns => $list) {\r
- foreach ($list as $xs) {\r
- $wsdlparts = parse_url($this->wsdl); // this is bogusly simple!\r
- foreach ($xs->imports as $ns2 => $list2) {\r
- for ($ii = 0; $ii < count($list2); $ii++) {\r
- if (! $list2[$ii]['loaded']) {\r
- $this->schemas[$ns]->imports[$ns2][$ii]['loaded'] = true;\r
- $url = $list2[$ii]['location'];\r
- if ($url != '') {\r
- $urlparts = parse_url($url);\r
- if (!isset($urlparts['host'])) {\r
- $url = $wsdlparts['scheme'] . '://' . $wsdlparts['host'] . (isset($wsdlparts['port']) ? ':' .$wsdlparts['port'] : '') .\r
- substr($wsdlparts['path'],0,strrpos($wsdlparts['path'],'/') + 1) .$urlparts['path'];\r
- }\r
- if (! in_array($url, $imported_urls)) {\r
- $this->parseWSDL($url);\r
- $imported++;\r
- $imported_urls[] = $url;\r
- }\r
- } else {\r
- $this->debug("Unexpected scenario: empty URL for unloaded import");\r
- }\r
- }\r
- }\r
- } \r
- }\r
- }\r
- // WSDL imports\r
- $wsdlparts = parse_url($this->wsdl); // this is bogusly simple!\r
- foreach ($this->import as $ns => $list) {\r
- for ($ii = 0; $ii < count($list); $ii++) {\r
- if (! $list[$ii]['loaded']) {\r
- $this->import[$ns][$ii]['loaded'] = true;\r
- $url = $list[$ii]['location'];\r
- if ($url != '') {\r
- $urlparts = parse_url($url);\r
- if (!isset($urlparts['host'])) {\r
- $url = $wsdlparts['scheme'] . '://' . $wsdlparts['host'] . (isset($wsdlparts['port']) ? ':' . $wsdlparts['port'] : '') .\r
- substr($wsdlparts['path'],0,strrpos($wsdlparts['path'],'/') + 1) .$urlparts['path'];\r
- }\r
- if (! in_array($url, $imported_urls)) {\r
- $this->parseWSDL($url);\r
- $imported++;\r
- $imported_urls[] = $url;\r
- }\r
- } else {\r
- $this->debug("Unexpected scenario: empty URL for unloaded import");\r
- }\r
- }\r
- }\r
- } \r
- }\r
- // add new data to operation data\r
- foreach($this->bindings as $binding => $bindingData) {\r
- if (isset($bindingData['operations']) && is_array($bindingData['operations'])) {\r
- foreach($bindingData['operations'] as $operation => $data) {\r
- $this->debug('post-parse data gathering for ' . $operation);\r
- $this->bindings[$binding]['operations'][$operation]['input'] = \r
- isset($this->bindings[$binding]['operations'][$operation]['input']) ? \r
- array_merge($this->bindings[$binding]['operations'][$operation]['input'], $this->portTypes[ $bindingData['portType'] ][$operation]['input']) :\r
- $this->portTypes[ $bindingData['portType'] ][$operation]['input'];\r
- $this->bindings[$binding]['operations'][$operation]['output'] = \r
- isset($this->bindings[$binding]['operations'][$operation]['output']) ?\r
- array_merge($this->bindings[$binding]['operations'][$operation]['output'], $this->portTypes[ $bindingData['portType'] ][$operation]['output']) :\r
- $this->portTypes[ $bindingData['portType'] ][$operation]['output'];\r
- if(isset($this->messages[ $this->bindings[$binding]['operations'][$operation]['input']['message'] ])){\r
- $this->bindings[$binding]['operations'][$operation]['input']['parts'] = $this->messages[ $this->bindings[$binding]['operations'][$operation]['input']['message'] ];\r
- }\r
- if(isset($this->messages[ $this->bindings[$binding]['operations'][$operation]['output']['message'] ])){\r
- $this->bindings[$binding]['operations'][$operation]['output']['parts'] = $this->messages[ $this->bindings[$binding]['operations'][$operation]['output']['message'] ];\r
- }\r
- // Set operation style if necessary, but do not override one already provided\r
- if (isset($bindingData['style']) && !isset($this->bindings[$binding]['operations'][$operation]['style'])) {\r
- $this->bindings[$binding]['operations'][$operation]['style'] = $bindingData['style'];\r
- }\r
- $this->bindings[$binding]['operations'][$operation]['transport'] = isset($bindingData['transport']) ? $bindingData['transport'] : '';\r
- $this->bindings[$binding]['operations'][$operation]['documentation'] = isset($this->portTypes[ $bindingData['portType'] ][$operation]['documentation']) ? $this->portTypes[ $bindingData['portType'] ][$operation]['documentation'] : '';\r
- $this->bindings[$binding]['operations'][$operation]['endpoint'] = isset($bindingData['endpoint']) ? $bindingData['endpoint'] : '';\r
- } \r
- } \r
- }\r
- }\r
-\r
- /**\r
- * parses the wsdl document\r
- * \r
- * @param string $wsdl path or URL\r
- * @access private \r
- */\r
- function parseWSDL($wsdl = '') {\r
- $this->debug("parse WSDL at path=$wsdl");\r
-\r
- if ($wsdl == '') {\r
- $this->debug('no wsdl passed to parseWSDL()!!');\r
- $this->setError('no wsdl passed to parseWSDL()!!');\r
- return false;\r
- }\r
- \r
- // parse $wsdl for url format\r
- $wsdl_props = parse_url($wsdl);\r
-\r
- if (isset($wsdl_props['scheme']) && ($wsdl_props['scheme'] == 'http' || $wsdl_props['scheme'] == 'https')) {\r
- $this->debug('getting WSDL http(s) URL ' . $wsdl);\r
- // get wsdl\r
- $tr = new soap_transport_http($wsdl, $this->curl_options, $this->use_curl);\r
- $tr->request_method = 'GET';\r
- $tr->useSOAPAction = false;\r
- if($this->proxyhost && $this->proxyport){\r
- $tr->setProxy($this->proxyhost,$this->proxyport,$this->proxyusername,$this->proxypassword);\r
- }\r
- if ($this->authtype != '') {\r
- $tr->setCredentials($this->username, $this->password, $this->authtype, array(), $this->certRequest);\r
- }\r
- $tr->setEncoding('gzip, deflate');\r
- $wsdl_string = $tr->send('', $this->timeout, $this->response_timeout);\r
- //$this->debug("WSDL request\n" . $tr->outgoing_payload);\r
- //$this->debug("WSDL response\n" . $tr->incoming_payload);\r
- $this->appendDebug($tr->getDebug());\r
- // catch errors\r
- if($err = $tr->getError() ){\r
- $errstr = 'HTTP ERROR: '.$err;\r
- $this->debug($errstr);\r
- $this->setError($errstr);\r
- unset($tr);\r
- return false;\r
- }\r
- unset($tr);\r
- $this->debug("got WSDL URL");\r
- } else {\r
- // $wsdl is not http(s), so treat it as a file URL or plain file path\r
- if (isset($wsdl_props['scheme']) && ($wsdl_props['scheme'] == 'file') && isset($wsdl_props['path'])) {\r
- $path = isset($wsdl_props['host']) ? ($wsdl_props['host'] . ':' . $wsdl_props['path']) : $wsdl_props['path'];\r
- } else {\r
- $path = $wsdl;\r
- }\r
- $this->debug('getting WSDL file ' . $path);\r
- if ($fp = @fopen($path, 'r')) {\r
- $wsdl_string = '';\r
- while ($data = fread($fp, 32768)) {\r
- $wsdl_string .= $data;\r
- } \r
- fclose($fp);\r
- } else {\r
- $errstr = "Bad path to WSDL file $path";\r
- $this->debug($errstr);\r
- $this->setError($errstr);\r
- return false;\r
- } \r
- }\r
- $this->debug('Parse WSDL');\r
- // end new code added\r
- // Create an XML parser.\r
- $this->parser = xml_parser_create(); \r
- // Set the options for parsing the XML data.\r
- // xml_parser_set_option($parser, XML_OPTION_SKIP_WHITE, 1);\r
- xml_parser_set_option($this->parser, XML_OPTION_CASE_FOLDING, 0); \r
- // Set the object for the parser.\r
- xml_set_object($this->parser, $this); \r
- // Set the element handlers for the parser.\r
- xml_set_element_handler($this->parser, 'start_element', 'end_element');\r
- xml_set_character_data_handler($this->parser, 'character_data');\r
- // Parse the XML file.\r
- if (!xml_parse($this->parser, $wsdl_string, true)) {\r
- // Display an error message.\r
- $errstr = sprintf(\r
- 'XML error parsing WSDL from %s on line %d: %s',\r
- $wsdl,\r
- xml_get_current_line_number($this->parser),\r
- xml_error_string(xml_get_error_code($this->parser))\r
- );\r
- $this->debug($errstr);\r
- $this->debug("XML payload:\n" . $wsdl_string);\r
- $this->setError($errstr);\r
- return false;\r
- } \r
- // free the parser\r
- xml_parser_free($this->parser);\r
- $this->debug('Parsing WSDL done');\r
- // catch wsdl parse errors\r
- if($this->getError()){\r
- return false;\r
- }\r
- return true;\r
- } \r
-\r
- /**\r
- * start-element handler\r
- * \r
- * @param string $parser XML parser object\r
- * @param string $name element name\r
- * @param string $attrs associative array of attributes\r
- * @access private \r
- */\r
- function start_element($parser, $name, $attrs)\r
- {\r
- if ($this->status == 'schema') {\r
- $this->currentSchema->schemaStartElement($parser, $name, $attrs);\r
- $this->appendDebug($this->currentSchema->getDebug());\r
- $this->currentSchema->clearDebug();\r
- } elseif (ereg('schema$', $name)) {\r
- $this->debug('Parsing WSDL schema');\r
- // $this->debug("startElement for $name ($attrs[name]). status = $this->status (".$this->getLocalPart($name).")");\r
- $this->status = 'schema';\r
- $this->currentSchema = new nusoap_xmlschema('', '', $this->namespaces);\r
- $this->currentSchema->schemaStartElement($parser, $name, $attrs);\r
- $this->appendDebug($this->currentSchema->getDebug());\r
- $this->currentSchema->clearDebug();\r
- } else {\r
- // position in the total number of elements, starting from 0\r
- $pos = $this->position++;\r
- $depth = $this->depth++; \r
- // set self as current value for this depth\r
- $this->depth_array[$depth] = $pos;\r
- $this->message[$pos] = array('cdata' => ''); \r
- // process attributes\r
- if (count($attrs) > 0) {\r
- // register namespace declarations\r
- foreach($attrs as $k => $v) {\r
- if (ereg("^xmlns", $k)) {\r
- if ($ns_prefix = substr(strrchr($k, ':'), 1)) {\r
- $this->namespaces[$ns_prefix] = $v;\r
- } else {\r
- $this->namespaces['ns' . (count($this->namespaces) + 1)] = $v;\r
- } \r
- if ($v == 'http://www.w3.org/2001/XMLSchema' || $v == 'http://www.w3.org/1999/XMLSchema' || $v == 'http://www.w3.org/2000/10/XMLSchema') {\r
- $this->XMLSchemaVersion = $v;\r
- $this->namespaces['xsi'] = $v . '-instance';\r
- } \r
- }\r
- }\r
- // expand each attribute prefix to its namespace\r
- foreach($attrs as $k => $v) {\r
- $k = strpos($k, ':') ? $this->expandQname($k) : $k;\r
- if ($k != 'location' && $k != 'soapAction' && $k != 'namespace') {\r
- $v = strpos($v, ':') ? $this->expandQname($v) : $v;\r
- } \r
- $eAttrs[$k] = $v;\r
- } \r
- $attrs = $eAttrs;\r
- } else {\r
- $attrs = array();\r
- } \r
- // get element prefix, namespace and name\r
- if (ereg(':', $name)) {\r
- // get ns prefix\r
- $prefix = substr($name, 0, strpos($name, ':')); \r
- // get ns\r
- $namespace = isset($this->namespaces[$prefix]) ? $this->namespaces[$prefix] : ''; \r
- // get unqualified name\r
- $name = substr(strstr($name, ':'), 1);\r
- } \r
- // process attributes, expanding any prefixes to namespaces\r
- // find status, register data\r
- switch ($this->status) {\r
- case 'message':\r
- if ($name == 'part') {\r
- if (isset($attrs['type'])) {\r
- $this->debug("msg " . $this->currentMessage . ": found part (with type) $attrs[name]: " . implode(',', $attrs));\r
- $this->messages[$this->currentMessage][$attrs['name']] = $attrs['type'];\r
- } \r
- if (isset($attrs['element'])) {\r
- $this->debug("msg " . $this->currentMessage . ": found part (with element) $attrs[name]: " . implode(',', $attrs));\r
- $this->messages[$this->currentMessage][$attrs['name']] = $attrs['element'] . '^';\r
- } \r
- } \r
- break;\r
- case 'portType':\r
- switch ($name) {\r
- case 'operation':\r
- $this->currentPortOperation = $attrs['name'];\r
- $this->debug("portType $this->currentPortType operation: $this->currentPortOperation");\r
- if (isset($attrs['parameterOrder'])) {\r
- $this->portTypes[$this->currentPortType][$attrs['name']]['parameterOrder'] = $attrs['parameterOrder'];\r
- } \r
- break;\r
- case 'documentation':\r
- $this->documentation = true;\r
- break; \r
- // merge input/output data\r
- default:\r
- $m = isset($attrs['message']) ? $this->getLocalPart($attrs['message']) : '';\r
- $this->portTypes[$this->currentPortType][$this->currentPortOperation][$name]['message'] = $m;\r
- break;\r
- } \r
- break;\r
- case 'binding':\r
- switch ($name) {\r
- case 'binding': \r
- // get ns prefix\r
- if (isset($attrs['style'])) {\r
- $this->bindings[$this->currentBinding]['prefix'] = $prefix;\r
- } \r
- $this->bindings[$this->currentBinding] = array_merge($this->bindings[$this->currentBinding], $attrs);\r
- break;\r
- case 'header':\r
- $this->bindings[$this->currentBinding]['operations'][$this->currentOperation][$this->opStatus]['headers'][] = $attrs;\r
- break;\r
- case 'operation':\r
- if (isset($attrs['soapAction'])) {\r
- $this->bindings[$this->currentBinding]['operations'][$this->currentOperation]['soapAction'] = $attrs['soapAction'];\r
- } \r
- if (isset($attrs['style'])) {\r
- $this->bindings[$this->currentBinding]['operations'][$this->currentOperation]['style'] = $attrs['style'];\r
- } \r
- if (isset($attrs['name'])) {\r
- $this->currentOperation = $attrs['name'];\r
- $this->debug("current binding operation: $this->currentOperation");\r
- $this->bindings[$this->currentBinding]['operations'][$this->currentOperation]['name'] = $attrs['name'];\r
- $this->bindings[$this->currentBinding]['operations'][$this->currentOperation]['binding'] = $this->currentBinding;\r
- $this->bindings[$this->currentBinding]['operations'][$this->currentOperation]['endpoint'] = isset($this->bindings[$this->currentBinding]['endpoint']) ? $this->bindings[$this->currentBinding]['endpoint'] : '';\r
- } \r
- break;\r
- case 'input':\r
- $this->opStatus = 'input';\r
- break;\r
- case 'output':\r
- $this->opStatus = 'output';\r
- break;\r
- case 'body':\r
- if (isset($this->bindings[$this->currentBinding]['operations'][$this->currentOperation][$this->opStatus])) {\r
- $this->bindings[$this->currentBinding]['operations'][$this->currentOperation][$this->opStatus] = array_merge($this->bindings[$this->currentBinding]['operations'][$this->currentOperation][$this->opStatus], $attrs);\r
- } else {\r
- $this->bindings[$this->currentBinding]['operations'][$this->currentOperation][$this->opStatus] = $attrs;\r
- } \r
- break;\r
- } \r
- break;\r
- case 'service':\r
- switch ($name) {\r
- case 'port':\r
- $this->currentPort = $attrs['name'];\r
- $this->debug('current port: ' . $this->currentPort);\r
- $this->ports[$this->currentPort]['binding'] = $this->getLocalPart($attrs['binding']);\r
- \r
- break;\r
- case 'address':\r
- $this->ports[$this->currentPort]['location'] = $attrs['location'];\r
- $this->ports[$this->currentPort]['bindingType'] = $namespace;\r
- $this->bindings[ $this->ports[$this->currentPort]['binding'] ]['bindingType'] = $namespace;\r
- $this->bindings[ $this->ports[$this->currentPort]['binding'] ]['endpoint'] = $attrs['location'];\r
- break;\r
- } \r
- break;\r
- } \r
- // set status\r
- switch ($name) {\r
- case 'import':\r
- if (isset($attrs['location'])) {\r
- $this->import[$attrs['namespace']][] = array('location' => $attrs['location'], 'loaded' => false);\r
- $this->debug('parsing import ' . $attrs['namespace']. ' - ' . $attrs['location'] . ' (' . count($this->import[$attrs['namespace']]).')');\r
- } else {\r
- $this->import[$attrs['namespace']][] = array('location' => '', 'loaded' => true);\r
- if (! $this->getPrefixFromNamespace($attrs['namespace'])) {\r
- $this->namespaces['ns'.(count($this->namespaces)+1)] = $attrs['namespace'];\r
- }\r
- $this->debug('parsing import ' . $attrs['namespace']. ' - [no location] (' . count($this->import[$attrs['namespace']]).')');\r
- }\r
- break;\r
- //wait for schema\r
- //case 'types':\r
- // $this->status = 'schema';\r
- // break;\r
- case 'message':\r
- $this->status = 'message';\r
- $this->messages[$attrs['name']] = array();\r
- $this->currentMessage = $attrs['name'];\r
- break;\r
- case 'portType':\r
- $this->status = 'portType';\r
- $this->portTypes[$attrs['name']] = array();\r
- $this->currentPortType = $attrs['name'];\r
- break;\r
- case "binding":\r
- if (isset($attrs['name'])) {\r
- // get binding name\r
- if (strpos($attrs['name'], ':')) {\r
- $this->currentBinding = $this->getLocalPart($attrs['name']);\r
- } else {\r
- $this->currentBinding = $attrs['name'];\r
- } \r
- $this->status = 'binding';\r
- $this->bindings[$this->currentBinding]['portType'] = $this->getLocalPart($attrs['type']);\r
- $this->debug("current binding: $this->currentBinding of portType: " . $attrs['type']);\r
- } \r
- break;\r
- case 'service':\r
- $this->serviceName = $attrs['name'];\r
- $this->status = 'service';\r
- $this->debug('current service: ' . $this->serviceName);\r
- break;\r
- case 'definitions':\r
- foreach ($attrs as $name => $value) {\r
- $this->wsdl_info[$name] = $value;\r
- } \r
- break;\r
- } \r
- } \r
- } \r
-\r
- /**\r
- * end-element handler\r
- * \r
- * @param string $parser XML parser object\r
- * @param string $name element name\r
- * @access private \r
- */\r
- function end_element($parser, $name){ \r
- // unset schema status\r
- if (/*ereg('types$', $name) ||*/ ereg('schema$', $name)) {\r
- $this->status = "";\r
- $this->appendDebug($this->currentSchema->getDebug());\r
- $this->currentSchema->clearDebug();\r
- $this->schemas[$this->currentSchema->schemaTargetNamespace][] = $this->currentSchema;\r
- $this->debug('Parsing WSDL schema done');\r
- } \r
- if ($this->status == 'schema') {\r
- $this->currentSchema->schemaEndElement($parser, $name);\r
- } else {\r
- // bring depth down a notch\r
- $this->depth--;\r
- } \r
- // end documentation\r
- if ($this->documentation) {\r
- //TODO: track the node to which documentation should be assigned; it can be a part, message, etc.\r
- //$this->portTypes[$this->currentPortType][$this->currentPortOperation]['documentation'] = $this->documentation;\r
- $this->documentation = false;\r
- } \r
- } \r
-\r
- /**\r
- * element content handler\r
- * \r
- * @param string $parser XML parser object\r
- * @param string $data element content\r
- * @access private \r
- */\r
- function character_data($parser, $data)\r
- {\r
- $pos = isset($this->depth_array[$this->depth]) ? $this->depth_array[$this->depth] : 0;\r
- if (isset($this->message[$pos]['cdata'])) {\r
- $this->message[$pos]['cdata'] .= $data;\r
- } \r
- if ($this->documentation) {\r
- $this->documentation .= $data;\r
- } \r
- } \r
- \r
- /**\r
- * if authenticating, set user credentials here\r
- *\r
- * @param string $username\r
- * @param string $password\r
- * @param string $authtype (basic|digest|certificate|ntlm)\r
- * @param array $certRequest (keys must be cainfofile (optional), sslcertfile, sslkeyfile, passphrase, certpassword (optional), verifypeer (optional), verifyhost (optional): see corresponding options in cURL docs)\r
- * @access public\r
- */\r
- function setCredentials($username, $password, $authtype = 'basic', $certRequest = array()) {\r
- $this->debug("setCredentials username=$username authtype=$authtype certRequest=");\r
- $this->appendDebug($this->varDump($certRequest));\r
- $this->username = $username;\r
- $this->password = $password;\r
- $this->authtype = $authtype;\r
- $this->certRequest = $certRequest;\r
- }\r
- \r
- function getBindingData($binding)\r
- {\r
- if (is_array($this->bindings[$binding])) {\r
- return $this->bindings[$binding];\r
- } \r
- }\r
- \r
- /**\r
- * returns an assoc array of operation names => operation data\r
- * \r
- * @param string $bindingType eg: soap, smtp, dime (only soap and soap12 are currently supported)\r
- * @return array \r
- * @access public \r
- */\r
- function getOperations($bindingType = 'soap') {\r
- $ops = array();\r
- if ($bindingType == 'soap') {\r
- $bindingType = 'http://schemas.xmlsoap.org/wsdl/soap/';\r
- } elseif ($bindingType == 'soap12') {\r
- $bindingType = 'http://schemas.xmlsoap.org/wsdl/soap12/';\r
- }\r
- // loop thru ports\r
- foreach($this->ports as $port => $portData) {\r
- // binding type of port matches parameter\r
- if ($portData['bindingType'] == $bindingType) {\r
- //$this->debug("getOperations for port $port");\r
- //$this->debug("port data: " . $this->varDump($portData));\r
- //$this->debug("bindings: " . $this->varDump($this->bindings[ $portData['binding'] ]));\r
- // merge bindings\r
- if (isset($this->bindings[ $portData['binding'] ]['operations'])) {\r
- $ops = array_merge ($ops, $this->bindings[ $portData['binding'] ]['operations']);\r
- }\r
- }\r
- } \r
- return $ops;\r
- } \r
- \r
- /**\r
- * returns an associative array of data necessary for calling an operation\r
- * \r
- * @param string $operation name of operation\r
- * @param string $bindingType type of binding eg: soap, soap12\r
- * @return array \r
- * @access public \r
- */\r
- function getOperationData($operation, $bindingType = 'soap')\r
- {\r
- if ($bindingType == 'soap') {\r
- $bindingType = 'http://schemas.xmlsoap.org/wsdl/soap/';\r
- } elseif ($bindingType == 'soap12') {\r
- $bindingType = 'http://schemas.xmlsoap.org/wsdl/soap12/';\r
- }\r
- // loop thru ports\r
- foreach($this->ports as $port => $portData) {\r
- // binding type of port matches parameter\r
- if ($portData['bindingType'] == $bindingType) {\r
- // get binding\r
- //foreach($this->bindings[ $portData['binding'] ]['operations'] as $bOperation => $opData) {\r
- foreach(array_keys($this->bindings[ $portData['binding'] ]['operations']) as $bOperation) {\r
- // note that we could/should also check the namespace here\r
- if ($operation == $bOperation) {\r
- $opData = $this->bindings[ $portData['binding'] ]['operations'][$operation];\r
- return $opData;\r
- } \r
- } \r
- }\r
- } \r
- }\r
- \r
- /**\r
- * returns an associative array of data necessary for calling an operation\r
- * \r
- * @param string $soapAction soapAction for operation\r
- * @param string $bindingType type of binding eg: soap, soap12\r
- * @return array \r
- * @access public \r
- */\r
- function getOperationDataForSoapAction($soapAction, $bindingType = 'soap') {\r
- if ($bindingType == 'soap') {\r
- $bindingType = 'http://schemas.xmlsoap.org/wsdl/soap/';\r
- } elseif ($bindingType == 'soap12') {\r
- $bindingType = 'http://schemas.xmlsoap.org/wsdl/soap12/';\r
- }\r
- // loop thru ports\r
- foreach($this->ports as $port => $portData) {\r
- // binding type of port matches parameter\r
- if ($portData['bindingType'] == $bindingType) {\r
- // loop through operations for the binding\r
- foreach ($this->bindings[ $portData['binding'] ]['operations'] as $bOperation => $opData) {\r
- if ($opData['soapAction'] == $soapAction) {\r
- return $opData;\r
- } \r
- } \r
- }\r
- } \r
- }\r
- \r
- /**\r
- * returns an array of information about a given type\r
- * returns false if no type exists by the given name\r
- *\r
- * typeDef = array(\r
- * 'elements' => array(), // refs to elements array\r
- * 'restrictionBase' => '',\r
- * 'phpType' => '',\r
- * 'order' => '(sequence|all)',\r
- * 'attrs' => array() // refs to attributes array\r
- * )\r
- *\r
- * @param string $type the type\r
- * @param string $ns namespace (not prefix) of the type\r
- * @return mixed\r
- * @access public\r
- * @see nusoap_xmlschema\r
- */\r
- function getTypeDef($type, $ns) {\r
- $this->debug("in getTypeDef: type=$type, ns=$ns");\r
- if ((! $ns) && isset($this->namespaces['tns'])) {\r
- $ns = $this->namespaces['tns'];\r
- $this->debug("in getTypeDef: type namespace forced to $ns");\r
- }\r
- if (!isset($this->schemas[$ns])) {\r
- foreach ($this->schemas as $ns0 => $schema0) {\r
- if (strcasecmp($ns, $ns0) == 0) {\r
- $this->debug("in getTypeDef: replacing schema namespace $ns with $ns0");\r
- $ns = $ns0;\r
- break;\r
- }\r
- }\r
- }\r
- if (isset($this->schemas[$ns])) {\r
- $this->debug("in getTypeDef: have schema for namespace $ns");\r
- for ($i = 0; $i < count($this->schemas[$ns]); $i++) {\r
- $xs = &$this->schemas[$ns][$i];\r
- $t = $xs->getTypeDef($type);\r
- //$this->appendDebug($xs->getDebug());\r
- //$xs->clearDebug();\r
- if ($t) {\r
- if (!isset($t['phpType'])) {\r
- // get info for type to tack onto the element\r
- $uqType = substr($t['type'], strrpos($t['type'], ':') + 1);\r
- $ns = substr($t['type'], 0, strrpos($t['type'], ':'));\r
- $etype = $this->getTypeDef($uqType, $ns);\r
- if ($etype) {\r
- $this->debug("found type for [element] $type:");\r
- $this->debug($this->varDump($etype));\r
- if (isset($etype['phpType'])) {\r
- $t['phpType'] = $etype['phpType'];\r
- }\r
- if (isset($etype['elements'])) {\r
- $t['elements'] = $etype['elements'];\r
- }\r
- if (isset($etype['attrs'])) {\r
- $t['attrs'] = $etype['attrs'];\r
- }\r
- }\r
- }\r
- return $t;\r
- }\r
- }\r
- } else {\r
- $this->debug("in getTypeDef: do not have schema for namespace $ns");\r
- }\r
- return false;\r
- }\r
-\r
- /**\r
- * prints html description of services\r
- *\r
- * @access private\r
- */\r
- function webDescription(){\r
- global $HTTP_SERVER_VARS;\r
-\r
- if (isset($_SERVER)) {\r
- $PHP_SELF = $_SERVER['PHP_SELF'];\r
- } elseif (isset($HTTP_SERVER_VARS)) {\r
- $PHP_SELF = $HTTP_SERVER_VARS['PHP_SELF'];\r
- } else {\r
- $this->setError("Neither _SERVER nor HTTP_SERVER_VARS is available");\r
- }\r
-\r
- $b = '\r
- <html><head><title>NuSOAP: '.$this->serviceName.'</title>\r
- <style type="text/css">\r
- body { font-family: arial; color: #000000; background-color: #ffffff; margin: 0px 0px 0px 0px; }\r
- p { font-family: arial; color: #000000; margin-top: 0px; margin-bottom: 12px; }\r
- pre { background-color: silver; padding: 5px; font-family: Courier New; font-size: x-small; color: #000000;}\r
- ul { margin-top: 10px; margin-left: 20px; }\r
- li { list-style-type: none; margin-top: 10px; color: #000000; }\r
- .content{\r
- margin-left: 0px; padding-bottom: 2em; }\r
- .nav {\r
- padding-top: 10px; padding-bottom: 10px; padding-left: 15px; font-size: .70em;\r
- margin-top: 10px; margin-left: 0px; color: #000000;\r
- background-color: #ccccff; width: 20%; margin-left: 20px; margin-top: 20px; }\r
- .title {\r
- font-family: arial; font-size: 26px; color: #ffffff;\r
- background-color: #999999; width: 105%; margin-left: 0px;\r
- padding-top: 10px; padding-bottom: 10px; padding-left: 15px;}\r
- .hidden {\r
- position: absolute; visibility: hidden; z-index: 200; left: 250px; top: 100px;\r
- font-family: arial; overflow: hidden; width: 600;\r
- padding: 20px; font-size: 10px; background-color: #999999;\r
- layer-background-color:#FFFFFF; }\r
- a,a:active { color: charcoal; font-weight: bold; }\r
- a:visited { color: #666666; font-weight: bold; }\r
- a:hover { color: cc3300; font-weight: bold; }\r
- </style>\r
- <script language="JavaScript" type="text/javascript">\r
- <!--\r
- // POP-UP CAPTIONS...\r
- function lib_bwcheck(){ //Browsercheck (needed)\r
- this.ver=navigator.appVersion\r
- this.agent=navigator.userAgent\r
- this.dom=document.getElementById?1:0\r
- this.opera5=this.agent.indexOf("Opera 5")>-1\r
- this.ie5=(this.ver.indexOf("MSIE 5")>-1 && this.dom && !this.opera5)?1:0;\r
- this.ie6=(this.ver.indexOf("MSIE 6")>-1 && this.dom && !this.opera5)?1:0;\r
- this.ie4=(document.all && !this.dom && !this.opera5)?1:0;\r
- this.ie=this.ie4||this.ie5||this.ie6\r
- this.mac=this.agent.indexOf("Mac")>-1\r
- this.ns6=(this.dom && parseInt(this.ver) >= 5) ?1:0;\r
- this.ns4=(document.layers && !this.dom)?1:0;\r
- this.bw=(this.ie6 || this.ie5 || this.ie4 || this.ns4 || this.ns6 || this.opera5)\r
- return this\r
- }\r
- var bw = new lib_bwcheck()\r
- //Makes crossbrowser object.\r
- function makeObj(obj){\r
- this.evnt=bw.dom? document.getElementById(obj):bw.ie4?document.all[obj]:bw.ns4?document.layers[obj]:0;\r
- if(!this.evnt) return false\r
- this.css=bw.dom||bw.ie4?this.evnt.style:bw.ns4?this.evnt:0;\r
- this.wref=bw.dom||bw.ie4?this.evnt:bw.ns4?this.css.document:0;\r
- this.writeIt=b_writeIt;\r
- return this\r
- }\r
- // A unit of measure that will be added when setting the position of a layer.\r
- //var px = bw.ns4||window.opera?"":"px";\r
- function b_writeIt(text){\r
- if (bw.ns4){this.wref.write(text);this.wref.close()}\r
- else this.wref.innerHTML = text\r
- }\r
- //Shows the messages\r
- var oDesc;\r
- function popup(divid){\r
- if(oDesc = new makeObj(divid)){\r
- oDesc.css.visibility = "visible"\r
- }\r
- }\r
- function popout(){ // Hides message\r
- if(oDesc) oDesc.css.visibility = "hidden"\r
- }\r
- //-->\r
- </script>\r
- </head>\r
- <body>\r
- <div class=content>\r
- <br><br>\r
- <div class=title>'.$this->serviceName.'</div>\r
- <div class=nav>\r
- <p>View the <a href="'.$PHP_SELF.'?wsdl">WSDL</a> for the service.\r
- Click on an operation name to view it's details.</p>\r
- <ul>';\r
- foreach($this->getOperations() as $op => $data){\r
- $b .= "<li><a href='#' onclick=\"popout();popup('$op')\">$op</a></li>";\r
- // create hidden div\r
- $b .= "<div id='$op' class='hidden'>\r
- <a href='#' onclick='popout()'><font color='#ffffff'>Close</font></a><br><br>";\r
- foreach($data as $donnie => $marie){ // loop through opdata\r
- if($donnie == 'input' || $donnie == 'output'){ // show input/output data\r
- $b .= "<font color='white'>".ucfirst($donnie).':</font><br>';\r
- foreach($marie as $captain => $tenille){ // loop through data\r
- if($captain == 'parts'){ // loop thru parts\r
- $b .= " $captain:<br>";\r
- //if(is_array($tenille)){\r
- foreach($tenille as $joanie => $chachi){\r
- $b .= " $joanie: $chachi<br>";\r
- }\r
- //}\r
- } else {\r
- $b .= " $captain: $tenille<br>";\r
- }\r
- }\r
- } else {\r
- $b .= "<font color='white'>".ucfirst($donnie).":</font> $marie<br>";\r
- }\r
- }\r
- $b .= '</div>';\r
- }\r
- $b .= '\r
- <ul>\r
- </div>\r
- </div></body></html>';\r
- return $b;\r
- }\r
-\r
- /**\r
- * serialize the parsed wsdl\r
- *\r
- * @param mixed $debug whether to put debug=1 in endpoint URL\r
- * @return string serialization of WSDL\r
- * @access public \r
- */\r
- function serialize($debug = 0)\r
- {\r
- $xml = '<?xml version="1.0" encoding="ISO-8859-1"?>';\r
- $xml .= "\n<definitions";\r
- foreach($this->namespaces as $k => $v) {\r
- $xml .= " xmlns:$k=\"$v\"";\r
- } \r
- // 10.9.02 - add poulter fix for wsdl and tns declarations\r
- if (isset($this->namespaces['wsdl'])) {\r
- $xml .= " xmlns=\"" . $this->namespaces['wsdl'] . "\"";\r
- } \r
- if (isset($this->namespaces['tns'])) {\r
- $xml .= " targetNamespace=\"" . $this->namespaces['tns'] . "\"";\r
- } \r
- $xml .= '>'; \r
- // imports\r
- if (sizeof($this->import) > 0) {\r
- foreach($this->import as $ns => $list) {\r
- foreach ($list as $ii) {\r
- if ($ii['location'] != '') {\r
- $xml .= '<import location="' . $ii['location'] . '" namespace="' . $ns . '" />';\r
- } else {\r
- $xml .= '<import namespace="' . $ns . '" />';\r
- }\r
- }\r
- } \r
- } \r
- // types\r
- if (count($this->schemas)>=1) {\r
- $xml .= "\n<types>\n";\r
- foreach ($this->schemas as $ns => $list) {\r
- foreach ($list as $xs) {\r
- $xml .= $xs->serializeSchema();\r
- }\r
- }\r
- $xml .= '</types>';\r
- } \r
- // messages\r
- if (count($this->messages) >= 1) {\r
- foreach($this->messages as $msgName => $msgParts) {\r
- $xml .= "\n<message name=\"" . $msgName . '">';\r
- if(is_array($msgParts)){\r
- foreach($msgParts as $partName => $partType) {\r
- // print 'serializing '.$partType.', sv: '.$this->XMLSchemaVersion.'<br>';\r
- if (strpos($partType, ':')) {\r
- $typePrefix = $this->getPrefixFromNamespace($this->getPrefix($partType));\r
- } elseif (isset($this->typemap[$this->namespaces['xsd']][$partType])) {\r
- // print 'checking typemap: '.$this->XMLSchemaVersion.'<br>';\r
- $typePrefix = 'xsd';\r
- } else {\r
- foreach($this->typemap as $ns => $types) {\r
- if (isset($types[$partType])) {\r
- $typePrefix = $this->getPrefixFromNamespace($ns);\r
- } \r
- } \r
- if (!isset($typePrefix)) {\r
- die("$partType has no namespace!");\r
- } \r
- }\r
- $ns = $this->getNamespaceFromPrefix($typePrefix);\r
- $localPart = $this->getLocalPart($partType);\r
- $typeDef = $this->getTypeDef($localPart, $ns);\r
- if ($typeDef['typeClass'] == 'element') {\r
- $elementortype = 'element';\r
- if (substr($localPart, -1) == '^') {\r
- $localPart = substr($localPart, 0, -1);\r
- }\r
- } else {\r
- $elementortype = 'type';\r
- }\r
- $xml .= "\n" . ' <part name="' . $partName . '" ' . $elementortype . '="' . $typePrefix . ':' . $localPart . '" />';\r
- }\r
- }\r
- $xml .= '</message>';\r
- } \r
- } \r
- // bindings & porttypes\r
- if (count($this->bindings) >= 1) {\r
- $binding_xml = '';\r
- $portType_xml = '';\r
- foreach($this->bindings as $bindingName => $attrs) {\r
- $binding_xml .= "\n<binding name=\"" . $bindingName . '" type="tns:' . $attrs['portType'] . '">';\r
- $binding_xml .= "\n" . ' <soap:binding style="' . $attrs['style'] . '" transport="' . $attrs['transport'] . '"/>';\r
- $portType_xml .= "\n<portType name=\"" . $attrs['portType'] . '">';\r
- foreach($attrs['operations'] as $opName => $opParts) {\r
- $binding_xml .= "\n" . ' <operation name="' . $opName . '">';\r
- $binding_xml .= "\n" . ' <soap:operation soapAction="' . $opParts['soapAction'] . '" style="'. $opParts['style'] . '"/>';\r
- if (isset($opParts['input']['encodingStyle']) && $opParts['input']['encodingStyle'] != '') {\r
- $enc_style = ' encodingStyle="' . $opParts['input']['encodingStyle'] . '"';\r
- } else {\r
- $enc_style = '';\r
- }\r
- $binding_xml .= "\n" . ' <input><soap:body use="' . $opParts['input']['use'] . '" namespace="' . $opParts['input']['namespace'] . '"' . $enc_style . '/></input>';\r
- if (isset($opParts['output']['encodingStyle']) && $opParts['output']['encodingStyle'] != '') {\r
- $enc_style = ' encodingStyle="' . $opParts['output']['encodingStyle'] . '"';\r
- } else {\r
- $enc_style = '';\r
- }\r
- $binding_xml .= "\n" . ' <output><soap:body use="' . $opParts['output']['use'] . '" namespace="' . $opParts['output']['namespace'] . '"' . $enc_style . '/></output>';\r
- $binding_xml .= "\n" . ' </operation>';\r
- $portType_xml .= "\n" . ' <operation name="' . $opParts['name'] . '"';\r
- if (isset($opParts['parameterOrder'])) {\r
- $portType_xml .= ' parameterOrder="' . $opParts['parameterOrder'] . '"';\r
- } \r
- $portType_xml .= '>';\r
- if(isset($opParts['documentation']) && $opParts['documentation'] != '') {\r
- $portType_xml .= "\n" . ' <documentation>' . htmlspecialchars($opParts['documentation']) . '</documentation>';\r
- }\r
- $portType_xml .= "\n" . ' <input message="tns:' . $opParts['input']['message'] . '"/>';\r
- $portType_xml .= "\n" . ' <output message="tns:' . $opParts['output']['message'] . '"/>';\r
- $portType_xml .= "\n" . ' </operation>';\r
- } \r
- $portType_xml .= "\n" . '</portType>';\r
- $binding_xml .= "\n" . '</binding>';\r
- } \r
- $xml .= $portType_xml . $binding_xml;\r
- } \r
- // services\r
- $xml .= "\n<service name=\"" . $this->serviceName . '">';\r
- if (count($this->ports) >= 1) {\r
- foreach($this->ports as $pName => $attrs) {\r
- $xml .= "\n" . ' <port name="' . $pName . '" binding="tns:' . $attrs['binding'] . '">';\r
- $xml .= "\n" . ' <soap:address location="' . $attrs['location'] . ($debug ? '?debug=1' : '') . '"/>';\r
- $xml .= "\n" . ' </port>';\r
- } \r
- } \r
- $xml .= "\n" . '</service>';\r
- return $xml . "\n</definitions>";\r
- } \r
-\r
- /**\r
- * determine whether a set of parameters are unwrapped\r
- * when they are expect to be wrapped, Microsoft-style.\r
- *\r
- * @param string $type the type (element name) of the wrapper\r
- * @param array $parameters the parameter values for the SOAP call\r
- * @return boolean whether they parameters are unwrapped (and should be wrapped)\r
- * @access private\r
- */\r
- function parametersMatchWrapped($type, &$parameters) {\r
- $this->debug("in parametersMatchWrapped type=$type, parameters=");\r
- $this->appendDebug($this->varDump($parameters));\r
-\r
- // split type into namespace:unqualified-type\r
- if (strpos($type, ':')) {\r
- $uqType = substr($type, strrpos($type, ':') + 1);\r
- $ns = substr($type, 0, strrpos($type, ':'));\r
- $this->debug("in parametersMatchWrapped: got a prefixed type: $uqType, $ns");\r
- if ($this->getNamespaceFromPrefix($ns)) {\r
- $ns = $this->getNamespaceFromPrefix($ns);\r
- $this->debug("in parametersMatchWrapped: expanded prefixed type: $uqType, $ns");\r
- }\r
- } else {\r
- // TODO: should the type be compared to types in XSD, and the namespace\r
- // set to XSD if the type matches?\r
- $this->debug("in parametersMatchWrapped: No namespace for type $type");\r
- $ns = '';\r
- $uqType = $type;\r
- }\r
-\r
- // get the type information\r
- if (!$typeDef = $this->getTypeDef($uqType, $ns)) {\r
- $this->debug("in parametersMatchWrapped: $type ($uqType) is not a supported type.");\r
- return false;\r
- }\r
- $this->debug("in parametersMatchWrapped: found typeDef=");\r
- $this->appendDebug($this->varDump($typeDef));\r
- if (substr($uqType, -1) == '^') {\r
- $uqType = substr($uqType, 0, -1);\r
- }\r
- $phpType = $typeDef['phpType'];\r
- $arrayType = (isset($typeDef['arrayType']) ? $typeDef['arrayType'] : '');\r
- $this->debug("in parametersMatchWrapped: uqType: $uqType, ns: $ns, phptype: $phpType, arrayType: $arrayType");\r
- \r
- // we expect a complexType or element of complexType\r
- if ($phpType != 'struct') {\r
- $this->debug("in parametersMatchWrapped: not a struct");\r
- return false;\r
- }\r
-\r
- // see whether the parameter names match the elements\r
- if (isset($typeDef['elements']) && is_array($typeDef['elements'])) {\r
- $elements = 0;\r
- $matches = 0;\r
- $change = false;\r
- if ($this->isArraySimpleOrStruct($parameters) == 'arraySimple' && count($parameters) == count($typeDef['elements'])) {\r
- $this->debug("in parametersMatchWrapped: (wrapped return value kludge) correct number of elements in simple array, so change array and wrap");\r
- $change = true;\r
- }\r
- foreach ($typeDef['elements'] as $name => $attrs) {\r
- if ($change) {\r
- $this->debug("in parametersMatchWrapped: change parameter $element to name $name");\r
- $parameters[$name] = $parameters[$elements];\r
- unset($parameters[$elements]);\r
- $matches++;\r
- } elseif (isset($parameters[$name])) {\r
- $this->debug("in parametersMatchWrapped: have parameter named $name");\r
- $matches++;\r
- } else {\r
- $this->debug("in parametersMatchWrapped: do not have parameter named $name");\r
- }\r
- $elements++;\r
- }\r
-\r
- $this->debug("in parametersMatchWrapped: $matches parameter names match $elements wrapped parameter names");\r
- if ($matches == 0) {\r
- return false;\r
- }\r
- return true;\r
- }\r
-\r
- // since there are no elements for the type, if the user passed no\r
- // parameters, the parameters match wrapped.\r
- $this->debug("in parametersMatchWrapped: no elements type $ns:$uqType");\r
- return count($parameters) == 0;\r
- }\r
-\r
- /**\r
- * serialize PHP values according to a WSDL message definition\r
- * contrary to the method name, this is not limited to RPC\r
- *\r
- * TODO\r
- * - multi-ref serialization\r
- * - validate PHP values against type definitions, return errors if invalid\r
- * \r
- * @param string $operation operation name\r
- * @param string $direction (input|output)\r
- * @param mixed $parameters parameter value(s)\r
- * @param string $bindingType (soap|soap12)\r
- * @return mixed parameters serialized as XML or false on error (e.g. operation not found)\r
- * @access public\r
- */\r
- function serializeRPCParameters($operation, $direction, $parameters, $bindingType = 'soap') {\r
- $this->debug("in serializeRPCParameters: operation=$operation, direction=$direction, XMLSchemaVersion=$this->XMLSchemaVersion, bindingType=$bindingType");\r
- \r
- //echo "in serializeRPCParameters: operation=$operation, direction=$direction, XMLSchemaVersion=$this->XMLSchemaVersion, bindingType=$bindingType"."<br/>";\r
- //print_r($parameters);\r
- //echo "<br/>";\r
- \r
- $this->appendDebug('parameters=' . $this->varDump($parameters));\r
- \r
- if ($direction != 'input' && $direction != 'output') {\r
- $this->debug('The value of the \$direction argument needs to be either "input" or "output"');\r
- $this->setError('The value of the \$direction argument needs to be either "input" or "output"');\r
- return false;\r
- } \r
- if (!$opData = $this->getOperationData($operation, $bindingType)) {\r
- $this->debug('Unable to retrieve WSDL data for operation: ' . $operation . ' bindingType: ' . $bindingType);\r
- $this->setError('Unable to retrieve WSDL data for operation: ' . $operation . ' bindingType: ' . $bindingType);\r
- return false;\r
- }\r
- $this->debug('in serializeRPCParameters: opData:');\r
- $this->appendDebug($this->varDump($opData));\r
-\r
- // Get encoding style for output and set to current\r
- $encodingStyle = 'http://schemas.xmlsoap.org/soap/encoding/';\r
- if(($direction == 'input') && isset($opData['output']['encodingStyle']) && ($opData['output']['encodingStyle'] != $encodingStyle)) {\r
- $encodingStyle = $opData['output']['encodingStyle'];\r
- $enc_style = $encodingStyle;\r
- }\r
-\r
- // set input params\r
- $xml = '';\r
- if (isset($opData[$direction]['parts']) && sizeof($opData[$direction]['parts']) > 0) {\r
- $parts = &$opData[$direction]['parts'];\r
- $part_count = sizeof($parts);\r
- $style = $opData['style'];\r
- $use = $opData[$direction]['use'];\r
- $this->debug("have $part_count part(s) to serialize using $style/$use");\r
- if (is_array($parameters)) {\r
- $parametersArrayType = $this->isArraySimpleOrStruct($parameters);\r
- $parameter_count = count($parameters);\r
- $this->debug("have $parameter_count parameter(s) provided as $parametersArrayType to serialize");\r
- // check for Microsoft-style wrapped parameters\r
- if ($style == 'document' && $use == 'literal' && $part_count == 1 && isset($parts['parameters'])) {\r
- $this->debug('check whether the caller has wrapped the parameters');\r
- if ((($parametersArrayType == 'arrayStruct' || $parameter_count == 0) && !isset($parameters['parameters'])) || ($direction == 'output' && $parametersArrayType == 'arraySimple' && $parameter_count == 1)) {\r
- $this->debug('check whether caller\'s parameters match the wrapped ones');\r
- if ($this->parametersMatchWrapped($parts['parameters'], $parameters)) {\r
- $this->debug('wrap the parameters for the caller');\r
- $parameters = array('parameters' => $parameters);\r
- $parameter_count = 1;\r
- }\r
- }\r
- }\r
- foreach ($parts as $name => $type) {\r
- //echo "serializing part $name of type $type"."<br/>";\r
- $this->debug("serializing part $name of type $type");\r
- // Track encoding style\r
- if (isset($opData[$direction]['encodingStyle']) && $encodingStyle != $opData[$direction]['encodingStyle']) {\r
- $encodingStyle = $opData[$direction]['encodingStyle']; \r
- $enc_style = $encodingStyle;\r
- } else {\r
- $enc_style = false;\r
- }\r
- // NOTE: add error handling here\r
- // if serializeType returns false, then catch global error and fault\r
- if ($parametersArrayType == 'arraySimple') {\r
- //echo "arraySimple<br/>";\r
- $p = array_shift($parameters);\r
- $this->debug('calling serializeType w/indexed param');\r
- $xml .= $this->serializeType($name, $type, $p, $use, $enc_style);\r
- } elseif (isset($parameters[$name])) {\r
- //echo "array SECOND<br/>";\r
- $this->debug('calling serializeType w/named param');\r
- //echo "PARAMS: ";\r
- //print_r ($parameters[$name]); \r
- //echo "<br/>";\r
- $xml .= $this->serializeType($name, $type, $parameters[$name], $use, $enc_style);\r
- } else {\r
- //echo "array THIRD<br/>";\r
- // TODO: only send nillable\r
- $this->debug('calling serializeType w/null param');\r
- //echo "PARAMS: ";\r
- //print_r ($parameters); \r
- //echo "<br/>";\r
- //For some reason this does not work!! I am heavily (!) thinking about WHY the params here\r
- //are passed as NULL?! What should be the resulting XML if you pass NULL as paramlist?!?!?\r
- //seba.wagner at gmail dot com 2008/05/12\r
- //$xml .= $this->serializeType($name, $type, null, $use, $enc_style);\r
- $xml .= $this->serializeLinuxAxis2Type($name, $type, $parameters, $use, $enc_style);\r
- }\r
- //echo "PART XML: ".htmlentities($xml)."<br/>";\r
- }\r
- } else {\r
- $this->debug('no parameters passed.');\r
- }\r
- }\r
- $this->debug("serializeRPCParameters returning: $xml");\r
- //echo "<br/>"."serializeRPCParameters returning: ".htmlentities($xml)."<BR/>";\r
- return $xml;\r
- } \r
- \r
- /**\r
- * serialize a PHP value according to a WSDL message definition\r
- * \r
- * TODO\r
- * - multi-ref serialization\r
- * - validate PHP values against type definitions, return errors if invalid\r
- * \r
- * @param string $operation operation name\r
- * @param string $direction (input|output)\r
- * @param mixed $parameters parameter value(s)\r
- * @return mixed parameters serialized as XML or false on error (e.g. operation not found)\r
- * @access public\r
- * @deprecated\r
- */\r
- function serializeParameters($operation, $direction, $parameters)\r
- {\r
- $this->debug("in serializeParameters: operation=$operation, direction=$direction, XMLSchemaVersion=$this->XMLSchemaVersion"); \r
- $this->appendDebug('parameters=' . $this->varDump($parameters));\r
- \r
- if ($direction != 'input' && $direction != 'output') {\r
- $this->debug('The value of the \$direction argument needs to be either "input" or "output"');\r
- $this->setError('The value of the \$direction argument needs to be either "input" or "output"');\r
- return false;\r
- } \r
- if (!$opData = $this->getOperationData($operation)) {\r
- $this->debug('Unable to retrieve WSDL data for operation: ' . $operation);\r
- $this->setError('Unable to retrieve WSDL data for operation: ' . $operation);\r
- return false;\r
- }\r
- $this->debug('opData:');\r
- $this->appendDebug($this->varDump($opData));\r
- \r
- // Get encoding style for output and set to current\r
- $encodingStyle = 'http://schemas.xmlsoap.org/soap/encoding/';\r
- if(($direction == 'input') && isset($opData['output']['encodingStyle']) && ($opData['output']['encodingStyle'] != $encodingStyle)) {\r
- $encodingStyle = $opData['output']['encodingStyle'];\r
- $enc_style = $encodingStyle;\r
- }\r
- \r
- // set input params\r
- $xml = '';\r
- if (isset($opData[$direction]['parts']) && sizeof($opData[$direction]['parts']) > 0) {\r
- \r
- $use = $opData[$direction]['use'];\r
- $this->debug("use=$use");\r
- $this->debug('got ' . count($opData[$direction]['parts']) . ' part(s)');\r
- if (is_array($parameters)) {\r
- $parametersArrayType = $this->isArraySimpleOrStruct($parameters);\r
- $this->debug('have ' . $parametersArrayType . ' parameters');\r
- foreach($opData[$direction]['parts'] as $name => $type) {\r
- $this->debug('serializing part "'.$name.'" of type "'.$type.'"');\r
- // Track encoding style\r
- if(isset($opData[$direction]['encodingStyle']) && $encodingStyle != $opData[$direction]['encodingStyle']) {\r
- $encodingStyle = $opData[$direction]['encodingStyle']; \r
- $enc_style = $encodingStyle;\r
- } else {\r
- $enc_style = false;\r
- }\r
- // NOTE: add error handling here\r
- // if serializeType returns false, then catch global error and fault\r
- if ($parametersArrayType == 'arraySimple') {\r
- $p = array_shift($parameters);\r
- $this->debug('calling serializeType w/indexed param');\r
- $xml .= $this->serializeType($name, $type, $p, $use, $enc_style);\r
- } elseif (isset($parameters[$name])) {\r
- $this->debug('calling serializeType w/named param');\r
- $xml .= $this->serializeType($name, $type, $parameters[$name], $use, $enc_style);\r
- } else {\r
- // TODO: only send nillable\r
- $this->debug('calling serializeType w/null param');\r
- $xml .= $this->serializeType($name, $type, null, $use, $enc_style);\r
- }\r
- }\r
- } else {\r
- $this->debug('no parameters passed.');\r
- }\r
- }\r
- $this->debug("serializeParameters returning: $xml");\r
- return $xml;\r
- } \r
- \r
- function serializeLinuxAxis2Type($name, $type, $params, $use='encoded', $encodingStyle=false, $unqualified=false)\r
- {\r
- $xml = '';\r
- if (strpos($type, ':')) {\r
- $uqType = substr($type, strrpos($type, ':') + 1);\r
- $ns = substr($type, 0, strrpos($type, ':'));\r
- $this->debug("in serializeType: got a prefixed type: $uqType, $ns");\r
- if ($this->getNamespaceFromPrefix($ns)) {\r
- $ns = $this->getNamespaceFromPrefix($ns);\r
- $this->debug("in serializeType: expanded prefixed type: $uqType, $ns");\r
- }\r
-\r
- //echo "NameSpace: ".$ns."<br/>";\r
- //echo "Method: ".$uqType."<br/>";\r
- $methodName = substr($uqType,0,strlen($uqType)-1);\r
- \r
- //echo "Method: ".$methodName."<br/>";\r
- \r
- $xml .= '<'.$methodName.' xmlns="'.$ns.'">';\r
- \r
- foreach ($params as $key => $val){\r
- //echo "Key".$key." Value".$val."<br/>";\r
- \r
- $insertVal = $val;\r
- \r
- //If Boolean rewrite the Value\r
- if (is_bool($val)){\r
- if ($val) {\r
- $insertVal = "true";\r
- } else {\r
- $insertVal = "false";\r
- }\r
- }\r
- $xml .= '<'.$key.'>'.$insertVal.'</'.$key.'>';\r
- }\r
- \r
- $xml .= '</'.$methodName.'>';\r
- \r
- //echo htmlentities($xml)."<br/>";\r
- return $xml;\r
- //<loginUser xmlns="http://services.axis.openmeetings.org">\r
- }\r
- \r
- }\r
- /**\r
- * serializes a PHP value according a given type definition\r
- * \r
- * @param string $name name of value (part or element)\r
- * @param string $type XML schema type of value (type or element)\r
- * @param mixed $value a native PHP value (parameter value)\r
- * @param string $use use for part (encoded|literal)\r
- * @param string $encodingStyle SOAP encoding style for the value (if different than the enclosing style)\r
- * @param boolean $unqualified a kludge for what should be XML namespace form handling\r
- * @return string value serialized as an XML string\r
- * @access private\r
- */\r
- function serializeType($name, $type, $value, $use='encoded', $encodingStyle=false, $unqualified=false)\r
- {\r
- $this->debug("in serializeType: name=$name, type=$type, use=$use, encodingStyle=$encodingStyle, unqualified=" . ($unqualified ? "unqualified" : "qualified"));\r
- //echo "in serializeType: name=$name, type=$type, use=$use, encodingStyle=$encodingStyle, unqualified=" . ($unqualified ? "unqualified" : "qualified")."<br/>";\r
- \r
- //echo "SerialieType: ".$type."<br/>";\r
- \r
- $this->appendDebug("value=" . $this->varDump($value));\r
- if($use == 'encoded' && $encodingStyle) {\r
- $encodingStyle = ' SOAP-ENV:encodingStyle="' . $encodingStyle . '"';\r
- }\r
-\r
- // if a soapval has been supplied, let its type override the WSDL\r
- if (is_object($value) && get_class($value) == 'soapval') {\r
- ////echo "IS OBJECT "."<br/>";\r
- if ($value->type_ns) {\r
- $type = $value->type_ns . ':' . $value->type;\r
- $forceType = true;\r
- $this->debug("in serializeType: soapval overrides type to $type");\r
- } elseif ($value->type) {\r
- $type = $value->type;\r
- $forceType = true;\r
- $this->debug("in serializeType: soapval overrides type to $type");\r
- } else {\r
- $forceType = false;\r
- $this->debug("in serializeType: soapval does not override type");\r
- }\r
- $attrs = $value->attributes;\r
- $value = $value->value;\r
- $this->debug("in serializeType: soapval overrides value to $value");\r
- if ($attrs) {\r
- if (!is_array($value)) {\r
- $value['!'] = $value;\r
- }\r
- foreach ($attrs as $n => $v) {\r
- $value['!' . $n] = $v;\r
- }\r
- $this->debug("in serializeType: soapval provides attributes");\r
- }\r
- } else {\r
- $forceType = false;\r
- }\r
-\r
- $xml = '';\r
- if (strpos($type, ':')) {\r
- $uqType = substr($type, strrpos($type, ':') + 1);\r
- \r
- //echo "FIRST ### uqType: ".$uqType."<br/>";\r
- \r
- $ns = substr($type, 0, strrpos($type, ':'));\r
- $this->debug("in serializeType: got a prefixed type: $uqType, $ns");\r
- if ($this->getNamespaceFromPrefix($ns)) {\r
- $ns = $this->getNamespaceFromPrefix($ns);\r
- $this->debug("in serializeType: expanded prefixed type: $uqType, $ns");\r
- }\r
-\r
- //echo "NameSpace: ".$ns."<br/>";\r
- if($ns == $this->XMLSchemaVersion || $ns == 'http://schemas.xmlsoap.org/soap/encoding/'){\r
- $this->debug('in serializeType: type namespace indicates XML Schema or SOAP Encoding type');\r
- if ($unqualified && $use == 'literal') {\r
- $elementNS = " xmlns=\"\"";\r
- } else {\r
- $elementNS = '';\r
- }\r
- if (is_null($value)) {\r
- if ($use == 'literal') {\r
- // TODO: depends on minOccurs\r
- $xml = "<$name$elementNS/>";\r
- } else {\r
- // TODO: depends on nillable, which should be checked before calling this method\r
- $xml = "<$name$elementNS xsi:nil=\"true\" xsi:type=\"" . $this->getPrefixFromNamespace($ns) . ":$uqType\"/>";\r
- }\r
- $this->debug("in serializeType: returning: $xml");\r
- return $xml;\r
- }\r
- //echo "uqType: ".$uqType."<br/>";\r
- if ($uqType == 'Array') {\r
- // JBoss/Axis does this sometimes\r
- return $this->serialize_val($value, $name, false, false, false, false, $use);\r
- }\r
- if ($uqType == 'boolean') {\r
- if ((is_string($value) && $value == 'false') || (! $value)) {\r
- $value = 'false';\r
- } else {\r
- $value = 'true';\r
- }\r
- } \r
- if ($uqType == 'string' && gettype($value) == 'string') {\r
- $value = $this->expandEntities($value);\r
- }\r
- if (($uqType == 'long' || $uqType == 'unsignedLong') && gettype($value) == 'double') {\r
- $value = sprintf("%.0lf", $value);\r
- }\r
- // it's a scalar\r
- // TODO: what about null/nil values?\r
- // check type isn't a custom type extending xmlschema namespace\r
- if (!$this->getTypeDef($uqType, $ns)) {\r
- if ($use == 'literal') {\r
- if ($forceType) {\r
- $xml = "<$name$elementNS xsi:type=\"" . $this->getPrefixFromNamespace($ns) . ":$uqType\">$value</$name>";\r
- } else {\r
- $xml = "<$name$elementNS>$value</$name>";\r
- }\r
- } else {\r
- $xml = "<$name$elementNS xsi:type=\"" . $this->getPrefixFromNamespace($ns) . ":$uqType\"$encodingStyle>$value</$name>";\r
- }\r
- $this->debug("in serializeType: returning: $xml");\r
- return $xml;\r
- }\r
- $this->debug('custom type extends XML Schema or SOAP Encoding namespace (yuck)');\r
- } else if ($ns == 'http://xml.apache.org/xml-soap') {\r
- $this->debug('in serializeType: appears to be Apache SOAP type');\r
- if ($uqType == 'Map') {\r
- $tt_prefix = $this->getPrefixFromNamespace('http://xml.apache.org/xml-soap');\r
- if (! $tt_prefix) {\r
- $this->debug('in serializeType: Add namespace for Apache SOAP type');\r
- $tt_prefix = 'ns' . rand(1000, 9999);\r
- $this->namespaces[$tt_prefix] = 'http://xml.apache.org/xml-soap';\r
- // force this to be added to usedNamespaces\r
- $tt_prefix = $this->getPrefixFromNamespace('http://xml.apache.org/xml-soap');\r
- }\r
- $contents = '';\r
- foreach($value as $k => $v) {\r
- $this->debug("serializing map element: key $k, value $v");\r
- $contents .= '<item>';\r
- $contents .= $this->serialize_val($k,'key',false,false,false,false,$use);\r
- $contents .= $this->serialize_val($v,'value',false,false,false,false,$use);\r
- $contents .= '</item>';\r
- }\r
- if ($use == 'literal') {\r
- if ($forceType) {\r
- $xml = "<$name xsi:type=\"" . $tt_prefix . ":$uqType\">$contents</$name>";\r
- } else {\r
- $xml = "<$name>$contents</$name>";\r
- }\r
- } else {\r
- $xml = "<$name xsi:type=\"" . $tt_prefix . ":$uqType\"$encodingStyle>$contents</$name>";\r
- }\r
- $this->debug("in serializeType: returning: $xml");\r
- return $xml;\r
- }\r
- $this->debug('in serializeType: Apache SOAP type, but only support Map');\r
- }\r
- } else {\r
- // TODO: should the type be compared to types in XSD, and the namespace\r
- // set to XSD if the type matches?\r
- $this->debug("in serializeType: No namespace for type $type");\r
- $ns = '';\r
- $uqType = $type;\r
- }\r
- if(!$typeDef = $this->getTypeDef($uqType, $ns)){\r
- $this->setError("$type ($uqType) is not a supported type.");\r
- $this->debug("in serializeType: $type ($uqType) is not a supported type.");\r
- return false;\r
- } else {\r
- $this->debug("in serializeType: found typeDef");\r
- $this->appendDebug('typeDef=' . $this->varDump($typeDef));\r
- if (substr($uqType, -1) == '^') {\r
- $uqType = substr($uqType, 0, -1);\r
- }\r
- }\r
- $phpType = $typeDef['phpType'];\r
- $this->debug("in serializeType: uqType: $uqType, ns: $ns, phptype: $phpType, arrayType: " . (isset($typeDef['arrayType']) ? $typeDef['arrayType'] : '') ); \r
- // if php type == struct, map value to the <all> element names\r
- if ($phpType == 'struct') {\r
- if (isset($typeDef['typeClass']) && $typeDef['typeClass'] == 'element') {\r
- $elementName = $uqType;\r
- if (isset($typeDef['form']) && ($typeDef['form'] == 'qualified')) {\r
- $elementNS = " xmlns=\"$ns\"";\r
- } else {\r
- $elementNS = " xmlns=\"\"";\r
- }\r
- } else {\r
- $elementName = $name;\r
- if ($unqualified) {\r
- $elementNS = " xmlns=\"\"";\r
- } else {\r
- $elementNS = '';\r
- }\r
- }\r
- if (is_null($value)) {\r
- if ($use == 'literal') {\r
- // TODO: depends on minOccurs\r
- $xml = "<$elementName$elementNS/>";\r
- } else {\r
- $xml = "<$elementName$elementNS xsi:nil=\"true\" xsi:type=\"" . $this->getPrefixFromNamespace($ns) . ":$uqType\"/>";\r
- }\r
- $this->debug("in serializeType: returning: $xml");\r
- return $xml;\r
- }\r
- if (is_object($value)) {\r
- $value = get_object_vars($value);\r
- }\r
- if (is_array($value)) {\r
- $elementAttrs = $this->serializeComplexTypeAttributes($typeDef, $value, $ns, $uqType);\r
- if ($use == 'literal') {\r
- if ($forceType) {\r
- $xml = "<$elementName$elementNS$elementAttrs xsi:type=\"" . $this->getPrefixFromNamespace($ns) . ":$uqType\">";\r
- } else {\r
- $xml = "<$elementName$elementNS$elementAttrs>";\r
- }\r
- } else {\r
- $xml = "<$elementName$elementNS$elementAttrs xsi:type=\"" . $this->getPrefixFromNamespace($ns) . ":$uqType\"$encodingStyle>";\r
- }\r
- \r
- $xml .= $this->serializeComplexTypeElements($typeDef, $value, $ns, $uqType, $use, $encodingStyle);\r
- $xml .= "</$elementName>";\r
- } else {\r
- $this->debug("in serializeType: phpType is struct, but value is not an array");\r
- $this->setError("phpType is struct, but value is not an array: see debug output for details");\r
- $xml = '';\r
- }\r
- } elseif ($phpType == 'array') {\r
- if (isset($typeDef['form']) && ($typeDef['form'] == 'qualified')) {\r
- $elementNS = " xmlns=\"$ns\"";\r
- } else {\r
- if ($unqualified) {\r
- $elementNS = " xmlns=\"\"";\r
- } else {\r
- $elementNS = '';\r
- }\r
- }\r
- if (is_null($value)) {\r
- if ($use == 'literal') {\r
- // TODO: depends on minOccurs\r
- $xml = "<$name$elementNS/>";\r
- } else {\r
- $xml = "<$name$elementNS xsi:nil=\"true\" xsi:type=\"" .\r
- $this->getPrefixFromNamespace('http://schemas.xmlsoap.org/soap/encoding/') .\r
- ":Array\" " .\r
- $this->getPrefixFromNamespace('http://schemas.xmlsoap.org/soap/encoding/') .\r
- ':arrayType="' .\r
- $this->getPrefixFromNamespace($this->getPrefix($typeDef['arrayType'])) .\r
- ':' .\r
- $this->getLocalPart($typeDef['arrayType'])."[0]\"/>";\r
- }\r
- $this->debug("in serializeType: returning: $xml");\r
- return $xml;\r
- }\r
- if (isset($typeDef['multidimensional'])) {\r
- $nv = array();\r
- foreach($value as $v) {\r
- $cols = ',' . sizeof($v);\r
- $nv = array_merge($nv, $v);\r
- } \r
- $value = $nv;\r
- } else {\r
- $cols = '';\r
- } \r
- if (is_array($value) && sizeof($value) >= 1) {\r
- ////echo "IS ARRAY !! ".sizeof($value)."<br/>";\r
- $rows = sizeof($value);\r
- $contents = '';\r
- foreach($value as $k => $v) {\r
- \r
- ////echo $k." => ".$v."<br/>";\r
- \r
- $this->debug("serializing array element: $k, $v of type: $typeDef[arrayType]");\r
- //if (strpos($typeDef['arrayType'], ':') ) {\r
- if (!in_array($typeDef['arrayType'],$this->typemap['http://www.w3.org/2001/XMLSchema'])) {\r
- //echo "CALL AGAIN HEHRERERERER ########### <br/>";\r
- $contents .= $this->serializeType('item', $typeDef['arrayType'], $v, $use);\r
- } else {\r
- $contents .= $this->serialize_val($v, 'item', $typeDef['arrayType'], null, $this->XMLSchemaVersion, false, $use);\r
- } \r
- }\r
- } else {\r
- $rows = 0;\r
- $contents = null;\r
- }\r
- // TODO: for now, an empty value will be serialized as a zero element\r
- // array. Revisit this when coding the handling of null/nil values.\r
- if ($use == 'literal') {\r
- $xml = "<$name$elementNS>"\r
- .$contents\r
- ."</$name>";\r
- } else {\r
- $xml = "<$name$elementNS xsi:type=\"".$this->getPrefixFromNamespace('http://schemas.xmlsoap.org/soap/encoding/').':Array" '.\r
- $this->getPrefixFromNamespace('http://schemas.xmlsoap.org/soap/encoding/')\r
- .':arrayType="'\r
- .$this->getPrefixFromNamespace($this->getPrefix($typeDef['arrayType']))\r
- .":".$this->getLocalPart($typeDef['arrayType'])."[$rows$cols]\">"\r
- .$contents\r
- ."</$name>";\r
- }\r
- } elseif ($phpType == 'scalar') {\r
- if (isset($typeDef['form']) && ($typeDef['form'] == 'qualified')) {\r
- $elementNS = " xmlns=\"$ns\"";\r
- } else {\r
- if ($unqualified) {\r
- $elementNS = " xmlns=\"\"";\r
- } else {\r
- $elementNS = '';\r
- }\r
- }\r
- if ($use == 'literal') {\r
- if ($forceType) {\r
- $xml = "<$name$elementNS xsi:type=\"" . $this->getPrefixFromNamespace($ns) . ":$uqType\">$value</$name>";\r
- } else {\r
- $xml = "<$name$elementNS>$value</$name>";\r
- }\r
- } else {\r
- $xml = "<$name$elementNS xsi:type=\"" . $this->getPrefixFromNamespace($ns) . ":$uqType\"$encodingStyle>$value</$name>";\r
- }\r
- }\r
- $this->debug("in serializeType: returning: $xml");\r
- return $xml;\r
- }\r
- \r
- /**\r
- * serializes the attributes for a complexType\r
- *\r
- * @param array $typeDef our internal representation of an XML schema type (or element)\r
- * @param mixed $value a native PHP value (parameter value)\r
- * @param string $ns the namespace of the type\r
- * @param string $uqType the local part of the type\r
- * @return string value serialized as an XML string\r
- * @access private\r
- */\r
- function serializeComplexTypeAttributes($typeDef, $value, $ns, $uqType) {\r
- $xml = '';\r
- if (isset($typeDef['attrs']) && is_array($typeDef['attrs'])) {\r
- $this->debug("serialize attributes for XML Schema type $ns:$uqType");\r
- if (is_array($value)) {\r
- $xvalue = $value;\r
- } elseif (is_object($value)) {\r
- $xvalue = get_object_vars($value);\r
- } else {\r
- $this->debug("value is neither an array nor an object for XML Schema type $ns:$uqType");\r
- $xvalue = array();\r
- }\r
- foreach ($typeDef['attrs'] as $aName => $attrs) {\r
- if (isset($xvalue['!' . $aName])) {\r
- $xname = '!' . $aName;\r
- $this->debug("value provided for attribute $aName with key $xname");\r
- } elseif (isset($xvalue[$aName])) {\r
- $xname = $aName;\r
- $this->debug("value provided for attribute $aName with key $xname");\r
- } elseif (isset($attrs['default'])) {\r
- $xname = '!' . $aName;\r
- $xvalue[$xname] = $attrs['default'];\r
- $this->debug('use default value of ' . $xvalue[$aName] . ' for attribute ' . $aName);\r
- } else {\r
- $xname = '';\r
- $this->debug("no value provided for attribute $aName");\r
- }\r
- if ($xname) {\r
- $xml .= " $aName=\"" . $this->expandEntities($xvalue[$xname]) . "\"";\r
- }\r
- } \r
- } else {\r
- $this->debug("no attributes to serialize for XML Schema type $ns:$uqType");\r
- }\r
- if (isset($typeDef['extensionBase'])) {\r
- $ns = $this->getPrefix($typeDef['extensionBase']);\r
- $uqType = $this->getLocalPart($typeDef['extensionBase']);\r
- if ($this->getNamespaceFromPrefix($ns)) {\r
- $ns = $this->getNamespaceFromPrefix($ns);\r
- }\r
- if ($typeDef = $this->getTypeDef($uqType, $ns)) {\r
- $this->debug("serialize attributes for extension base $ns:$uqType");\r
- $xml .= $this->serializeComplexTypeAttributes($typeDef, $value, $ns, $uqType);\r
- } else {\r
- $this->debug("extension base $ns:$uqType is not a supported type");\r
- }\r
- }\r
- return $xml;\r
- }\r
-\r
- /**\r
- * serializes the elements for a complexType\r
- *\r
- * @param array $typeDef our internal representation of an XML schema type (or element)\r
- * @param mixed $value a native PHP value (parameter value)\r
- * @param string $ns the namespace of the type\r
- * @param string $uqType the local part of the type\r
- * @param string $use use for part (encoded|literal)\r
- * @param string $encodingStyle SOAP encoding style for the value (if different than the enclosing style)\r
- * @return string value serialized as an XML string\r
- * @access private\r
- */\r
- function serializeComplexTypeElements($typeDef, $value, $ns, $uqType, $use='encoded', $encodingStyle=false) {\r
- $xml = '';\r
- if (isset($typeDef['elements']) && is_array($typeDef['elements'])) {\r
- $this->debug("in serializeComplexTypeElements, serialize elements for XML Schema type $ns:$uqType");\r
- if (is_array($value)) {\r
- $xvalue = $value;\r
- } elseif (is_object($value)) {\r
- $xvalue = get_object_vars($value);\r
- } else {\r
- $this->debug("value is neither an array nor an object for XML Schema type $ns:$uqType");\r
- $xvalue = array();\r
- }\r
- // toggle whether all elements are present - ideally should validate against schema\r
- if (count($typeDef['elements']) != count($xvalue)){\r
- $optionals = true;\r
- }\r
- foreach ($typeDef['elements'] as $eName => $attrs) {\r
- if (!isset($xvalue[$eName])) {\r
- if (isset($attrs['default'])) {\r
- $xvalue[$eName] = $attrs['default'];\r
- $this->debug('use default value of ' . $xvalue[$eName] . ' for element ' . $eName);\r
- }\r
- }\r
- // if user took advantage of a minOccurs=0, then only serialize named parameters\r
- if (isset($optionals)\r
- && (!isset($xvalue[$eName])) \r
- && ( (!isset($attrs['nillable'])) || $attrs['nillable'] != 'true')\r
- ){\r
- if (isset($attrs['minOccurs']) && $attrs['minOccurs'] <> '0') {\r
- $this->debug("apparent error: no value provided for element $eName with minOccurs=" . $attrs['minOccurs']);\r
- }\r
- // do nothing\r
- $this->debug("no value provided for complexType element $eName and element is not nillable, so serialize nothing");\r
- } else {\r
- // get value\r
- if (isset($xvalue[$eName])) {\r
- $v = $xvalue[$eName];\r
- } else {\r
- $v = null;\r
- }\r
- if (isset($attrs['form'])) {\r
- $unqualified = ($attrs['form'] == 'unqualified');\r
- } else {\r
- $unqualified = false;\r
- }\r
- if (isset($attrs['maxOccurs']) && ($attrs['maxOccurs'] == 'unbounded' || $attrs['maxOccurs'] > 1) && isset($v) && is_array($v) && $this->isArraySimpleOrStruct($v) == 'arraySimple') {\r
- $vv = $v;\r
- foreach ($vv as $k => $v) {\r
- if (isset($attrs['type']) || isset($attrs['ref'])) {\r
- // serialize schema-defined type\r
- $xml .= $this->serializeType($eName, isset($attrs['type']) ? $attrs['type'] : $attrs['ref'], $v, $use, $encodingStyle, $unqualified);\r
- } else {\r
- // serialize generic type (can this ever really happen?)\r
- $this->debug("calling serialize_val() for $v, $eName, false, false, false, false, $use");\r
- $xml .= $this->serialize_val($v, $eName, false, false, false, false, $use);\r
- }\r
- }\r
- } else {\r
- if (isset($attrs['type']) || isset($attrs['ref'])) {\r
- // serialize schema-defined type\r
- $xml .= $this->serializeType($eName, isset($attrs['type']) ? $attrs['type'] : $attrs['ref'], $v, $use, $encodingStyle, $unqualified);\r
- } else {\r
- // serialize generic type (can this ever really happen?)\r
- $this->debug("calling serialize_val() for $v, $eName, false, false, false, false, $use");\r
- $xml .= $this->serialize_val($v, $eName, false, false, false, false, $use);\r
- }\r
- }\r
- }\r
- } \r
- } else {\r
- $this->debug("no elements to serialize for XML Schema type $ns:$uqType");\r
- }\r
- if (isset($typeDef['extensionBase'])) {\r
- $ns = $this->getPrefix($typeDef['extensionBase']);\r
- $uqType = $this->getLocalPart($typeDef['extensionBase']);\r
- if ($this->getNamespaceFromPrefix($ns)) {\r
- $ns = $this->getNamespaceFromPrefix($ns);\r
- }\r
- if ($typeDef = $this->getTypeDef($uqType, $ns)) {\r
- $this->debug("serialize elements for extension base $ns:$uqType");\r
- $xml .= $this->serializeComplexTypeElements($typeDef, $value, $ns, $uqType, $use, $encodingStyle);\r
- } else {\r
- $this->debug("extension base $ns:$uqType is not a supported type");\r
- }\r
- }\r
- return $xml;\r
- }\r
-\r
- /**\r
- * adds an XML Schema complex type to the WSDL types\r
- *\r
- * @param string $name\r
- * @param string $typeClass (complexType|simpleType|attribute)\r
- * @param string $phpType currently supported are array and struct (php assoc array)\r
- * @param string $compositor (all|sequence|choice)\r
- * @param string $restrictionBase namespace:name (http://schemas.xmlsoap.org/soap/encoding/:Array)\r
- * @param array $elements e.g. array ( name => array(name=>'',type=>'') )\r
- * @param array $attrs e.g. array(array('ref'=>'SOAP-ENC:arrayType','wsdl:arrayType'=>'xsd:string[]'))\r
- * @param string $arrayType as namespace:name (xsd:string)\r
- * @see nusoap_xmlschema\r
- * @access public\r
- */\r
- function addComplexType($name,$typeClass='complexType',$phpType='array',$compositor='',$restrictionBase='',$elements=array(),$attrs=array(),$arrayType='') {\r
- if (count($elements) > 0) {\r
- $eElements = array();\r
- foreach($elements as $n => $e){\r
- // expand each element\r
- $ee = array();\r
- foreach ($e as $k => $v) {\r
- $k = strpos($k,':') ? $this->expandQname($k) : $k;\r
- $v = strpos($v,':') ? $this->expandQname($v) : $v;\r
- $ee[$k] = $v;\r
- }\r
- $eElements[$n] = $ee;\r
- }\r
- $elements = $eElements;\r
- }\r
- \r
- if (count($attrs) > 0) {\r
- foreach($attrs as $n => $a){\r
- // expand each attribute\r
- foreach ($a as $k => $v) {\r
- $k = strpos($k,':') ? $this->expandQname($k) : $k;\r
- $v = strpos($v,':') ? $this->expandQname($v) : $v;\r
- $aa[$k] = $v;\r
- }\r
- $eAttrs[$n] = $aa;\r
- }\r
- $attrs = $eAttrs;\r
- }\r
-\r
- $restrictionBase = strpos($restrictionBase,':') ? $this->expandQname($restrictionBase) : $restrictionBase;\r
- $arrayType = strpos($arrayType,':') ? $this->expandQname($arrayType) : $arrayType;\r
-\r
- $typens = isset($this->namespaces['types']) ? $this->namespaces['types'] : $this->namespaces['tns'];\r
- $this->schemas[$typens][0]->addComplexType($name,$typeClass,$phpType,$compositor,$restrictionBase,$elements,$attrs,$arrayType);\r
- }\r
-\r
- /**\r
- * adds an XML Schema simple type to the WSDL types\r
- *\r
- * @param string $name\r
- * @param string $restrictionBase namespace:name (http://schemas.xmlsoap.org/soap/encoding/:Array)\r
- * @param string $typeClass (should always be simpleType)\r
- * @param string $phpType (should always be scalar)\r
- * @param array $enumeration array of values\r
- * @see nusoap_xmlschema\r
- * @access public\r
- */\r
- function addSimpleType($name, $restrictionBase='', $typeClass='simpleType', $phpType='scalar', $enumeration=array()) {\r
- $restrictionBase = strpos($restrictionBase,':') ? $this->expandQname($restrictionBase) : $restrictionBase;\r
-\r
- $typens = isset($this->namespaces['types']) ? $this->namespaces['types'] : $this->namespaces['tns'];\r
- $this->schemas[$typens][0]->addSimpleType($name, $restrictionBase, $typeClass, $phpType, $enumeration);\r
- }\r
-\r
- /**\r
- * adds an element to the WSDL types\r
- *\r
- * @param array $attrs attributes that must include name and type\r
- * @see nusoap_xmlschema\r
- * @access public\r
- */\r
- function addElement($attrs) {\r
- $typens = isset($this->namespaces['types']) ? $this->namespaces['types'] : $this->namespaces['tns'];\r
- $this->schemas[$typens][0]->addElement($attrs);\r
- }\r
-\r
- /**\r
- * register an operation with the server\r
- * \r
- * @param string $name operation (method) name\r
- * @param array $in assoc array of input values: key = param name, value = param type\r
- * @param array $out assoc array of output values: key = param name, value = param type\r
- * @param string $namespace optional The namespace for the operation\r
- * @param string $soapaction optional The soapaction for the operation\r
- * @param string $style (rpc|document) optional The style for the operation Note: when 'document' is specified, parameter and return wrappers are created for you automatically\r
- * @param string $use (encoded|literal) optional The use for the parameters (cannot mix right now)\r
- * @param string $documentation optional The description to include in the WSDL\r
- * @param string $encodingStyle optional (usually 'http://schemas.xmlsoap.org/soap/encoding/' for encoded)\r
- * @access public \r
- */\r
- function addOperation($name, $in = false, $out = false, $namespace = false, $soapaction = false, $style = 'rpc', $use = 'encoded', $documentation = '', $encodingStyle = ''){\r
- if ($use == 'encoded' && $encodingStyle == '') {\r
- $encodingStyle = 'http://schemas.xmlsoap.org/soap/encoding/';\r
- }\r
-\r
- if ($style == 'document') {\r
- $elements = array();\r
- foreach ($in as $n => $t) {\r
- $elements[$n] = array('name' => $n, 'type' => $t);\r
- }\r
- $this->addComplexType($name . 'RequestType', 'complexType', 'struct', 'all', '', $elements);\r
- $this->addElement(array('name' => $name, 'type' => $name . 'RequestType'));\r
- $in = array('parameters' => 'tns:' . $name . '^');\r
-\r
- $elements = array();\r
- foreach ($out as $n => $t) {\r
- $elements[$n] = array('name' => $n, 'type' => $t);\r
- }\r
- $this->addComplexType($name . 'ResponseType', 'complexType', 'struct', 'all', '', $elements);\r
- $this->addElement(array('name' => $name . 'Response', 'type' => $name . 'ResponseType', 'form' => 'qualified'));\r
- $out = array('parameters' => 'tns:' . $name . 'Response' . '^');\r
- }\r
-\r
- // get binding\r
- $this->bindings[ $this->serviceName . 'Binding' ]['operations'][$name] =\r
- array(\r
- 'name' => $name,\r
- 'binding' => $this->serviceName . 'Binding',\r
- 'endpoint' => $this->endpoint,\r
- 'soapAction' => $soapaction,\r
- 'style' => $style,\r
- 'input' => array(\r
- 'use' => $use,\r
- 'namespace' => $namespace,\r
- 'encodingStyle' => $encodingStyle,\r
- 'message' => $name . 'Request',\r
- 'parts' => $in),\r
- 'output' => array(\r
- 'use' => $use,\r
- 'namespace' => $namespace,\r
- 'encodingStyle' => $encodingStyle,\r
- 'message' => $name . 'Response',\r
- 'parts' => $out),\r
- 'namespace' => $namespace,\r
- 'transport' => 'http://schemas.xmlsoap.org/soap/http',\r
- 'documentation' => $documentation); \r
- // add portTypes\r
- // add messages\r
- if($in)\r
- {\r
- foreach($in as $pName => $pType)\r
- {\r
- if(strpos($pType,':')) {\r
- $pType = $this->getNamespaceFromPrefix($this->getPrefix($pType)).":".$this->getLocalPart($pType);\r
- }\r
- $this->messages[$name.'Request'][$pName] = $pType;\r
- }\r
- } else {\r
- $this->messages[$name.'Request']= '0';\r
- }\r
- if($out)\r
- {\r
- foreach($out as $pName => $pType)\r
- {\r
- if(strpos($pType,':')) {\r
- $pType = $this->getNamespaceFromPrefix($this->getPrefix($pType)).":".$this->getLocalPart($pType);\r
- }\r
- $this->messages[$name.'Response'][$pName] = $pType;\r
- }\r
- } else {\r
- $this->messages[$name.'Response']= '0';\r
- }\r
- return true;\r
- } \r
-}\r
-?><?php\r
-\r
-\r
-\r
-/**\r
-*\r
-* nusoap_parser class parses SOAP XML messages into native PHP values\r
-*\r
-* @author Dietrich Ayala <dietrich@ganx4.com>\r
-* @author Scott Nichol <snichol@users.sourceforge.net>\r
-* @version $Id: nusoap.php,v 1.114 2007/11/06 15:17:46 snichol Exp $\r
-* @access public\r
-*/\r
-class nusoap_parser extends nusoap_base {\r
-\r
- var $xml = '';\r
- var $xml_encoding = '';\r
- var $method = '';\r
- var $root_struct = '';\r
- var $root_struct_name = '';\r
- var $root_struct_namespace = '';\r
- var $root_header = '';\r
- var $document = ''; // incoming SOAP body (text)\r
- // determines where in the message we are (envelope,header,body,method)\r
- var $status = '';\r
- var $position = 0;\r
- var $depth = 0;\r
- var $default_namespace = '';\r
- var $namespaces = array();\r
- var $message = array();\r
- var $parent = '';\r
- var $fault = false;\r
- var $fault_code = '';\r
- var $fault_str = '';\r
- var $fault_detail = '';\r
- var $depth_array = array();\r
- var $debug_flag = true;\r
- var $soapresponse = NULL; // parsed SOAP Body\r
- var $soapheader = NULL; // parsed SOAP Header\r
- var $responseHeaders = ''; // incoming SOAP headers (text)\r
- var $body_position = 0;\r
- // for multiref parsing:\r
- // array of id => pos\r
- var $ids = array();\r
- // array of id => hrefs => pos\r
- var $multirefs = array();\r
- // toggle for auto-decoding element content\r
- var $decode_utf8 = true;\r
-\r
- /**\r
- * constructor that actually does the parsing\r
- *\r
- * @param string $xml SOAP message\r
- * @param string $encoding character encoding scheme of message\r
- * @param string $method method for which XML is parsed (unused?)\r
- * @param string $decode_utf8 whether to decode UTF-8 to ISO-8859-1\r
- * @access public\r
- */\r
- function nusoap_parser($xml,$encoding='UTF-8',$method='',$decode_utf8=true){\r
- parent::nusoap_base();\r
- $this->xml = $xml;\r
- $this->xml_encoding = $encoding;\r
- $this->method = $method;\r
- $this->decode_utf8 = $decode_utf8;\r
-\r
- // Check whether content has been read.\r
- if(!empty($xml)){\r
- // Check XML encoding\r
- $pos_xml = strpos($xml, '<?xml');\r
- if ($pos_xml !== FALSE) {\r
- $xml_decl = substr($xml, $pos_xml, strpos($xml, '?>', $pos_xml + 2) - $pos_xml + 1);\r
- if (preg_match("/encoding=[\"']([^\"']*)[\"']/", $xml_decl, $res)) {\r
- $xml_encoding = $res[1];\r
- if (strtoupper($xml_encoding) != $encoding) {\r
- $err = "Charset from HTTP Content-Type '" . $encoding . "' does not match encoding from XML declaration '" . $xml_encoding . "'";\r
- $this->debug($err);\r
- if ($encoding != 'ISO-8859-1' || strtoupper($xml_encoding) != 'UTF-8') {\r
- $this->setError($err);\r
- return;\r
- }\r
- // when HTTP says ISO-8859-1 (the default) and XML says UTF-8 (the typical), assume the other endpoint is just sloppy and proceed\r
- } else {\r
- $this->debug('Charset from HTTP Content-Type matches encoding from XML declaration');\r
- }\r
- } else {\r
- $this->debug('No encoding specified in XML declaration');\r
- }\r
- } else {\r
- $this->debug('No XML declaration');\r
- }\r
- $this->debug('Entering nusoap_parser(), length='.strlen($xml).', encoding='.$encoding);\r
- // Create an XML parser - why not xml_parser_create_ns?\r
- $this->parser = xml_parser_create($this->xml_encoding);\r
- // Set the options for parsing the XML data.\r
- //xml_parser_set_option($parser, XML_OPTION_SKIP_WHITE, 1);\r
- xml_parser_set_option($this->parser, XML_OPTION_CASE_FOLDING, 0);\r
- xml_parser_set_option($this->parser, XML_OPTION_TARGET_ENCODING, $this->xml_encoding);\r
- // Set the object for the parser.\r
- xml_set_object($this->parser, $this);\r
- // Set the element handlers for the parser.\r
- xml_set_element_handler($this->parser, 'start_element','end_element');\r
- xml_set_character_data_handler($this->parser,'character_data');\r
-\r
- // Parse the XML file.\r
- if(!xml_parse($this->parser,$xml,true)){\r
- // Display an error message.\r
- $err = sprintf('XML error parsing SOAP payload on line %d: %s',\r
- xml_get_current_line_number($this->parser),\r
- xml_error_string(xml_get_error_code($this->parser)));\r
- $this->debug($err);\r
- $this->debug("XML payload:\n" . $xml);\r
- $this->setError($err);\r
- } else {\r
- $this->debug('parsed successfully, found root struct: '.$this->root_struct.' of name '.$this->root_struct_name);\r
- // get final value\r
- $this->soapresponse = $this->message[$this->root_struct]['result'];\r
- // get header value\r
- if($this->root_header != '' && isset($this->message[$this->root_header]['result'])){\r
- $this->soapheader = $this->message[$this->root_header]['result'];\r
- }\r
- // resolve hrefs/ids\r
- if(sizeof($this->multirefs) > 0){\r
- foreach($this->multirefs as $id => $hrefs){\r
- $this->debug('resolving multirefs for id: '.$id);\r
- $idVal = $this->buildVal($this->ids[$id]);\r
- if (is_array($idVal) && isset($idVal['!id'])) {\r
- unset($idVal['!id']);\r
- }\r
- foreach($hrefs as $refPos => $ref){\r
- $this->debug('resolving href at pos '.$refPos);\r
- $this->multirefs[$id][$refPos] = $idVal;\r
- }\r
- }\r
- }\r
- }\r
- xml_parser_free($this->parser);\r
- } else {\r
- $this->debug('xml was empty, didn\'t parse!');\r
- $this->setError('xml was empty, didn\'t parse!');\r
- }\r
- }\r
-\r
- /**\r
- * start-element handler\r
- *\r
- * @param resource $parser XML parser object\r
- * @param string $name element name\r
- * @param array $attrs associative array of attributes\r
- * @access private\r
- */\r
- function start_element($parser, $name, $attrs) {\r
- // position in a total number of elements, starting from 0\r
- // update class level pos\r
- $pos = $this->position++;\r
- // and set mine\r
- $this->message[$pos] = array('pos' => $pos,'children'=>'','cdata'=>'');\r
- // depth = how many levels removed from root?\r
- // set mine as current global depth and increment global depth value\r
- $this->message[$pos]['depth'] = $this->depth++;\r
-\r
- // else add self as child to whoever the current parent is\r
- if($pos != 0){\r
- $this->message[$this->parent]['children'] .= '|'.$pos;\r
- }\r
- // set my parent\r
- $this->message[$pos]['parent'] = $this->parent;\r
- // set self as current parent\r
- $this->parent = $pos;\r
- // set self as current value for this depth\r
- $this->depth_array[$this->depth] = $pos;\r
- // get element prefix\r
- if(strpos($name,':')){\r
- // get ns prefix\r
- $prefix = substr($name,0,strpos($name,':'));\r
- // get unqualified name\r
- $name = substr(strstr($name,':'),1);\r
- }\r
- // set status\r
- if($name == 'Envelope'){\r
- $this->status = 'envelope';\r
- } elseif($name == 'Header' && $this->status = 'envelope'){\r
- $this->root_header = $pos;\r
- $this->status = 'header';\r
- } elseif($name == 'Body' && $this->status = 'envelope'){\r
- $this->status = 'body';\r
- $this->body_position = $pos;\r
- // set method\r
- } elseif($this->status == 'body' && $pos == ($this->body_position+1)){\r
- $this->status = 'method';\r
- $this->root_struct_name = $name;\r
- $this->root_struct = $pos;\r
- $this->message[$pos]['type'] = 'struct';\r
- $this->debug("found root struct $this->root_struct_name, pos $this->root_struct");\r
- }\r
- // set my status\r
- $this->message[$pos]['status'] = $this->status;\r
- // set name\r
- $this->message[$pos]['name'] = htmlspecialchars($name);\r
- // set attrs\r
- $this->message[$pos]['attrs'] = $attrs;\r
-\r
- // loop through atts, logging ns and type declarations\r
- $attstr = '';\r
- foreach($attrs as $key => $value){\r
- $key_prefix = $this->getPrefix($key);\r
- $key_localpart = $this->getLocalPart($key);\r
- // if ns declarations, add to class level array of valid namespaces\r
- if($key_prefix == 'xmlns'){\r
- if(ereg('^http://www.w3.org/[0-9]{4}/XMLSchema$',$value)){\r
- $this->XMLSchemaVersion = $value;\r
- $this->namespaces['xsd'] = $this->XMLSchemaVersion;\r
- $this->namespaces['xsi'] = $this->XMLSchemaVersion.'-instance';\r
- }\r
- $this->namespaces[$key_localpart] = $value;\r
- // set method namespace\r
- if($name == $this->root_struct_name){\r
- $this->methodNamespace = $value;\r
- }\r
- // if it's a type declaration, set type\r
- } elseif($key_localpart == 'type'){\r
- if (isset($this->message[$pos]['type']) && $this->message[$pos]['type'] == 'array') {\r
- // do nothing: already processed arrayType\r
- } else {\r
- $value_prefix = $this->getPrefix($value);\r
- $value_localpart = $this->getLocalPart($value);\r
- $this->message[$pos]['type'] = $value_localpart;\r
- $this->message[$pos]['typePrefix'] = $value_prefix;\r
- if(isset($this->namespaces[$value_prefix])){\r
- $this->message[$pos]['type_namespace'] = $this->namespaces[$value_prefix];\r
- } else if(isset($attrs['xmlns:'.$value_prefix])) {\r
- $this->message[$pos]['type_namespace'] = $attrs['xmlns:'.$value_prefix];\r
- }\r
- // should do something here with the namespace of specified type?\r
- }\r
- } elseif($key_localpart == 'arrayType'){\r
- $this->message[$pos]['type'] = 'array';\r
- /* do arrayType ereg here\r
- [1] arrayTypeValue ::= atype asize\r
- [2] atype ::= QName rank*\r
- [3] rank ::= '[' (',')* ']'\r
- [4] asize ::= '[' length~ ']'\r
- [5] length ::= nextDimension* Digit+\r
- [6] nextDimension ::= Digit+ ','\r
- */\r
- $expr = '([A-Za-z0-9_]+):([A-Za-z]+[A-Za-z0-9_]+)\[([0-9]+),?([0-9]*)\]';\r
- if(ereg($expr,$value,$regs)){\r
- $this->message[$pos]['typePrefix'] = $regs[1];\r
- $this->message[$pos]['arrayTypePrefix'] = $regs[1];\r
- if (isset($this->namespaces[$regs[1]])) {\r
- $this->message[$pos]['arrayTypeNamespace'] = $this->namespaces[$regs[1]];\r
- } else if (isset($attrs['xmlns:'.$regs[1]])) {\r
- $this->message[$pos]['arrayTypeNamespace'] = $attrs['xmlns:'.$regs[1]];\r
- }\r
- $this->message[$pos]['arrayType'] = $regs[2];\r
- $this->message[$pos]['arraySize'] = $regs[3];\r
- $this->message[$pos]['arrayCols'] = $regs[4];\r
- }\r
- // specifies nil value (or not)\r
- } elseif ($key_localpart == 'nil'){\r
- $this->message[$pos]['nil'] = ($value == 'true' || $value == '1');\r
- // some other attribute\r
- } elseif ($key != 'href' && $key != 'xmlns' && $key_localpart != 'encodingStyle' && $key_localpart != 'root') {\r
- $this->message[$pos]['xattrs']['!' . $key] = $value;\r
- }\r
-\r
- if ($key == 'xmlns') {\r
- $this->default_namespace = $value;\r
- }\r
- // log id\r
- if($key == 'id'){\r
- $this->ids[$value] = $pos;\r
- }\r
- // root\r
- if($key_localpart == 'root' && $value == 1){\r
- $this->status = 'method';\r
- $this->root_struct_name = $name;\r
- $this->root_struct = $pos;\r
- $this->debug("found root struct $this->root_struct_name, pos $pos");\r
- }\r
- // for doclit\r
- $attstr .= " $key=\"$value\"";\r
- }\r
- // get namespace - must be done after namespace atts are processed\r
- if(isset($prefix)){\r
- $this->message[$pos]['namespace'] = $this->namespaces[$prefix];\r
- $this->default_namespace = $this->namespaces[$prefix];\r
- } else {\r
- $this->message[$pos]['namespace'] = $this->default_namespace;\r
- }\r
- if($this->status == 'header'){\r
- if ($this->root_header != $pos) {\r
- $this->responseHeaders .= "<" . (isset($prefix) ? $prefix . ':' : '') . "$name$attstr>";\r
- }\r
- } elseif($this->root_struct_name != ''){\r
- $this->document .= "<" . (isset($prefix) ? $prefix . ':' : '') . "$name$attstr>";\r
- }\r
- }\r
-\r
- /**\r
- * end-element handler\r
- *\r
- * @param resource $parser XML parser object\r
- * @param string $name element name\r
- * @access private\r
- */\r
- function end_element($parser, $name) {\r
- // position of current element is equal to the last value left in depth_array for my depth\r
- $pos = $this->depth_array[$this->depth--];\r
-\r
- // get element prefix\r
- if(strpos($name,':')){\r
- // get ns prefix\r
- $prefix = substr($name,0,strpos($name,':'));\r
- // get unqualified name\r
- $name = substr(strstr($name,':'),1);\r
- }\r
- \r
- // build to native type\r
- if(isset($this->body_position) && $pos > $this->body_position){\r
- // deal w/ multirefs\r
- if(isset($this->message[$pos]['attrs']['href'])){\r
- // get id\r
- $id = substr($this->message[$pos]['attrs']['href'],1);\r
- // add placeholder to href array\r
- $this->multirefs[$id][$pos] = 'placeholder';\r
- // add set a reference to it as the result value\r
- $this->message[$pos]['result'] =& $this->multirefs[$id][$pos];\r
- // build complexType values\r
- } elseif($this->message[$pos]['children'] != ''){\r
- // if result has already been generated (struct/array)\r
- if(!isset($this->message[$pos]['result'])){\r
- $this->message[$pos]['result'] = $this->buildVal($pos);\r
- }\r
- // build complexType values of attributes and possibly simpleContent\r
- } elseif (isset($this->message[$pos]['xattrs'])) {\r
- if (isset($this->message[$pos]['nil']) && $this->message[$pos]['nil']) {\r
- $this->message[$pos]['xattrs']['!'] = null;\r
- } elseif (isset($this->message[$pos]['cdata']) && trim($this->message[$pos]['cdata']) != '') {\r
- if (isset($this->message[$pos]['type'])) {\r
- $this->message[$pos]['xattrs']['!'] = $this->decodeSimple($this->message[$pos]['cdata'], $this->message[$pos]['type'], isset($this->message[$pos]['type_namespace']) ? $this->message[$pos]['type_namespace'] : '');\r
- } else {\r
- $parent = $this->message[$pos]['parent'];\r
- if (isset($this->message[$parent]['type']) && ($this->message[$parent]['type'] == 'array') && isset($this->message[$parent]['arrayType'])) {\r
- $this->message[$pos]['xattrs']['!'] = $this->decodeSimple($this->message[$pos]['cdata'], $this->message[$parent]['arrayType'], isset($this->message[$parent]['arrayTypeNamespace']) ? $this->message[$parent]['arrayTypeNamespace'] : '');\r
- } else {\r
- $this->message[$pos]['xattrs']['!'] = $this->message[$pos]['cdata'];\r
- }\r
- }\r
- }\r
- $this->message[$pos]['result'] = $this->message[$pos]['xattrs'];\r
- // set value of simpleType (or nil complexType)\r
- } else {\r
- //$this->debug('adding data for scalar value '.$this->message[$pos]['name'].' of value '.$this->message[$pos]['cdata']);\r
- if (isset($this->message[$pos]['nil']) && $this->message[$pos]['nil']) {\r
- $this->message[$pos]['xattrs']['!'] = null;\r
- } elseif (isset($this->message[$pos]['type'])) {\r
- $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'] : '');\r
- } else {\r
- $parent = $this->message[$pos]['parent'];\r
- if (isset($this->message[$parent]['type']) && ($this->message[$parent]['type'] == 'array') && isset($this->message[$parent]['arrayType'])) {\r
- $this->message[$pos]['result'] = $this->decodeSimple($this->message[$pos]['cdata'], $this->message[$parent]['arrayType'], isset($this->message[$parent]['arrayTypeNamespace']) ? $this->message[$parent]['arrayTypeNamespace'] : '');\r
- } else {\r
- $this->message[$pos]['result'] = $this->message[$pos]['cdata'];\r
- }\r
- }\r
-\r
- /* add value to parent's result, if parent is struct/array\r
- $parent = $this->message[$pos]['parent'];\r
- if($this->message[$parent]['type'] != 'map'){\r
- if(strtolower($this->message[$parent]['type']) == 'array'){\r
- $this->message[$parent]['result'][] = $this->message[$pos]['result'];\r
- } else {\r
- $this->message[$parent]['result'][$this->message[$pos]['name']] = $this->message[$pos]['result'];\r
- }\r
- }\r
- */\r
- }\r
- }\r
- \r
- // for doclit\r
- if($this->status == 'header'){\r
- if ($this->root_header != $pos) {\r
- $this->responseHeaders .= "</" . (isset($prefix) ? $prefix . ':' : '') . "$name>";\r
- }\r
- } elseif($pos >= $this->root_struct){\r
- $this->document .= "</" . (isset($prefix) ? $prefix . ':' : '') . "$name>";\r
- }\r
- // switch status\r
- if($pos == $this->root_struct){\r
- $this->status = 'body';\r
- $this->root_struct_namespace = $this->message[$pos]['namespace'];\r
- } elseif($name == 'Body'){\r
- $this->status = 'envelope';\r
- } elseif($name == 'Header'){\r
- $this->status = 'envelope';\r
- } elseif($name == 'Envelope'){\r
- //\r
- }\r
- // set parent back to my parent\r
- $this->parent = $this->message[$pos]['parent'];\r
- }\r
-\r
- /**\r
- * element content handler\r
- *\r
- * @param resource $parser XML parser object\r
- * @param string $data element content\r
- * @access private\r
- */\r
- function character_data($parser, $data){\r
- $pos = $this->depth_array[$this->depth];\r
- if ($this->xml_encoding=='UTF-8'){\r
- // TODO: add an option to disable this for folks who want\r
- // raw UTF-8 that, e.g., might not map to iso-8859-1\r
- // TODO: this can also be handled with xml_parser_set_option($this->parser, XML_OPTION_TARGET_ENCODING, "ISO-8859-1");\r
- if($this->decode_utf8){\r
- $data = utf8_decode($data);\r
- }\r
- }\r
- $this->message[$pos]['cdata'] .= $data;\r
- // for doclit\r
- if($this->status == 'header'){\r
- $this->responseHeaders .= $data;\r
- } else {\r
- $this->document .= $data;\r
- }\r
- }\r
-\r
- /**\r
- * get the parsed message (SOAP Body)\r
- *\r
- * @return mixed\r
- * @access public\r
- * @deprecated use get_soapbody instead\r
- */\r
- function get_response(){\r
- return $this->soapresponse;\r
- }\r
-\r
- /**\r
- * get the parsed SOAP Body (NULL if there was none)\r
- *\r
- * @return mixed\r
- * @access public\r
- */\r
- function get_soapbody(){\r
- return $this->soapresponse;\r
- }\r
-\r
- /**\r
- * get the parsed SOAP Header (NULL if there was none)\r
- *\r
- * @return mixed\r
- * @access public\r
- */\r
- function get_soapheader(){\r
- return $this->soapheader;\r
- }\r
-\r
- /**\r
- * get the unparsed SOAP Header\r
- *\r
- * @return string XML or empty if no Header\r
- * @access public\r
- */\r
- function getHeaders(){\r
- return $this->responseHeaders;\r
- }\r
-\r
- /**\r
- * decodes simple types into PHP variables\r
- *\r
- * @param string $value value to decode\r
- * @param string $type XML type to decode\r
- * @param string $typens XML type namespace to decode\r
- * @return mixed PHP value\r
- * @access private\r
- */\r
- function decodeSimple($value, $type, $typens) {\r
- // TODO: use the namespace!\r
- if ((!isset($type)) || $type == 'string' || $type == 'long' || $type == 'unsignedLong') {\r
- return (string) $value;\r
- }\r
- if ($type == 'int' || $type == 'integer' || $type == 'short' || $type == 'byte') {\r
- return (int) $value;\r
- }\r
- if ($type == 'float' || $type == 'double' || $type == 'decimal') {\r
- return (double) $value;\r
- }\r
- if ($type == 'boolean') {\r
- if (strtolower($value) == 'false' || strtolower($value) == 'f') {\r
- return false;\r
- }\r
- return (boolean) $value;\r
- }\r
- if ($type == 'base64' || $type == 'base64Binary') {\r
- $this->debug('Decode base64 value');\r
- return base64_decode($value);\r
- }\r
- // obscure numeric types\r
- if ($type == 'nonPositiveInteger' || $type == 'negativeInteger'\r
- || $type == 'nonNegativeInteger' || $type == 'positiveInteger'\r
- || $type == 'unsignedInt'\r
- || $type == 'unsignedShort' || $type == 'unsignedByte') {\r
- return (int) $value;\r
- }\r
- // bogus: parser treats array with no elements as a simple type\r
- if ($type == 'array') {\r
- return array();\r
- }\r
- // everything else\r
- return (string) $value;\r
- }\r
-\r
- /**\r
- * builds response structures for compound values (arrays/structs)\r
- * and scalars\r
- *\r
- * @param integer $pos position in node tree\r
- * @return mixed PHP value\r
- * @access private\r
- */\r
- function buildVal($pos){\r
- if(!isset($this->message[$pos]['type'])){\r
- $this->message[$pos]['type'] = '';\r
- }\r
- $this->debug('in buildVal() for '.$this->message[$pos]['name']."(pos $pos) of type ".$this->message[$pos]['type']);\r
- // if there are children...\r
- if($this->message[$pos]['children'] != ''){\r
- $this->debug('in buildVal, there are children');\r
- $children = explode('|',$this->message[$pos]['children']);\r
- array_shift($children); // knock off empty\r
- // md array\r
- if(isset($this->message[$pos]['arrayCols']) && $this->message[$pos]['arrayCols'] != ''){\r
- $r=0; // rowcount\r
- $c=0; // colcount\r
- foreach($children as $child_pos){\r
- $this->debug("in buildVal, got an MD array element: $r, $c");\r
- $params[$r][] = $this->message[$child_pos]['result'];\r
- $c++;\r
- if($c == $this->message[$pos]['arrayCols']){\r
- $c = 0;\r
- $r++;\r
- }\r
- }\r
- // array\r
- } elseif($this->message[$pos]['type'] == 'array' || $this->message[$pos]['type'] == 'Array'){\r
- $this->debug('in buildVal, adding array '.$this->message[$pos]['name']);\r
- foreach($children as $child_pos){\r
- $params[] = &$this->message[$child_pos]['result'];\r
- }\r
- // apache Map type: java hashtable\r
- } elseif($this->message[$pos]['type'] == 'Map' && $this->message[$pos]['type_namespace'] == 'http://xml.apache.org/xml-soap'){\r
- $this->debug('in buildVal, Java Map '.$this->message[$pos]['name']);\r
- foreach($children as $child_pos){\r
- $kv = explode("|",$this->message[$child_pos]['children']);\r
- $params[$this->message[$kv[1]]['result']] = &$this->message[$kv[2]]['result'];\r
- }\r
- // generic compound type\r
- //} elseif($this->message[$pos]['type'] == 'SOAPStruct' || $this->message[$pos]['type'] == 'struct') {\r
- } else {\r
- // Apache Vector type: treat as an array\r
- $this->debug('in buildVal, adding Java Vector or generic compound type '.$this->message[$pos]['name']);\r
- if ($this->message[$pos]['type'] == 'Vector' && $this->message[$pos]['type_namespace'] == 'http://xml.apache.org/xml-soap') {\r
- $notstruct = 1;\r
- } else {\r
- $notstruct = 0;\r
- }\r
- //\r
- foreach($children as $child_pos){\r
- if($notstruct){\r
- $params[] = &$this->message[$child_pos]['result'];\r
- } else {\r
- if (isset($params[$this->message[$child_pos]['name']])) {\r
- // de-serialize repeated element name into an array\r
- if ((!is_array($params[$this->message[$child_pos]['name']])) || (!isset($params[$this->message[$child_pos]['name']][0]))) {\r
- $params[$this->message[$child_pos]['name']] = array($params[$this->message[$child_pos]['name']]);\r
- }\r
- $params[$this->message[$child_pos]['name']][] = &$this->message[$child_pos]['result'];\r
- } else {\r
- $params[$this->message[$child_pos]['name']] = &$this->message[$child_pos]['result'];\r
- }\r
- }\r
- }\r
- }\r
- if (isset($this->message[$pos]['xattrs'])) {\r
- $this->debug('in buildVal, handling attributes');\r
- foreach ($this->message[$pos]['xattrs'] as $n => $v) {\r
- $params[$n] = $v;\r
- }\r
- }\r
- // handle simpleContent\r
- if (isset($this->message[$pos]['cdata']) && trim($this->message[$pos]['cdata']) != '') {\r
- $this->debug('in buildVal, handling simpleContent');\r
- if (isset($this->message[$pos]['type'])) {\r
- $params['!'] = $this->decodeSimple($this->message[$pos]['cdata'], $this->message[$pos]['type'], isset($this->message[$pos]['type_namespace']) ? $this->message[$pos]['type_namespace'] : '');\r
- } else {\r
- $parent = $this->message[$pos]['parent'];\r
- if (isset($this->message[$parent]['type']) && ($this->message[$parent]['type'] == 'array') && isset($this->message[$parent]['arrayType'])) {\r
- $params['!'] = $this->decodeSimple($this->message[$pos]['cdata'], $this->message[$parent]['arrayType'], isset($this->message[$parent]['arrayTypeNamespace']) ? $this->message[$parent]['arrayTypeNamespace'] : '');\r
- } else {\r
- $params['!'] = $this->message[$pos]['cdata'];\r
- }\r
- }\r
- }\r
- $ret = is_array($params) ? $params : array();\r
- $this->debug('in buildVal, return:');\r
- $this->appendDebug($this->varDump($ret));\r
- return $ret;\r
- } else {\r
- $this->debug('in buildVal, no children, building scalar');\r
- $cdata = isset($this->message[$pos]['cdata']) ? $this->message[$pos]['cdata'] : '';\r
- if (isset($this->message[$pos]['type'])) {\r
- $ret = $this->decodeSimple($cdata, $this->message[$pos]['type'], isset($this->message[$pos]['type_namespace']) ? $this->message[$pos]['type_namespace'] : '');\r
- $this->debug("in buildVal, return: $ret");\r
- return $ret;\r
- }\r
- $parent = $this->message[$pos]['parent'];\r
- if (isset($this->message[$parent]['type']) && ($this->message[$parent]['type'] == 'array') && isset($this->message[$parent]['arrayType'])) {\r
- $ret = $this->decodeSimple($cdata, $this->message[$parent]['arrayType'], isset($this->message[$parent]['arrayTypeNamespace']) ? $this->message[$parent]['arrayTypeNamespace'] : '');\r
- $this->debug("in buildVal, return: $ret");\r
- return $ret;\r
- }\r
- $ret = $this->message[$pos]['cdata'];\r
- $this->debug("in buildVal, return: $ret");\r
- return $ret;\r
- }\r
- }\r
-}\r
-\r
-/**\r
- * Backward compatibility\r
- */\r
-class soap_parser extends nusoap_parser {\r
-}\r
-\r
-?><?php\r
-\r
-\r
-\r
-/**\r
-*\r
-* [nu]soapclient higher level class for easy usage.\r
-*\r
-* usage:\r
-*\r
-* // instantiate client with server info\r
-* $soapclient = new nusoap_client( string path [ ,mixed wsdl] );\r
-*\r
-* // call method, get results\r
-* //echo $soapclient->call( string methodname [ ,array parameters] );\r
-*\r
-* // bye bye client\r
-* unset($soapclient);\r
-*\r
-* @author Dietrich Ayala <dietrich@ganx4.com>\r
-* @author Scott Nichol <snichol@users.sourceforge.net>\r
-* @version $Id: nusoap.php,v 1.114 2007/11/06 15:17:46 snichol Exp $\r
-* @access public\r
-*/\r
-class nusoap_client extends nusoap_base {\r
-\r
- var $username = ''; // Username for HTTP authentication\r
- var $password = ''; // Password for HTTP authentication\r
- var $authtype = ''; // Type of HTTP authentication\r
- var $certRequest = array(); // Certificate for HTTP SSL authentication\r
- var $requestHeaders = false; // SOAP headers in request (text)\r
- var $responseHeaders = ''; // SOAP headers from response (incomplete namespace resolution) (text)\r
- var $responseHeader = NULL; // SOAP Header from response (parsed)\r
- var $document = ''; // SOAP body response portion (incomplete namespace resolution) (text)\r
- var $endpoint;\r
- var $forceEndpoint = ''; // overrides WSDL endpoint\r
- var $proxyhost = '';\r
- var $proxyport = '';\r
- var $proxyusername = '';\r
- var $proxypassword = '';\r
- var $xml_encoding = ''; // character set encoding of incoming (response) messages\r
- var $http_encoding = false;\r
- var $timeout = 0; // HTTP connection timeout\r
- var $response_timeout = 30; // HTTP response timeout\r
- var $endpointType = ''; // soap|wsdl, empty for WSDL initialization error\r
- var $persistentConnection = false;\r
- var $defaultRpcParams = false; // This is no longer used\r
- var $request = ''; // HTTP request\r
- var $response = ''; // HTTP response\r
- var $responseData = ''; // SOAP payload of response\r
- var $cookies = array(); // Cookies from response or for request\r
- var $decode_utf8 = true; // toggles whether the parser decodes element content w/ utf8_decode()\r
- var $operations = array(); // WSDL operations, empty for WSDL initialization error\r
- var $curl_options = array(); // User-specified cURL options\r
- var $bindingType = ''; // WSDL operation binding type\r
- var $use_curl = false; // whether to always try to use cURL\r
-\r
- /*\r
- * fault related variables\r
- */\r
- /**\r
- * @var fault\r
- * @access public\r
- */\r
- var $fault;\r
- /**\r
- * @var faultcode\r
- * @access public\r
- */\r
- var $faultcode;\r
- /**\r
- * @var faultstring\r
- * @access public\r
- */\r
- var $faultstring;\r
- /**\r
- * @var faultdetail\r
- * @access public\r
- */\r
- var $faultdetail;\r
-\r
- /**\r
- * constructor\r
- *\r
- * @param mixed $endpoint SOAP server or WSDL URL (string), or wsdl instance (object)\r
- * @param bool $wsdl optional, set to true if using WSDL\r
- * @param int $portName optional portName in WSDL document\r
- * @param string $proxyhost\r
- * @param string $proxyport\r
- * @param string $proxyusername\r
- * @param string $proxypassword\r
- * @param integer $timeout set the connection timeout\r
- * @param integer $response_timeout set the response timeout\r
- * @access public\r
- */\r
- function nusoap_client($endpoint,$wsdl = false,$proxyhost = false,$proxyport = false,$proxyusername = false, $proxypassword = false, $timeout = 0, $response_timeout = 30){\r
- parent::nusoap_base();\r
- $this->endpoint = $endpoint;\r
- $this->proxyhost = $proxyhost;\r
- $this->proxyport = $proxyport;\r
- $this->proxyusername = $proxyusername;\r
- $this->proxypassword = $proxypassword;\r
- $this->timeout = $timeout;\r
- $this->response_timeout = $response_timeout;\r
-\r
- $this->debug("ctor wsdl=$wsdl timeout=$timeout response_timeout=$response_timeout");\r
- $this->appendDebug('endpoint=' . $this->varDump($endpoint));\r
-\r
- // make values\r
- if($wsdl){\r
- if (is_object($endpoint) && (get_class($endpoint) == 'wsdl')) {\r
- $this->wsdl = $endpoint;\r
- $this->endpoint = $this->wsdl->wsdl;\r
- $this->wsdlFile = $this->endpoint;\r
- $this->debug('existing wsdl instance created from ' . $this->endpoint);\r
- $this->checkWSDL();\r
- } else {\r
- $this->wsdlFile = $this->endpoint;\r
- $this->wsdl = null;\r
- $this->debug('will use lazy evaluation of wsdl from ' . $this->endpoint);\r
- }\r
- $this->endpointType = 'wsdl';\r
- } else {\r
- $this->debug("instantiate SOAP with endpoint at $endpoint");\r
- $this->endpointType = 'soap';\r
- }\r
- }\r
-\r
- /**\r
- * calls method, returns PHP native type\r
- *\r
- * @param string $operation SOAP server URL or path\r
- * @param mixed $params An array, associative or simple, of the parameters\r
- * for the method call, or a string that is the XML\r
- * for the call. For rpc style, this call will\r
- * wrap the XML in a tag named after the method, as\r
- * well as the SOAP Envelope and Body. For document\r
- * style, this will only wrap with the Envelope and Body.\r
- * IMPORTANT: when using an array with document style,\r
- * in which case there\r
- * is really one parameter, the root of the fragment\r
- * used in the call, which encloses what programmers\r
- * normally think of parameters. A parameter array\r
- * *must* include the wrapper.\r
- * @param string $namespace optional method namespace (WSDL can override)\r
- * @param string $soapAction optional SOAPAction value (WSDL can override)\r
- * @param mixed $headers optional string of XML with SOAP header content, or array of soapval objects for SOAP headers, or associative array\r
- * @param boolean $rpcParams optional (no longer used)\r
- * @param string $style optional (rpc|document) the style to use when serializing parameters (WSDL can override)\r
- * @param string $use optional (encoded|literal) the use when serializing parameters (WSDL can override)\r
- * @return mixed response from SOAP call\r
- * @access public\r
- */\r
- function call($operation,$params=array(),$namespace='http://tempuri.org',$soapAction='',$headers=false,$rpcParams=null,$style='rpc',$use='encoded'){\r
- $this->operation = $operation;\r
- $this->fault = false;\r
- $this->setError('');\r
- $this->request = '';\r
- $this->response = '';\r
- $this->responseData = '';\r
- $this->faultstring = '';\r
- $this->faultcode = '';\r
- $this->opData = array();\r
- \r
- $this->debug("call: operation=$operation, namespace=$namespace, soapAction=$soapAction, rpcParams=$rpcParams, style=$style, use=$use, endpointType=$this->endpointType");\r
- $this->appendDebug('params=' . $this->varDump($params));\r
- $this->appendDebug('headers=' . $this->varDump($headers));\r
- if ($headers) {\r
- $this->requestHeaders = $headers;\r
- }\r
- if ($this->endpointType == 'wsdl' && is_null($this->wsdl)) {\r
- $this->loadWSDL();\r
- if ($this->getError())\r
- return false;\r
- }\r
- // serialize parameters\r
- if($this->endpointType == 'wsdl' && $opData = $this->getOperationData($operation)){\r
- // use WSDL for operation\r
- //echo "use WSDL for operation<br/>";\r
- $this->opData = $opData;\r
- $this->debug("found operation");\r
- $this->appendDebug('opData=' . $this->varDump($opData));\r
- if (isset($opData['soapAction'])) {\r
- $soapAction = $opData['soapAction'];\r
- }\r
- if (! $this->forceEndpoint) {\r
- $this->endpoint = $opData['endpoint'];\r
- } else {\r
- $this->endpoint = $this->forceEndpoint;\r
- }\r
- $namespace = isset($opData['input']['namespace']) ? $opData['input']['namespace'] : $namespace;\r
- $style = $opData['style'];\r
- $use = $opData['input']['use'];\r
- // add ns to ns array\r
- if($namespace != '' && !isset($this->wsdl->namespaces[$namespace])){\r
- $nsPrefix = 'ns' . rand(1000, 9999);\r
- $this->wsdl->namespaces[$nsPrefix] = $namespace;\r
- }\r
- $nsPrefix = $this->wsdl->getPrefixFromNamespace($namespace);\r
- // serialize payload\r
- if (is_string($params)) {\r
- $this->debug("serializing param string for WSDL operation $operation");\r
- $payload = $params;\r
- } elseif (is_array($params)) {\r
- $this->debug("serializing param array for WSDL operation $operation");\r
- $payload = $this->wsdl->serializeRPCParameters($operation,'input',$params,$this->bindingType);\r
- //echo "#####PAYLOAD 2 ####<br/>";\r
- //echo htmlentities($payload)."<br/>";\r
- //echo "#####PAYLOAD 2 ####<br/>";\r
- } else {\r
- $this->debug('params must be array or string');\r
- $this->setError('params must be array or string');\r
- return false;\r
- }\r
- $usedNamespaces = $this->wsdl->usedNamespaces;\r
- if (isset($opData['input']['encodingStyle'])) {\r
- $encodingStyle = $opData['input']['encodingStyle'];\r
- } else {\r
- $encodingStyle = '';\r
- }\r
- $this->appendDebug($this->wsdl->getDebug());\r
- $this->wsdl->clearDebug();\r
- if ($errstr = $this->wsdl->getError()) {\r
- $this->debug('got wsdl error: '.$errstr);\r
- $this->setError('wsdl error: '.$errstr);\r
- return false;\r
- }\r
- } elseif($this->endpointType == 'wsdl') {\r
- // operation not in WSDL\r
- $this->appendDebug($this->wsdl->getDebug());\r
- $this->wsdl->clearDebug();\r
- $this->setError( 'operation '.$operation.' not present.');\r
- $this->debug("operation '$operation' not present.");\r
- return false;\r
- } else {\r
- // no WSDL\r
- //$this->namespaces['ns1'] = $namespace;\r
- $nsPrefix = 'ns' . rand(1000, 9999);\r
- // serialize \r
- $payload = '';\r
- if (is_string($params)) {\r
- $this->debug("serializing param string for operation $operation");\r
- $payload = $params;\r
- } elseif (is_array($params)) {\r
- $this->debug("serializing param array for operation $operation");\r
- foreach($params as $k => $v){\r
- $payload .= $this->serialize_val($v,$k,false,false,false,false,$use);\r
- }\r
- } else {\r
- $this->debug('params must be array or string');\r
- $this->setError('params must be array or string');\r
- return false;\r
- }\r
- $usedNamespaces = array();\r
- if ($use == 'encoded') {\r
- $encodingStyle = 'http://schemas.xmlsoap.org/soap/encoding/';\r
- } else {\r
- $encodingStyle = '';\r
- }\r
- }\r
- //echo "#####PAYLOAD 1 ####<br/>";\r
- //echo htmlentities($payload)."<br/>";\r
- //echo "#####PAYLOAD 1 ####<br/>";\r
- // wrap RPC calls with method element\r
- if ($style == 'rpc') {\r
- if ($use == 'literal') {\r
- $this->debug("wrapping RPC request with literal method element");\r
- if ($namespace) {\r
- // http://www.ws-i.org/Profiles/BasicProfile-1.1-2004-08-24.html R2735 says rpc/literal accessor elements should not be in a namespace\r
- $payload = "<$nsPrefix:$operation xmlns:$nsPrefix=\"$namespace\">" .\r
- $payload .\r
- "</$nsPrefix:$operation>";\r
- } else {\r
- $payload = "<$operation>" . $payload . "</$operation>";\r
- }\r
- } else {\r
- $this->debug("wrapping RPC request with encoded method element");\r
- if ($namespace) {\r
- $payload = "<$nsPrefix:$operation xmlns:$nsPrefix=\"$namespace\">" .\r
- $payload .\r
- "</$nsPrefix:$operation>";\r
- } else {\r
- $payload = "<$operation>" .\r
- $payload .\r
- "</$operation>";\r
- }\r
- }\r
- }\r
- //echo "#####PAYLOAD####<br/>";\r
- //echo htmlentities($payload)."<br/>";\r
- //echo "#####PAYLOAD####<br/>";\r
- // serialize envelope\r
- $soapmsg = $this->serializeEnvelope($payload,$this->requestHeaders,$usedNamespaces,$style,$use,$encodingStyle);\r
- $this->debug("endpoint=$this->endpoint, soapAction=$soapAction, namespace=$namespace, style=$style, use=$use, encodingStyle=$encodingStyle");\r
- $this->debug('SOAP message length=' . strlen($soapmsg) . ' contents (max 1000 bytes)=' . substr($soapmsg, 0, 1000));\r
- // send\r
- $return = $this->send($this->getHTTPBody($soapmsg),$soapAction,$this->timeout,$this->response_timeout);\r
- if($errstr = $this->getError()){\r
- $this->debug('Error: '.$errstr);\r
- return false;\r
- } else {\r
- $this->return = $return;\r
- $this->debug('sent message successfully and got a(n) '.gettype($return));\r
- $this->appendDebug('return=' . $this->varDump($return));\r
- \r
- // fault?\r
- if(is_array($return) && isset($return['faultcode'])){\r
- $this->debug('got fault');\r
- $this->setError($return['faultcode'].': '.$return['faultstring']);\r
- $this->fault = true;\r
- foreach($return as $k => $v){\r
- $this->$k = $v;\r
- $this->debug("$k = $v<br>");\r
- }\r
- return $return;\r
- } elseif ($style == 'document') {\r
- // NOTE: if the response is defined to have multiple parts (i.e. unwrapped),\r
- // we are only going to return the first part here...sorry about that\r
- return $return;\r
- } else {\r
- // array of return values\r
- if(is_array($return)){\r
- // multiple 'out' parameters, which we return wrapped up\r
- // in the array\r
- if(sizeof($return) > 1){\r
- return $return;\r
- }\r
- // single 'out' parameter (normally the return value)\r
- $return = array_shift($return);\r
- $this->debug('return shifted value: ');\r
- $this->appendDebug($this->varDump($return));\r
- return $return;\r
- // nothing returned (ie, echoVoid)\r
- } else {\r
- return "";\r
- }\r
- }\r
- }\r
- }\r
-\r
- /**\r
- * check WSDL passed as an instance or pulled from an endpoint\r
- *\r
- * @access private\r
- */\r
- function checkWSDL() {\r
- $this->appendDebug($this->wsdl->getDebug());\r
- $this->wsdl->clearDebug();\r
- $this->debug('checkWSDL');\r
- // catch errors\r
- if ($errstr = $this->wsdl->getError()) {\r
- $this->debug('got wsdl error: '.$errstr);\r
- $this->setError('wsdl error: '.$errstr);\r
- } elseif ($this->operations = $this->wsdl->getOperations('soap')) {\r
- $this->bindingType = 'soap';\r
- $this->debug('got '.count($this->operations).' operations from wsdl '.$this->wsdlFile.' for binding type '.$this->bindingType);\r
- } elseif ($this->operations = $this->wsdl->getOperations('soap12')) {\r
- $this->bindingType = 'soap12';\r
- $this->debug('got '.count($this->operations).' operations from wsdl '.$this->wsdlFile.' for binding type '.$this->bindingType);\r
- $this->debug('**************** WARNING: SOAP 1.2 BINDING *****************');\r
- } else {\r
- $this->debug('getOperations returned false');\r
- $this->setError('no operations defined in the WSDL document!');\r
- }\r
- }\r
-\r
- /**\r
- * instantiate wsdl object and parse wsdl file\r
- *\r
- * @access public\r
- */\r
- function loadWSDL() {\r
- $this->debug('instantiating wsdl class with doc: '.$this->wsdlFile);\r
- $this->wsdl =& new wsdl('',$this->proxyhost,$this->proxyport,$this->proxyusername,$this->proxypassword,$this->timeout,$this->response_timeout,$this->curl_options,$this->use_curl);\r
- $this->wsdl->setCredentials($this->username, $this->password, $this->authtype, $this->certRequest);\r
- $this->wsdl->fetchWSDL($this->wsdlFile);\r
- $this->checkWSDL();\r
- }\r
-\r
- /**\r
- * get available data pertaining to an operation\r
- *\r
- * @param string $operation operation name\r
- * @return array array of data pertaining to the operation\r
- * @access public\r
- */\r
- function getOperationData($operation){\r
- if ($this->endpointType == 'wsdl' && is_null($this->wsdl)) {\r
- $this->loadWSDL();\r
- if ($this->getError())\r
- return false;\r
- }\r
- if(isset($this->operations[$operation])){\r
- return $this->operations[$operation];\r
- }\r
- $this->debug("No data for operation: $operation");\r
- }\r
-\r
- /**\r
- * send the SOAP message\r
- *\r
- * Note: if the operation has multiple return values\r
- * the return value of this method will be an array\r
- * of those values.\r
- *\r
- * @param string $msg a SOAPx4 soapmsg object\r
- * @param string $soapaction SOAPAction value\r
- * @param integer $timeout set connection timeout in seconds\r
- * @param integer $response_timeout set response timeout in seconds\r
- * @return mixed native PHP types.\r
- * @access private\r
- */\r
- function send($msg, $soapaction = '', $timeout=0, $response_timeout=30) {\r
- $this->checkCookies();\r
- // detect transport\r
- switch(true){\r
- // http(s)\r
- case ereg('^http',$this->endpoint):\r
- $this->debug('transporting via HTTP');\r
- if($this->persistentConnection == true && is_object($this->persistentConnection)){\r
- $http =& $this->persistentConnection;\r
- } else {\r
- $http = new soap_transport_http($this->endpoint, $this->curl_options, $this->use_curl);\r
- if ($this->persistentConnection) {\r
- $http->usePersistentConnection();\r
- }\r
- }\r
- $http->setContentType($this->getHTTPContentType(), $this->getHTTPContentTypeCharset());\r
- $http->setSOAPAction($soapaction);\r
- if($this->proxyhost && $this->proxyport){\r
- $http->setProxy($this->proxyhost,$this->proxyport,$this->proxyusername,$this->proxypassword);\r
- }\r
- if($this->authtype != '') {\r
- $http->setCredentials($this->username, $this->password, $this->authtype, array(), $this->certRequest);\r
- }\r
- if($this->http_encoding != ''){\r
- $http->setEncoding($this->http_encoding);\r
- }\r
- $this->debug('sending message, length='.strlen($msg));\r
- if(ereg('^http:',$this->endpoint)){\r
- //if(strpos($this->endpoint,'http:')){\r
- $this->responseData = $http->send($msg,$timeout,$response_timeout,$this->cookies);\r
- } elseif(ereg('^https',$this->endpoint)){\r
- //} elseif(strpos($this->endpoint,'https:')){\r
- //if(phpversion() == '4.3.0-dev'){\r
- //$response = $http->send($msg,$timeout,$response_timeout);\r
- //$this->request = $http->outgoing_payload;\r
- //$this->response = $http->incoming_payload;\r
- //} else\r
- $this->responseData = $http->sendHTTPS($msg,$timeout,$response_timeout,$this->cookies);\r
- } else {\r
- $this->setError('no http/s in endpoint url');\r
- }\r
- $this->request = $http->outgoing_payload;\r
- $this->response = $http->incoming_payload;\r
- $this->appendDebug($http->getDebug());\r
- $this->UpdateCookies($http->incoming_cookies);\r
-\r
- // save transport object if using persistent connections\r
- if ($this->persistentConnection) {\r
- $http->clearDebug();\r
- if (!is_object($this->persistentConnection)) {\r
- $this->persistentConnection = $http;\r
- }\r
- }\r
- \r
- if($err = $http->getError()){\r
- $this->setError('HTTP Error: '.$err);\r
- return false;\r
- } elseif($this->getError()){\r
- return false;\r
- } else {\r
- $this->debug('got response, length='. strlen($this->responseData).' type='.$http->incoming_headers['content-type']);\r
- return $this->parseResponse($http->incoming_headers, $this->responseData);\r
- }\r
- break;\r
- default:\r
- $this->setError('no transport found, or selected transport is not yet supported!');\r
- return false;\r
- break;\r
- }\r
- }\r
-\r
- /**\r
- * processes SOAP message returned from server\r
- *\r
- * @param array $headers The HTTP headers\r
- * @param string $data unprocessed response data from server\r
- * @return mixed value of the message, decoded into a PHP type\r
- * @access private\r
- */\r
- function parseResponse($headers, $data) {\r
- $this->debug('Entering parseResponse() for data of length ' . strlen($data) . ' headers:');\r
- $this->appendDebug($this->varDump($headers));\r
- if (!strstr($headers['content-type'], 'text/xml')) {\r
- $this->setError('Response not of type text/xml: ' . $headers['content-type']);\r
- return false;\r
- }\r
- if (strpos($headers['content-type'], '=')) {\r
- $enc = str_replace('"', '', substr(strstr($headers["content-type"], '='), 1));\r
- $this->debug('Got response encoding: ' . $enc);\r
- if(eregi('^(ISO-8859-1|US-ASCII|UTF-8)$',$enc)){\r
- $this->xml_encoding = strtoupper($enc);\r
- } else {\r
- $this->xml_encoding = 'US-ASCII';\r
- }\r
- } else {\r
- // should be US-ASCII for HTTP 1.0 or ISO-8859-1 for HTTP 1.1\r
- $this->xml_encoding = 'ISO-8859-1';\r
- }\r
- $this->debug('Use encoding: ' . $this->xml_encoding . ' when creating nusoap_parser');\r
- $parser = new nusoap_parser($data,$this->xml_encoding,$this->operation,$this->decode_utf8);\r
- // add parser debug data to our debug\r
- $this->appendDebug($parser->getDebug());\r
- // if parse errors\r
- if($errstr = $parser->getError()){\r
- $this->setError( $errstr);\r
- // destroy the parser object\r
- unset($parser);\r
- return false;\r
- } else {\r
- // get SOAP headers\r
- $this->responseHeaders = $parser->getHeaders();\r
- // get SOAP headers\r
- $this->responseHeader = $parser->get_soapheader();\r
- // get decoded message\r
- $return = $parser->get_soapbody();\r
- // add document for doclit support\r
- $this->document = $parser->document;\r
- // destroy the parser object\r
- unset($parser);\r
- // return decode message\r
- return $return;\r
- }\r
- }\r
-\r
- /**\r
- * sets user-specified cURL options\r
- *\r
- * @param mixed $option The cURL option (always integer?)\r
- * @param mixed $value The cURL option value\r
- * @access public\r
- */\r
- function setCurlOption($option, $value) {\r
- $this->debug("setCurlOption option=$option, value=");\r
- $this->appendDebug($this->varDump($value));\r
- $this->curl_options[$option] = $value;\r
- }\r
-\r
- /**\r
- * sets the SOAP endpoint, which can override WSDL\r
- *\r
- * @param string $endpoint The endpoint URL to use, or empty string or false to prevent override\r
- * @access public\r
- */\r
- function setEndpoint($endpoint) {\r
- $this->debug("setEndpoint(\"$endpoint\")");\r
- $this->forceEndpoint = $endpoint;\r
- }\r
-\r
- /**\r
- * set the SOAP headers\r
- *\r
- * @param mixed $headers String of XML with SOAP header content, or array of soapval objects for SOAP headers\r
- * @access public\r
- */\r
- function setHeaders($headers){\r
- $this->debug("setHeaders headers=");\r
- $this->appendDebug($this->varDump($headers));\r
- $this->requestHeaders = $headers;\r
- }\r
-\r
- /**\r
- * get the SOAP response headers (namespace resolution incomplete)\r
- *\r
- * @return string\r
- * @access public\r
- */\r
- function getHeaders(){\r
- return $this->responseHeaders;\r
- }\r
-\r
- /**\r
- * get the SOAP response Header (parsed)\r
- *\r
- * @return mixed\r
- * @access public\r
- */\r
- function getHeader(){\r
- return $this->responseHeader;\r
- }\r
-\r
- /**\r
- * set proxy info here\r
- *\r
- * @param string $proxyhost\r
- * @param string $proxyport\r
- * @param string $proxyusername\r
- * @param string $proxypassword\r
- * @access public\r
- */\r
- function setHTTPProxy($proxyhost, $proxyport, $proxyusername = '', $proxypassword = '') {\r
- $this->proxyhost = $proxyhost;\r
- $this->proxyport = $proxyport;\r
- $this->proxyusername = $proxyusername;\r
- $this->proxypassword = $proxypassword;\r
- }\r
-\r
- /**\r
- * if authenticating, set user credentials here\r
- *\r
- * @param string $username\r
- * @param string $password\r
- * @param string $authtype (basic|digest|certificate|ntlm)\r
- * @param array $certRequest (keys must be cainfofile (optional), sslcertfile, sslkeyfile, passphrase, verifypeer (optional), verifyhost (optional): see corresponding options in cURL docs)\r
- * @access public\r
- */\r
- function setCredentials($username, $password, $authtype = 'basic', $certRequest = array()) {\r
- $this->debug("setCredentials username=$username authtype=$authtype certRequest=");\r
- $this->appendDebug($this->varDump($certRequest));\r
- $this->username = $username;\r
- $this->password = $password;\r
- $this->authtype = $authtype;\r
- $this->certRequest = $certRequest;\r
- }\r
- \r
- /**\r
- * use HTTP encoding\r
- *\r
- * @param string $enc HTTP encoding\r
- * @access public\r
- */\r
- function setHTTPEncoding($enc='gzip, deflate'){\r
- $this->debug("setHTTPEncoding(\"$enc\")");\r
- $this->http_encoding = $enc;\r
- }\r
- \r
- /**\r
- * Set whether to try to use cURL connections if possible\r
- *\r
- * @param boolean $use Whether to try to use cURL\r
- * @access public\r
- */\r
- function setUseCURL($use) {\r
- $this->debug("setUseCURL($use)");\r
- $this->use_curl = $use;\r
- }\r
-\r
- /**\r
- * use HTTP persistent connections if possible\r
- *\r
- * @access public\r
- */\r
- function useHTTPPersistentConnection(){\r
- $this->debug("useHTTPPersistentConnection");\r
- $this->persistentConnection = true;\r
- }\r
- \r
- /**\r
- * gets the default RPC parameter setting.\r
- * If true, default is that call params are like RPC even for document style.\r
- * Each call() can override this value.\r
- *\r
- * This is no longer used.\r
- *\r
- * @return boolean\r
- * @access public\r
- * @deprecated\r
- */\r
- function getDefaultRpcParams() {\r
- return $this->defaultRpcParams;\r
- }\r
-\r
- /**\r
- * sets the default RPC parameter setting.\r
- * If true, default is that call params are like RPC even for document style\r
- * Each call() can override this value.\r
- *\r
- * This is no longer used.\r
- *\r
- * @param boolean $rpcParams\r
- * @access public\r
- * @deprecated\r
- */\r
- function setDefaultRpcParams($rpcParams) {\r
- $this->defaultRpcParams = $rpcParams;\r
- }\r
- \r
- /**\r
- * dynamically creates an instance of a proxy class,\r
- * allowing user to directly call methods from wsdl\r
- *\r
- * @return object soap_proxy object\r
- * @access public\r
- */\r
- function getProxy() {\r
- $r = rand();\r
- $evalStr = $this->_getProxyClassCode($r);\r
- //$this->debug("proxy class: $evalStr");\r
- if ($this->getError()) {\r
- $this->debug("Error from _getProxyClassCode, so return NULL");\r
- return null;\r
- }\r
- // eval the class\r
- eval($evalStr);\r
- // instantiate proxy object\r
- eval("\$proxy = new nusoap_proxy_$r('');");\r
- // transfer current wsdl data to the proxy thereby avoiding parsing the wsdl twice\r
- $proxy->endpointType = 'wsdl';\r
- $proxy->wsdlFile = $this->wsdlFile;\r
- $proxy->wsdl = $this->wsdl;\r
- $proxy->operations = $this->operations;\r
- $proxy->defaultRpcParams = $this->defaultRpcParams;\r
- // transfer other state\r
- $proxy->soap_defencoding = $this->soap_defencoding;\r
- $proxy->username = $this->username;\r
- $proxy->password = $this->password;\r
- $proxy->authtype = $this->authtype;\r
- $proxy->certRequest = $this->certRequest;\r
- $proxy->requestHeaders = $this->requestHeaders;\r
- $proxy->endpoint = $this->endpoint;\r
- $proxy->forceEndpoint = $this->forceEndpoint;\r
- $proxy->proxyhost = $this->proxyhost;\r
- $proxy->proxyport = $this->proxyport;\r
- $proxy->proxyusername = $this->proxyusername;\r
- $proxy->proxypassword = $this->proxypassword;\r
- $proxy->http_encoding = $this->http_encoding;\r
- $proxy->timeout = $this->timeout;\r
- $proxy->response_timeout = $this->response_timeout;\r
- $proxy->persistentConnection = &$this->persistentConnection;\r
- $proxy->decode_utf8 = $this->decode_utf8;\r
- $proxy->curl_options = $this->curl_options;\r
- $proxy->bindingType = $this->bindingType;\r
- $proxy->use_curl = $this->use_curl;\r
- return $proxy;\r
- }\r
-\r
- /**\r
- * dynamically creates proxy class code\r
- *\r
- * @return string PHP/NuSOAP code for the proxy class\r
- * @access private\r
- */\r
- function _getProxyClassCode($r) {\r
- $this->debug("in getProxy endpointType=$this->endpointType");\r
- $this->appendDebug("wsdl=" . $this->varDump($this->wsdl));\r
- if ($this->endpointType != 'wsdl') {\r
- $evalStr = 'A proxy can only be created for a WSDL client';\r
- $this->setError($evalStr);\r
- $evalStr = "echo \"$evalStr\";";\r
- return $evalStr;\r
- }\r
- if ($this->endpointType == 'wsdl' && is_null($this->wsdl)) {\r
- $this->loadWSDL();\r
- if ($this->getError()) {\r
- return "echo \"" . $this->getError() . "\";";\r
- }\r
- }\r
- $evalStr = '';\r
- foreach ($this->operations as $operation => $opData) {\r
- if ($operation != '') {\r
- // create param string and param comment string\r
- if (sizeof($opData['input']['parts']) > 0) {\r
- $paramStr = '';\r
- $paramArrayStr = '';\r
- $paramCommentStr = '';\r
- foreach ($opData['input']['parts'] as $name => $type) {\r
- $paramStr .= "\$$name, ";\r
- $paramArrayStr .= "'$name' => \$$name, ";\r
- $paramCommentStr .= "$type \$$name, ";\r
- }\r
- $paramStr = substr($paramStr, 0, strlen($paramStr)-2);\r
- $paramArrayStr = substr($paramArrayStr, 0, strlen($paramArrayStr)-2);\r
- $paramCommentStr = substr($paramCommentStr, 0, strlen($paramCommentStr)-2);\r
- } else {\r
- $paramStr = '';\r
- $paramArrayStr = '';\r
- $paramCommentStr = 'void';\r
- }\r
- $opData['namespace'] = !isset($opData['namespace']) ? 'http://testuri.com' : $opData['namespace'];\r
- $evalStr .= "// $paramCommentStr\r
- function " . str_replace('.', '__', $operation) . "($paramStr) {\r
- \$params = array($paramArrayStr);\r
- return \$this->call('$operation', \$params, '".$opData['namespace']."', '".(isset($opData['soapAction']) ? $opData['soapAction'] : '')."');\r
- }\r
- ";\r
- unset($paramStr);\r
- unset($paramCommentStr);\r
- }\r
- }\r
- $evalStr = 'class nusoap_proxy_'.$r.' extends nusoap_client {\r
- '.$evalStr.'\r
-}';\r
- return $evalStr;\r
- }\r
-\r
- /**\r
- * dynamically creates proxy class code\r
- *\r
- * @return string PHP/NuSOAP code for the proxy class\r
- * @access public\r
- */\r
- function getProxyClassCode() {\r
- $r = rand();\r
- return $this->_getProxyClassCode($r);\r
- }\r
-\r
- /**\r
- * gets the HTTP body for the current request.\r
- *\r
- * @param string $soapmsg The SOAP payload\r
- * @return string The HTTP body, which includes the SOAP payload\r
- * @access private\r
- */\r
- function getHTTPBody($soapmsg) {\r
- return $soapmsg;\r
- }\r
- \r
- /**\r
- * gets the HTTP content type for the current request.\r
- *\r
- * Note: getHTTPBody must be called before this.\r
- *\r
- * @return string the HTTP content type for the current request.\r
- * @access private\r
- */\r
- function getHTTPContentType() {\r
- return 'text/xml';\r
- }\r
- \r
- /**\r
- * gets the HTTP content type charset for the current request.\r
- * returns false for non-text content types.\r
- *\r
- * Note: getHTTPBody must be called before this.\r
- *\r
- * @return string the HTTP content type charset for the current request.\r
- * @access private\r
- */\r
- function getHTTPContentTypeCharset() {\r
- return $this->soap_defencoding;\r
- }\r
-\r
- /*\r
- * whether or not parser should decode utf8 element content\r
- *\r
- * @return always returns true\r
- * @access public\r
- */\r
- function decodeUTF8($bool){\r
- $this->decode_utf8 = $bool;\r
- return true;\r
- }\r
-\r
- /**\r
- * adds a new Cookie into $this->cookies array\r
- *\r
- * @param string $name Cookie Name\r
- * @param string $value Cookie Value\r
- * @return boolean if cookie-set was successful returns true, else false\r
- * @access public\r
- */\r
- function setCookie($name, $value) {\r
- if (strlen($name) == 0) {\r
- return false;\r
- }\r
- $this->cookies[] = array('name' => $name, 'value' => $value);\r
- return true;\r
- }\r
-\r
- /**\r
- * gets all Cookies\r
- *\r
- * @return array with all internal cookies\r
- * @access public\r
- */\r
- function getCookies() {\r
- return $this->cookies;\r
- }\r
-\r
- /**\r
- * checks all Cookies and delete those which are expired\r
- *\r
- * @return boolean always return true\r
- * @access private\r
- */\r
- function checkCookies() {\r
- if (sizeof($this->cookies) == 0) {\r
- return true;\r
- }\r
- $this->debug('checkCookie: check ' . sizeof($this->cookies) . ' cookies');\r
- $curr_cookies = $this->cookies;\r
- $this->cookies = array();\r
- foreach ($curr_cookies as $cookie) {\r
- if (! is_array($cookie)) {\r
- $this->debug('Remove cookie that is not an array');\r
- continue;\r
- }\r
- if ((isset($cookie['expires'])) && (! empty($cookie['expires']))) {\r
- if (strtotime($cookie['expires']) > time()) {\r
- $this->cookies[] = $cookie;\r
- } else {\r
- $this->debug('Remove expired cookie ' . $cookie['name']);\r
- }\r
- } else {\r
- $this->cookies[] = $cookie;\r
- }\r
- }\r
- $this->debug('checkCookie: '.sizeof($this->cookies).' cookies left in array');\r
- return true;\r
- }\r
-\r
- /**\r
- * updates the current cookies with a new set\r
- *\r
- * @param array $cookies new cookies with which to update current ones\r
- * @return boolean always return true\r
- * @access private\r
- */\r
- function UpdateCookies($cookies) {\r
- if (sizeof($this->cookies) == 0) {\r
- // no existing cookies: take whatever is new\r
- if (sizeof($cookies) > 0) {\r
- $this->debug('Setting new cookie(s)');\r
- $this->cookies = $cookies;\r
- }\r
- return true;\r
- }\r
- if (sizeof($cookies) == 0) {\r
- // no new cookies: keep what we've got\r
- return true;\r
- }\r
- // merge\r
- foreach ($cookies as $newCookie) {\r
- if (!is_array($newCookie)) {\r
- continue;\r
- }\r
- if ((!isset($newCookie['name'])) || (!isset($newCookie['value']))) {\r
- continue;\r
- }\r
- $newName = $newCookie['name'];\r
-\r
- $found = false;\r
- for ($i = 0; $i < count($this->cookies); $i++) {\r
- $cookie = $this->cookies[$i];\r
- if (!is_array($cookie)) {\r
- continue;\r
- }\r
- if (!isset($cookie['name'])) {\r
- continue;\r
- }\r
- if ($newName != $cookie['name']) {\r
- continue;\r
- }\r
- $newDomain = isset($newCookie['domain']) ? $newCookie['domain'] : 'NODOMAIN';\r
- $domain = isset($cookie['domain']) ? $cookie['domain'] : 'NODOMAIN';\r
- if ($newDomain != $domain) {\r
- continue;\r
- }\r
- $newPath = isset($newCookie['path']) ? $newCookie['path'] : 'NOPATH';\r
- $path = isset($cookie['path']) ? $cookie['path'] : 'NOPATH';\r
- if ($newPath != $path) {\r
- continue;\r
- }\r
- $this->cookies[$i] = $newCookie;\r
- $found = true;\r
- $this->debug('Update cookie ' . $newName . '=' . $newCookie['value']);\r
- break;\r
- }\r
- if (! $found) {\r
- $this->debug('Add cookie ' . $newName . '=' . $newCookie['value']);\r
- $this->cookies[] = $newCookie;\r
- }\r
- }\r
- return true;\r
- }\r
-}\r
-\r
-if (!extension_loaded('soap')) {\r
- /**\r
- * For backwards compatiblity, define soapclient unless the PHP SOAP extension is loaded.\r
- */\r
- class soapclient extends nusoap_client {\r
- }\r
-}\r
-?>\r