74$GLOBALS[
'_transient'][
'static'][
'nusoap_base'][
'globalDebugLevel'] = 9;
93 public $title =
'NuSOAP';
100 public $version =
'0.9.5';
107 public $revision =
'$Revision: 1.123 $';
114 public $error_str =
'';
121 public $debug_str =
'';
129 public $charencoding =
true;
144 public $XMLSchemaVersion =
'https://www.w3.org/2001/XMLSchema';
152 public $soap_defencoding =
'UTF-8';
163 public $namespaces = [
164 'SOAP-ENV' =>
'https://schemas.xmlsoap.org/soap/envelope/',
165 'xsd' =>
'https://www.w3.org/2001/XMLSchema',
166 'xsi' =>
'https://www.w3.org/2001/XMLSchema-instance',
167 'SOAP-ENC' =>
'https://schemas.xmlsoap.org/soap/encoding/'
176 public $usedNamespaces = [];
186 'https://www.w3.org/2001/XMLSchema' => [
187 'string'=>
'string',
'boolean'=>
'boolean',
'float'=>
'double',
'double'=>
'double',
'decimal'=>
'double',
188 'duration'=>
'',
'dateTime'=>
'string',
'time'=>
'string',
'date'=>
'string',
'gYearMonth'=>
'',
189 'gYear'=>
'',
'gMonthDay'=>
'',
'gDay'=>
'',
'gMonth'=>
'',
'hexBinary'=>
'string',
'base64Binary'=>
'string',
191 'anyType'=>
'string',
'anySimpleType'=>
'string',
193 'normalizedString'=>
'string',
'token'=>
'string',
'language'=>
'',
'NMTOKEN'=>
'',
'NMTOKENS'=>
'',
'Name'=>
'',
'NCName'=>
'',
'ID'=>
'',
194 'IDREF'=>
'',
'IDREFS'=>
'',
'ENTITY'=>
'',
'ENTITIES'=>
'',
'integer'=>
'integer',
'nonPositiveInteger'=>
'integer',
195 'negativeInteger'=>
'integer',
'long'=>
'integer',
'int'=>
'integer',
'short'=>
'integer',
'byte'=>
'integer',
'nonNegativeInteger'=>
'integer',
196 'unsignedLong'=>
'',
'unsignedInt'=>
'',
'unsignedShort'=>
'',
'unsignedByte'=>
'',
'positiveInteger'=>
''
198 'https://www.w3.org/2000/10/XMLSchema' => [
199 'i4'=>
'',
'int'=>
'integer',
'boolean'=>
'boolean',
'string'=>
'string',
'double'=>
'double',
200 'float'=>
'double',
'dateTime'=>
'string',
201 'timeInstant'=>
'string',
'base64Binary'=>
'string',
'base64'=>
'string',
'ur-type'=>
'array'
203 'https://www.w3.org/1999/XMLSchema' => [
204 'i4'=>
'',
'int'=>
'integer',
'boolean'=>
'boolean',
'string'=>
'string',
'double'=>
'double',
205 'float'=>
'double',
'dateTime'=>
'string',
206 'timeInstant'=>
'string',
'base64Binary'=>
'string',
'base64'=>
'string',
'ur-type'=>
'array'
208 'https://soapinterop.org/xsd' => [
'SOAPStruct' =>
'struct'],
209 'https://schemas.xmlsoap.org/soap/encoding/' => [
'base64' =>
'string',
'array' =>
'array',
'Array' =>
'array'],
210 'https://xml.apache.org/xml-soap' => [
'Map']
221 public $xmlEntities = [
222 'quot' =>
'"',
'amp' =>
'&',
223 'lt' =>
'<',
'gt' =>
'>',
'apos' =>
"'"
233 $this->debugLevel = $GLOBALS[
'_transient'][
'static'][
'nusoap_base'][
'globalDebugLevel'];
244 return $GLOBALS[
'_transient'][
'static'][
'nusoap_base'][
'globalDebugLevel'];
255 $GLOBALS[
'_transient'][
'static'][
'nusoap_base'][
'globalDebugLevel'] = $level;
266 return $this->debugLevel;
277 $this->debugLevel = $level;
288 if ($this->debugLevel > 0) {
301 if ($this->debugLevel > 0) {
304 $this->debug_str .= $string;
317 $this->debug_str =
'';
330 return $this->debug_str;
344 while (strpos($this->debug_str,
'--')) {
345 $this->debug_str = str_replace(
'--',
'- -', $this->debug_str);
347 $ret =
"<!--\n" . $this->debug_str .
"\n-->";
360 if ($this->charencoding) {
361 $val = str_replace(
'&',
'&', $val);
362 $val = str_replace(
"'",
''', $val);
363 $val = str_replace(
'"',
'"', $val);
364 $val = str_replace(
'<',
'<', $val);
365 $val = str_replace(
'>',
'>', $val);
378 if (
'' != $this->error_str) {
379 return $this->error_str;
393 $this->error_str = $str;
405 $keyList = array_keys($val);
406 foreach ($keyList as $keyListValue) {
407 if (!is_int($keyListValue)) {
408 return 'arrayStruct';
411 return 'arraySimple';
429 public function serialize_val($val, $name=
false, $type=
false, $name_ns=
false, $type_ns=
false, $attributes=
false, $use=
'encoded', $soapval=
false)
432 $this->
debug(
"in serialize_val: name=$name, type=$type, name_ns=$name_ns, type_ns=$type_ns, use=$use, soapval=$soapval");
436 if (is_object($val) &&
'soapval' == get_class($val) && (! $soapval)) {
437 $this->
debug(
'serialize_val: serialize soapval');
438 $xml = $val->serialize($use);
441 $this->
debug(
"serialize_val of soapval returning $xml");
445 if (is_numeric($name)) {
446 $name =
'__numeric_' . $name;
453 $prefix =
'nu' . random_int(1000, 9999);
454 $name = $prefix.
':'.$name;
455 $xmlns .=
" xmlns:$prefix=\"$name_ns\"";
458 if (
'' != $type_ns && $type_ns == $this->namespaces[
'xsd']) {
461 $type_prefix =
'xsd';
462 } elseif ($type_ns) {
463 $type_prefix =
'ns' . random_int(1000, 9999);
464 $xmlns .=
" xmlns:$type_prefix=\"$type_ns\"";
469 foreach ($attributes as $k => $v) {
470 $atts .=
" $k=\"".$this->expandEntities($v).
'"';
475 $this->
debug(
'serialize_val: serialize null');
476 if (
'literal' == $use) {
478 $xml =
"<$name$xmlns$atts/>";
479 $this->
debug(
"serialize_val returning $xml");
482 if (isset($type) && isset($type_prefix)) {
483 $type_str =
" xsi:type=\"$type_prefix:$type\"";
487 $xml =
"<$name$xmlns$type_str$atts xsi:nil=\"true\"/>";
488 $this->
debug(
"serialize_val returning $xml");
493 if (
'' != $type && isset($this->typemap[$this->XMLSchemaVersion][$type])) {
494 $this->
debug(
'serialize_val: serialize xsd built-in primitive type');
496 if (
'boolean' == $type) {
497 $val = $val ?
'true' :
'false';
501 } elseif (is_string($val)) {
504 if (
'literal' == $use) {
505 $xml =
"<$name$xmlns$atts>$val</$name>";
506 $this->
debug(
"serialize_val returning $xml");
509 $xml =
"<$name$xmlns xsi:type=\"xsd:$type\"$atts>$val</$name>";
510 $this->
debug(
"serialize_val returning $xml");
517 case (is_bool($val) ||
'boolean' == $type):
518 $this->
debug(
'serialize_val: serialize boolean');
519 if (
'boolean' == $type) {
520 $val = $val ?
'true' :
'false';
524 if (
'literal' == $use) {
525 $xml .=
"<$name$xmlns$atts>$val</$name>";
527 $xml .=
"<$name$xmlns xsi:type=\"xsd:boolean\"$atts>$val</$name>";
530 case (is_int($val) || is_int($val) ||
'int' == $type):
531 $this->
debug(
'serialize_val: serialize int');
532 if (
'literal' == $use) {
533 $xml .=
"<$name$xmlns$atts>$val</$name>";
535 $xml .=
"<$name$xmlns xsi:type=\"xsd:int\"$atts>$val</$name>";
538 case (is_float($val) || is_float($val) ||
'float' == $type):
539 $this->
debug(
'serialize_val: serialize float');
540 if (
'literal' == $use) {
541 $xml .=
"<$name$xmlns$atts>$val</$name>";
543 $xml .=
"<$name$xmlns xsi:type=\"xsd:float\"$atts>$val</$name>";
546 case (is_string($val) ||
'string' == $type):
547 $this->
debug(
'serialize_val: serialize string');
549 if (
'literal' == $use) {
550 $xml .=
"<$name$xmlns$atts>$val</$name>";
552 $xml .=
"<$name$xmlns xsi:type=\"xsd:string\"$atts>$val</$name>";
555 case is_object($val):
556 $this->
debug(
'serialize_val: serialize object');
557 if (
'soapval' == get_class($val)) {
558 $this->
debug(
'serialize_val: serialize soapval object');
559 $pXml = $val->serialize($use);
564 $name = get_class($val);
565 $this->
debug(
"In serialize_val, used class name $name as element name");
567 $this->
debug(
"In serialize_val, do not override name $name for element name for class " . get_class($val));
569 foreach (get_object_vars($val) as $k => $v) {
570 $pXml = isset($pXml) ? $pXml.$this->serialize_val($v, $k,
false,
false,
false,
false, $use) : $this->
serialize_val($v, $k,
false,
false,
false,
false, $use);
573 if (isset($type) && isset($type_prefix)) {
574 $type_str =
" xsi:type=\"$type_prefix:$type\"";
578 if (
'literal' == $use) {
579 $xml .=
"<$name$xmlns$atts>$pXml</$name>";
581 $xml .=
"<$name$xmlns$type_str$atts>$pXml</$name>";
585 case (is_array($val) || $type):
588 if (
'arraySimple' == $valueType || preg_match(
'/^ArrayOf/', $type)) {
589 $this->
debug(
'serialize_val: serialize array');
591 if (is_array($val) && count($val)> 0) {
592 foreach ($val as $v) {
593 if (is_object($v) &&
'soapval' == get_class($v)) {
594 $tt_ns = $v->type_ns;
596 } elseif (is_array($v)) {
601 $array_types[$tt] = 1;
603 $xml .= $this->
serialize_val($v,
'item',
false,
false,
false,
false, $use);
606 if (count($array_types) > 1) {
607 $array_typename =
'xsd:anyType';
608 } elseif (isset($tt) && isset($this->typemap[$this->XMLSchemaVersion][$tt])) {
609 if (
'integer' == $tt) {
612 $array_typename =
'xsd:'.$tt;
613 } elseif (isset($tt) &&
'arraySimple' == $tt) {
614 $array_typename =
'SOAP-ENC:Array';
615 } elseif (isset($tt) &&
'arrayStruct' == $tt) {
616 $array_typename =
'unnamed_struct_use_soapval';
619 if (
'' != $tt_ns && $tt_ns == $this->namespaces[
'xsd']) {
620 $array_typename =
'xsd:' . $tt;
622 $tt_prefix =
'ns' . random_int(1000, 9999);
623 $array_typename =
"$tt_prefix:$tt";
624 $xmlns .=
" xmlns:$tt_prefix=\"$tt_ns\"";
626 $array_typename = $tt;
630 if (
'literal' == $use) {
632 } elseif (isset($type) && isset($type_prefix)) {
633 $type_str =
" xsi:type=\"$type_prefix:$type\"";
635 $type_str =
' xsi:type="SOAP-ENC:Array" SOAP-ENC:arrayType="' . $array_typename .
"[$array_type]\"";
639 if (
'literal' == $use) {
641 } elseif (isset($type) && isset($type_prefix)) {
642 $type_str =
" xsi:type=\"$type_prefix:$type\"";
644 $type_str =
' xsi:type="SOAP-ENC:Array" SOAP-ENC:arrayType="xsd:anyType[0]"';
648 $xml =
"<$name$xmlns$type_str$atts>".$xml.
"</$name>";
651 $this->
debug(
'serialize_val: serialize struct');
652 if (isset($type) && isset($type_prefix)) {
653 $type_str =
" xsi:type=\"$type_prefix:$type\"";
657 if (
'literal' == $use) {
658 $xml .=
"<$name$xmlns$atts>";
660 $xml .=
"<$name$xmlns$type_str$atts>";
662 foreach ($val as $k => $v) {
664 if (
'Map' == $type &&
'https://xml.apache.org/xml-soap' == $type_ns) {
666 $xml .= $this->
serialize_val($k,
'key',
false,
false,
false,
false, $use);
667 $xml .= $this->
serialize_val($v,
'value',
false,
false,
false,
false, $use);
670 $xml .= $this->
serialize_val($v, $k,
false,
false,
false,
false, $use);
677 $this->
debug(
'serialize_val: serialize unknown');
678 $xml .=
'not detected, got '.gettype($val).
' for '.$val;
681 $this->
debug(
"serialize_val returning $xml");
697 public function serializeEnvelope($body, $headers=
false, $namespaces= [], $style=
'rpc', $use=
'encoded', $encodingStyle=
'https://schemas.xmlsoap.org/soap/encoding/')
703 $this->
debug(
'In serializeEnvelope length=' . strlen($body) .
' body (max 1000 characters)=' . substr($body, 0, 1000) .
" style=$style use=$use encodingStyle=$encodingStyle");
704 $this->
debug(
'headers:');
706 $this->
debug(
'namespaces:');
711 foreach (array_merge($this->namespaces, $namespaces) as $k => $v) {
712 $ns_string .=
" xmlns:$k=\"$v\"";
714 if ($encodingStyle) {
715 $ns_string =
" SOAP-ENV:encodingStyle=\"$encodingStyle\"$ns_string";
720 if (is_array($headers)) {
722 foreach ($headers as $k => $v) {
723 if (is_object($v) &&
'soapval' == get_class($v)) {
724 $xml .= $this->
serialize_val($v,
false,
false,
false,
false,
false, $use);
726 $xml .= $this->
serialize_val($v, $k,
false,
false,
false,
false, $use);
730 $this->
debug(
"In serializeEnvelope, serialized array of headers to $headers");
732 $headers =
'<SOAP-ENV:Header>' . $headers .
'</SOAP-ENV:Header>';
736 '<?xml version="1.0" encoding="'.$this->soap_defencoding .
'"?' .
'>' .
737 '<SOAP-ENV:Envelope'.$ns_string .
'>' .
738 $headers.
'<SOAP-ENV:Body>' .
739 $body.
'</SOAP-ENV:Body>' .
'</SOAP-ENV:Envelope>';
752 $str = htmlspecialchars($str);
767 if (strrpos($qname,
':')) {
769 $name = substr($qname, strrpos($qname,
':') + 1);
771 $ns = substr($qname, 0, strrpos($qname,
':'));
774 return $p .
':' . $name;
792 if (strpos($qname,
':') && !preg_match(
'/^http:\/\//', $qname)) {
794 $name = substr(strstr($qname,
':'), 1);
796 $prefix = substr($qname, 0, strpos($qname,
':'));
797 if (isset($this->namespaces[$prefix])) {
798 return $this->namespaces[$prefix].
':'.$name;
817 if ($sstr = strrchr($str,
':')) {
819 return substr($sstr, 1);
835 if ($pos = strrpos($str,
':')) {
837 return substr($str, 0, $pos);
851 if (isset($this->namespaces[$prefix])) {
852 return $this->namespaces[$prefix];
868 foreach ($this->namespaces as $p => $n) {
869 if ($ns == $n || $ns == $p) {
870 $this->usedNamespaces[$p] = $n;
885 if (function_exists(
'gettimeofday')) {
886 $tod = gettimeofday();
888 $usec = $tod[
'usec'];
893 return strftime(
'%Y-%m-%d %H:%M:%S', $sec) .
'.' . sprintf(
'%06d', $usec);
907 $ret_val = ob_get_contents();
936function timestamp_to_iso8601($timestamp, $utc=
true)
938 $datestr = date(
'Y-m-d\TH:i:sO', $timestamp);
939 $pos = strrpos($datestr,
'+');
940 if (
false === $pos) {
941 $pos = strrpos($datestr,
'-');
943 if (
false !== $pos) {
944 if (strlen($datestr) == $pos + 5) {
945 $datestr = substr($datestr, 0, $pos + 3) .
':' . substr($datestr, -2);
956 '([0-9]{2})(\.[0-9]*)?'.
957 '(Z|[+\-][0-9]{2}:?[0-9]{2})?'.
960 if (preg_match($pattern, $datestr, $regs)) {
961 return sprintf(
'%04d-%02d-%02dT%02d:%02d:%02dZ', $regs[1], $regs[2], $regs[3], $regs[4], $regs[5], $regs[6]);
976function iso8601_to_timestamp($datestr)
985 '([0-9]{2})(\.[0-9]+)?'.
986 '(Z|[+\-][0-9]{2}:?[0-9]{2})?'.
988 if (preg_match($pattern, $datestr, $regs)) {
990 if (
'Z' != $regs[8]) {
991 $op = substr($regs[8], 0, 1);
992 $h = substr($regs[8], 1, 2);
993 $m = substr($regs[8], strlen($regs[8])-2, 2);
995 $regs[4] = $regs[4] + $h;
996 $regs[5] = $regs[5] + $m;
997 } elseif (
'+' == $op) {
998 $regs[4] = $regs[4] - $h;
999 $regs[5] = $regs[5] - $m;
1002 return gmmktime($regs[4], $regs[5], $regs[6], $regs[2], $regs[3], $regs[1]);
1016function usleepWindows($usec)
1018 $start = gettimeofday();
1021 $stop = gettimeofday();
1022 $timePassed = 1_000_000 * ($stop[
'sec'] - $start[
'sec'])
1023 + $stop[
'usec'] - $start[
'usec'];
1024 }
while ($timePassed < $usec);
1058 public $faultstring;
1064 public $faultdetail;
1074 public function __construct($faultcode, $faultactor=
'', $faultstring=
'', $faultdetail=
'')
1076 parent::__construct();
1077 $this->faultcode = $faultcode;
1078 $this->faultactor = $faultactor;
1079 $this->faultstring = $faultstring;
1080 $this->faultdetail = $faultdetail;
1092 foreach ($this->namespaces as $k => $v) {
1093 $ns_string .=
"\n xmlns:$k=\"$v\"";
1096 '<?xml version="1.0" encoding="'.$this->soap_defencoding.
'"?>'.
1097 '<SOAP-ENV:Envelope SOAP-ENV:encodingStyle="https://schemas.xmlsoap.org/soap/encoding/"'.$ns_string.
">\n".
1104 '</SOAP-ENV:Fault>'.
1106 '</SOAP-ENV:Envelope>';
1135 public $schema =
'';
1138 public $enclosingNamespaces;
1140 public $schemaInfo = [];
1141 public $schemaTargetNamespace =
'';
1143 public $attributes = [];
1144 public $complexTypes = [];
1145 public $complexTypeStack = [];
1146 public $currentComplexType =
null;
1147 public $elements = [];
1148 public $elementStack = [];
1149 public $currentElement =
null;
1150 public $simpleTypes = [];
1151 public $simpleTypeStack = [];
1152 public $currentSimpleType =
null;
1154 public $imports = [];
1157 public $position = 0;
1159 public $depth_array = [];
1160 public $message = [];
1161 public $defaultNamespace = [];
1173 parent::__construct();
1174 $this->
debug(
'nusoap_xmlschema class instantiated, inside constructor');
1176 $this->schema = $schema;
1180 $this->enclosingNamespaces = $namespaces;
1181 $this->namespaces = array_merge($this->namespaces, $namespaces);
1184 if (
'' != $schema) {
1185 $this->
debug(
'initial schema file: '.$schema);
1191 $this->
debug(
'initial xml file: '.$xml);
1208 $xmlStr = @implode(
'', @file($xml));
1209 if (
'' == $xmlStr) {
1210 $msg =
'Error reading XML from '.$xml;
1215 $this->
debug(
"parsing $xml");
1217 $this->
debug(
"done parsing $xml");
1237 $this->parser = xml_parser_create();
1239 xml_parser_set_option($this->parser, XML_OPTION_CASE_FOLDING, 0);
1242 xml_set_object($this->parser, $this);
1245 if (
'schema' == $type) {
1246 xml_set_element_handler($this->parser,
'schemaStartElement',
'schemaEndElement');
1247 xml_set_character_data_handler($this->parser,
'schemaCharacterData');
1248 } elseif (
'xml' == $type) {
1249 xml_set_element_handler($this->parser,
'xmlStartElement',
'xmlEndElement');
1250 xml_set_character_data_handler($this->parser,
'xmlCharacterData');
1254 if (!xml_parse($this->parser, $xml,
true)) {
1256 $errstr = sprintf(
'XML error parsing XML schema on line %d: %s',
1257 xml_get_current_line_number($this->parser),
1258 xml_error_string(xml_get_error_code($this->parser))
1260 $this->
debug($errstr);
1261 $this->
debug(
"XML payload:\n" . $xml);
1265 xml_parser_free($this->parser);
1267 $this->
debug(
'no xml passed to parseString()!!');
1268 $this->
setError(
'no xml passed to parseString()!!');
1282 for ($i = 0; $i < count($this->complexTypeStack); $i++) {
1283 $scope .= $this->complexTypeStack[$i] .
'_';
1285 return $scope . $ename .
'_ContainedType';
1301 $pos = $this->position++;
1302 $depth = $this->depth++;
1304 $this->depth_array[$depth] = $pos;
1305 $this->message[$pos] = [
'cdata' =>
''];
1307 $this->defaultNamespace[$pos] = $this->defaultNamespace[$this->depth_array[$depth - 1]];
1309 $this->defaultNamespace[$pos] =
false;
1313 if ($prefix = $this->
getPrefix($name)) {
1321 if ((is_countable($attrs) ? count($attrs) : 0) > 0) {
1322 foreach ($attrs as $k => $v) {
1324 if (preg_match(
'/^xmlns/', $k)) {
1327 if ($ns_prefix = substr(strrchr($k,
':'), 1)) {
1329 $this->namespaces[$ns_prefix] = $v;
1331 $this->defaultNamespace[$pos] = $v;
1333 $this->namespaces[
'ns'.(count($this->namespaces)+1)] = $v;
1336 if (
'https://www.w3.org/2001/XMLSchema' == $v ||
'https://www.w3.org/1999/XMLSchema' == $v ||
'https://www.w3.org/2000/10/XMLSchema' == $v) {
1337 $this->XMLSchemaVersion = $v;
1338 $this->namespaces[
'xsi'] = $v.
'-instance';
1342 foreach ($attrs as $k => $v) {
1344 $k = strpos($k,
':') ? $this->
expandQname($k) : $k;
1345 $v = strpos($v,
':') ? $this->
expandQname($v) : $v;
1359 $this->complexTypes[$this->currentComplexType][
'compositor'] = $name;
1366 $this->
xdebug(
'parsing attribute:');
1368 if (!isset($attrs[
'form'])) {
1370 $attrs[
'form'] = $this->schemaInfo[
'attributeFormDefault'];
1372 if (isset($attrs[
'https://schemas.xmlsoap.org/wsdl/:arrayType'])) {
1373 $v = $attrs[
'https://schemas.xmlsoap.org/wsdl/:arrayType'];
1374 if (!strpos($v,
':')) {
1376 if ($this->defaultNamespace[$pos]) {
1378 $attrs[
'https://schemas.xmlsoap.org/wsdl/:arrayType'] = $this->defaultNamespace[$pos] .
':' . $attrs[
'https://schemas.xmlsoap.org/wsdl/:arrayType'];
1382 if (isset($attrs[
'name'])) {
1383 $this->attributes[$attrs[
'name']] = $attrs;
1384 $aname = $attrs[
'name'];
1385 } elseif (isset($attrs[
'ref']) &&
'https://schemas.xmlsoap.org/soap/encoding/:arrayType' == $attrs[
'ref']) {
1386 if (isset($attrs[
'https://schemas.xmlsoap.org/wsdl/:arrayType'])) {
1387 $aname = $attrs[
'https://schemas.xmlsoap.org/wsdl/:arrayType'];
1391 } elseif (isset($attrs[
'ref'])) {
1392 $aname = $attrs[
'ref'];
1393 $this->attributes[$attrs[
'ref']] = $attrs;
1396 if ($this->currentComplexType) {
1397 $this->complexTypes[$this->currentComplexType][
'attrs'][$aname] = $attrs;
1400 if (isset($attrs[
'https://schemas.xmlsoap.org/wsdl/:arrayType']) ||
'arrayType' == $this->
getLocalPart($aname)) {
1401 $this->complexTypes[$this->currentComplexType][
'phpType'] =
'array';
1403 if (isset($attrs[
'https://schemas.xmlsoap.org/wsdl/:arrayType'])) {
1404 $v = $attrs[
'https://schemas.xmlsoap.org/wsdl/:arrayType'];
1408 if (strpos($v,
'[,]')) {
1409 $this->complexTypes[$this->currentComplexType][
'multidimensional'] =
true;
1411 $v = substr($v, 0, strpos($v,
'['));
1412 if (!strpos($v,
':') && isset($this->typemap[$this->XMLSchemaVersion][$v])) {
1413 $v = $this->XMLSchemaVersion.
':'.$v;
1415 $this->complexTypes[$this->currentComplexType][
'arrayType'] = $v;
1418 case 'complexContent':
1419 $this->
xdebug(
"do nothing for element $name");
1422 array_push($this->complexTypeStack, $this->currentComplexType);
1423 if (isset($attrs[
'name'])) {
1426 $this->
xdebug(
'processing named complexType '.$attrs[
'name']);
1428 $this->currentComplexType = $attrs[
'name'];
1429 $this->complexTypes[$this->currentComplexType] = $attrs;
1430 $this->complexTypes[$this->currentComplexType][
'typeClass'] =
'complexType';
1438 if (isset($attrs[
'base']) && preg_match(
'/:Array$/', $attrs[
'base'])) {
1439 $this->
xdebug(
'complexType is unusual array');
1440 $this->complexTypes[$this->currentComplexType][
'phpType'] =
'array';
1442 $this->complexTypes[$this->currentComplexType][
'phpType'] =
'struct';
1446 $this->
xdebug(
'processing unnamed complexType for element ' . $this->currentElement .
' named ' . $name);
1447 $this->currentComplexType = $name;
1449 $this->complexTypes[$this->currentComplexType] = $attrs;
1450 $this->complexTypes[$this->currentComplexType][
'typeClass'] =
'complexType';
1458 if (isset($attrs[
'base']) && preg_match(
'/:Array$/', $attrs[
'base'])) {
1459 $this->
xdebug(
'complexType is unusual array');
1460 $this->complexTypes[$this->currentComplexType][
'phpType'] =
'array';
1462 $this->complexTypes[$this->currentComplexType][
'phpType'] =
'struct';
1465 $this->complexTypes[$this->currentComplexType][
'simpleContent'] =
'false';
1468 array_push($this->elementStack, $this->currentElement);
1469 if (!isset($attrs[
'form'])) {
1470 if ($this->currentComplexType) {
1471 $attrs[
'form'] = $this->schemaInfo[
'elementFormDefault'];
1474 $attrs[
'form'] =
'qualified';
1477 if (isset($attrs[
'type'])) {
1478 $this->
xdebug(
'processing typed element ' . $attrs[
'name'] .
' of type ' . $attrs[
'type']);
1479 if (! $this->
getPrefix($attrs[
'type'])) {
1480 if ($this->defaultNamespace[$pos]) {
1481 $attrs[
'type'] = $this->defaultNamespace[$pos] .
':' . $attrs[
'type'];
1482 $this->
xdebug(
'used default namespace to make type ' . $attrs[
'type']);
1492 if ($this->currentComplexType &&
'array' == $this->complexTypes[$this->currentComplexType][
'phpType']) {
1493 $this->
xdebug(
'arrayType for unusual array is ' . $attrs[
'type']);
1494 $this->complexTypes[$this->currentComplexType][
'arrayType'] = $attrs[
'type'];
1496 $this->currentElement = $attrs[
'name'];
1497 $ename = $attrs[
'name'];
1498 } elseif (isset($attrs[
'ref'])) {
1499 $this->
xdebug(
'processing element as ref to ' . $attrs[
'ref']);
1500 $this->currentElement =
'ref to ' . $attrs[
'ref'];
1503 $type = $this->
CreateTypeName($this->currentComplexType .
'_' . $attrs[
'name']);
1504 $this->
xdebug(
'processing untyped element ' . $attrs[
'name'] .
' type ' . $type);
1505 $this->currentElement = $attrs[
'name'];
1506 $attrs[
'type'] = $this->schemaTargetNamespace .
':' . $type;
1507 $ename = $attrs[
'name'];
1509 if (isset($ename) && $this->currentComplexType) {
1510 $this->
xdebug(
"add element $ename to complexType $this->currentComplexType");
1511 $this->complexTypes[$this->currentComplexType][
'elements'][$ename] = $attrs;
1512 } elseif (!isset($attrs[
'ref'])) {
1513 $this->
xdebug(
"add element $ename to elements array");
1514 $this->elements[ $attrs[
'name'] ] = $attrs;
1515 $this->elements[ $attrs[
'name'] ][
'typeClass'] =
'element';
1519 $this->
xdebug(
'enumeration ' . $attrs[
'value']);
1520 if ($this->currentSimpleType) {
1521 $this->simpleTypes[$this->currentSimpleType][
'enumeration'][] = $attrs[
'value'];
1522 } elseif ($this->currentComplexType) {
1523 $this->complexTypes[$this->currentComplexType][
'enumeration'][] = $attrs[
'value'];
1527 $this->
xdebug(
'extension ' . $attrs[
'base']);
1528 if ($this->currentComplexType) {
1531 $this->complexTypes[$this->currentComplexType][
'extensionBase'] = $this->schemaTargetNamespace .
':' . $attrs[
'base'];
1533 $this->complexTypes[$this->currentComplexType][
'extensionBase'] = $attrs[
'base'];
1536 $this->
xdebug(
'no current complexType to set extensionBase');
1540 if (isset($attrs[
'schemaLocation'])) {
1541 $this->
xdebug(
'import namespace ' . $attrs[
'namespace'] .
' from ' . $attrs[
'schemaLocation']);
1542 $this->imports[$attrs[
'namespace']][] = [
'location' => $attrs[
'schemaLocation'],
'loaded' =>
false];
1544 $this->
xdebug(
'import namespace ' . $attrs[
'namespace']);
1545 $this->imports[$attrs[
'namespace']][] = [
'location' =>
'',
'loaded' =>
true];
1547 $this->namespaces[
'ns'.(count($this->namespaces)+1)] = $attrs[
'namespace'];
1552 if (isset($attrs[
'schemaLocation'])) {
1553 $this->
xdebug(
'include into namespace ' . $this->schemaTargetNamespace .
' from ' . $attrs[
'schemaLocation']);
1554 $this->imports[$this->schemaTargetNamespace][] = [
'location' => $attrs[
'schemaLocation'],
'loaded' =>
false];
1556 $this->
xdebug(
'ignoring invalid XML Schema construct: include without schemaLocation attribute');
1560 $this->
xdebug(
"do nothing for element $name");
1563 $this->
xdebug(
'restriction ' . $attrs[
'base']);
1564 if ($this->currentSimpleType) {
1565 $this->simpleTypes[$this->currentSimpleType][
'type'] = $attrs[
'base'];
1566 } elseif ($this->currentComplexType) {
1567 $this->complexTypes[$this->currentComplexType][
'restrictionBase'] = $attrs[
'base'];
1568 if (
':Array' == strstr($attrs[
'base'],
':')) {
1569 $this->complexTypes[$this->currentComplexType][
'phpType'] =
'array';
1574 $this->schemaInfo = $attrs;
1576 if (isset($attrs[
'targetNamespace'])) {
1577 $this->schemaTargetNamespace = $attrs[
'targetNamespace'];
1579 if (!isset($attrs[
'elementFormDefault'])) {
1580 $this->schemaInfo[
'elementFormDefault'] =
'unqualified';
1582 if (!isset($attrs[
'attributeFormDefault'])) {
1583 $this->schemaInfo[
'attributeFormDefault'] =
'unqualified';
1586 case 'simpleContent':
1587 if ($this->currentComplexType) {
1588 $this->complexTypes[$this->currentComplexType][
'simpleContent'] =
'true';
1590 $this->
xdebug(
"do nothing for element $name because there is no current complexType");
1594 array_push($this->simpleTypeStack, $this->currentSimpleType);
1595 if (isset($attrs[
'name'])) {
1596 $this->
xdebug(
'processing simpleType for name ' . $attrs[
'name']);
1597 $this->currentSimpleType = $attrs[
'name'];
1598 $this->simpleTypes[ $attrs[
'name'] ] = $attrs;
1599 $this->simpleTypes[ $attrs[
'name'] ][
'typeClass'] =
'simpleType';
1600 $this->simpleTypes[ $attrs[
'name'] ][
'phpType'] =
'scalar';
1602 $name = $this->
CreateTypeName($this->currentComplexType .
'_' . $this->currentElement);
1603 $this->
xdebug(
'processing unnamed simpleType for element ' . $this->currentElement .
' named ' . $name);
1604 $this->currentSimpleType = $name;
1606 $this->simpleTypes[$this->currentSimpleType] = $attrs;
1607 $this->simpleTypes[$this->currentSimpleType][
'phpType'] =
'scalar';
1611 $this->
xdebug(
"do nothing for element $name");
1614 $this->
xdebug(
"do not have any logic to process element $name");
1630 if (isset($this->depth_array[$this->depth])) {
1631 $pos = $this->depth_array[$this->depth];
1634 if ($prefix = $this->
getPrefix($name)) {
1641 if (
'complexType' == $name) {
1642 $this->
xdebug(
'done processing complexType ' . ($this->currentComplexType ?:
'(unknown)'));
1643 $this->
xdebug($this->
varDump($this->complexTypes[$this->currentComplexType]));
1644 $this->currentComplexType = array_pop($this->complexTypeStack);
1647 if (
'element' == $name) {
1648 $this->
xdebug(
'done processing element ' . ($this->currentElement ?:
'(unknown)'));
1649 $this->currentElement = array_pop($this->elementStack);
1651 if (
'simpleType' == $name) {
1652 $this->
xdebug(
'done processing simpleType ' . ($this->currentSimpleType ?:
'(unknown)'));
1653 $this->
xdebug($this->
varDump($this->simpleTypes[$this->currentSimpleType]));
1654 $this->currentSimpleType = array_pop($this->simpleTypeStack);
1667 $pos = $this->depth_array[$this->depth - 1];
1668 $this->message[$pos][
'cdata'] .= $data;
1681 if (count($this->imports) > 0) {
1682 foreach ($this->imports as $ns => $list) {
1683 foreach ($list as $ii) {
1684 if (
'' != $ii[
'location']) {
1685 $xml .=
" <$schemaPrefix:import location=\"" . $ii[
'location'] .
'" namespace="' . $ns .
"\" />\n";
1687 $xml .=
" <$schemaPrefix:import namespace=\"" . $ns .
"\" />\n";
1693 foreach ($this->complexTypes as $typeName => $attrs) {
1696 if (isset($attrs[
'elements']) && ((is_countable($attrs[
'elements']) ? count($attrs[
'elements']) : 0) > 0)) {
1697 foreach ($attrs[
'elements'] as $element => $eParts) {
1698 if (isset($eParts[
'ref'])) {
1699 $contentStr .=
" <$schemaPrefix:element ref=\"$element\"/>\n";
1701 $contentStr .=
" <$schemaPrefix:element name=\"$element\" type=\"" . $this->contractQName($eParts[
'type']) .
'"';
1702 foreach ($eParts as $aName => $aValue) {
1704 if (
'name' != $aName &&
'type' != $aName) {
1705 $contentStr .=
" $aName=\"$aValue\"";
1708 $contentStr .=
"/>\n";
1712 if (isset($attrs[
'compositor']) && (
'' != $attrs[
'compositor'])) {
1713 $contentStr =
" <$schemaPrefix:$attrs[compositor]>\n".$contentStr.
" </$schemaPrefix:$attrs[compositor]>\n";
1717 if (isset($attrs[
'attrs']) && ((is_countable($attrs[
'attrs']) ? count($attrs[
'attrs']) : 0) >= 1)) {
1718 foreach ($attrs[
'attrs'] as $attr => $aParts) {
1719 $contentStr .=
" <$schemaPrefix:attribute";
1720 foreach ($aParts as $a => $v) {
1721 if (
'ref' == $a ||
'type' == $a) {
1722 $contentStr .=
" $a=\"".$this->contractQName($v).
'"';
1723 } elseif (
'https://schemas.xmlsoap.org/wsdl/:arrayType' == $a) {
1724 $this->usedNamespaces[
'wsdl'] = $this->namespaces[
'wsdl'];
1725 $contentStr .=
' wsdl:arrayType="'.$this->contractQName($v).
'"';
1727 $contentStr .=
" $a=\"$v\"";
1730 $contentStr .=
"/>\n";
1734 if (isset($attrs[
'restrictionBase']) &&
'' != $attrs[
'restrictionBase']) {
1735 $contentStr =
" <$schemaPrefix:restriction base=\"".$this->contractQName($attrs[
'restrictionBase']).
"\">\n".$contentStr.
" </$schemaPrefix:restriction>\n";
1737 if ((isset($attrs[
'elements']) && (is_countable($attrs[
'elements']) ? count($attrs[
'elements']) : 0) > 0) || (isset($attrs[
'attrs']) && (is_countable($attrs[
'attrs']) ? count($attrs[
'attrs']) : 0) > 0)) {
1738 $contentStr =
" <$schemaPrefix:complexContent>\n".$contentStr.
" </$schemaPrefix:complexContent>\n";
1742 if (
'' != $contentStr) {
1743 $contentStr =
" <$schemaPrefix:complexType name=\"$typeName\">\n".$contentStr.
" </$schemaPrefix:complexType>\n";
1745 $contentStr =
" <$schemaPrefix:complexType name=\"$typeName\"/>\n";
1747 $xml .= $contentStr;
1750 if (isset($this->simpleTypes) && count($this->simpleTypes) > 0) {
1751 foreach ($this->simpleTypes as $typeName => $eParts) {
1752 $xml .=
" <$schemaPrefix:simpleType name=\"$typeName\">\n <$schemaPrefix:restriction base=\"".$this->contractQName($eParts[
'type']).
"\">\n";
1753 if (isset($eParts[
'enumeration'])) {
1754 foreach ($eParts[
'enumeration'] as $e) {
1755 $xml .=
" <$schemaPrefix:enumeration value=\"$e\"/>\n";
1758 $xml .=
" </$schemaPrefix:restriction>\n </$schemaPrefix:simpleType>";
1762 if (isset($this->elements) && count($this->elements) > 0) {
1763 foreach ($this->elements as $element => $eParts) {
1764 $xml .=
" <$schemaPrefix:element name=\"$element\" type=\"".$this->contractQName($eParts[
'type']).
"\"/>\n";
1768 if (isset($this->attributes) && count($this->attributes) > 0) {
1769 foreach ($this->attributes as $attr => $aParts) {
1770 $xml .=
" <$schemaPrefix:attribute name=\"$attr\" type=\"".$this->contractQName($aParts[
'type']).
"\"\n/>";
1775 foreach ($this->schemaInfo as $k => $v) {
1776 if (
'elementFormDefault' == $k ||
'attributeFormDefault' == $k) {
1777 $attr .=
" $k=\"$v\"";
1780 $el =
"<$schemaPrefix:schema$attr targetNamespace=\"$this->schemaTargetNamespace\"\n";
1781 foreach (array_diff($this->usedNamespaces, $this->enclosingNamespaces) as $nsp => $ns) {
1782 $el .=
" xmlns:$nsp=\"$ns\"";
1784 $xml = $el .
">\n".$xml.
"</$schemaPrefix:schema>\n";
1796 $this->
debug(
'<' . $this->schemaTargetNamespace .
'> '.$string);
1813 if (isset($this->typemap[$ns][$type])) {
1815 return $this->typemap[$ns][$type];
1816 } elseif (isset($this->complexTypes[$type])) {
1818 return $this->complexTypes[$type][
'phpType'];
1849 if (
'^' == substr($type, -1)) {
1851 $type = substr($type, 0, -1);
1856 if ((! $is_element) && isset($this->complexTypes[$type])) {
1857 $this->
xdebug(
"in getTypeDef, found complexType $type");
1858 return $this->complexTypes[$type];
1859 } elseif ((! $is_element) && isset($this->simpleTypes[$type])) {
1860 $this->
xdebug(
"in getTypeDef, found simpleType $type");
1861 if (!isset($this->simpleTypes[$type][
'phpType'])) {
1864 $uqType = substr($this->simpleTypes[$type][
'type'], strrpos($this->simpleTypes[$type][
'type'],
':') + 1);
1865 $ns = substr($this->simpleTypes[$type][
'type'], 0, strrpos($this->simpleTypes[$type][
'type'],
':'));
1868 $this->
xdebug(
"in getTypeDef, found type for simpleType $type:");
1870 if (isset($etype[
'phpType'])) {
1871 $this->simpleTypes[$type][
'phpType'] = $etype[
'phpType'];
1873 if (isset($etype[
'elements'])) {
1874 $this->simpleTypes[$type][
'elements'] = $etype[
'elements'];
1878 return $this->simpleTypes[$type];
1879 } elseif (isset($this->elements[$type])) {
1880 $this->
xdebug(
"in getTypeDef, found element $type");
1881 if (!isset($this->elements[$type][
'phpType'])) {
1883 $uqType = substr($this->elements[$type][
'type'], strrpos($this->elements[$type][
'type'],
':') + 1);
1884 $ns = substr($this->elements[$type][
'type'], 0, strrpos($this->elements[$type][
'type'],
':'));
1887 $this->
xdebug(
"in getTypeDef, found type for element $type:");
1889 if (isset($etype[
'phpType'])) {
1890 $this->elements[$type][
'phpType'] = $etype[
'phpType'];
1892 if (isset($etype[
'elements'])) {
1893 $this->elements[$type][
'elements'] = $etype[
'elements'];
1895 if (isset($etype[
'extensionBase'])) {
1896 $this->elements[$type][
'extensionBase'] = $etype[
'extensionBase'];
1898 } elseif (
'https://www.w3.org/2001/XMLSchema' == $ns) {
1899 $this->
xdebug(
"in getTypeDef, element $type is an XSD type");
1900 $this->elements[$type][
'phpType'] =
'scalar';
1903 return $this->elements[$type];
1904 } elseif (isset($this->attributes[$type])) {
1905 $this->
xdebug(
"in getTypeDef, found attribute $type");
1906 return $this->attributes[$type];
1907 } elseif (preg_match(
'/_ContainedType$/', $type)) {
1908 $this->
xdebug(
"in getTypeDef, have an untyped element $type");
1909 $typeDef[
'typeClass'] =
'simpleType';
1910 $typeDef[
'phpType'] =
'scalar';
1911 $typeDef[
'type'] =
'https://www.w3.org/2001/XMLSchema:string';
1914 $this->
xdebug(
"in getTypeDef, did not find $type");
1932 if (is_array($typeDef[
'attrs'])) {
1933 foreach ($typeDef[
'attrs'] as $attName => $data) {
1934 $str .=
" $attName=\"{type = ".$data[
'type'] .
'}"';
1937 $str .=
' xmlns="' . $this->schema[
'targetNamespace'] .
'"';
1938 if ((is_countable($typeDef[
'elements']) ? count($typeDef[
'elements']) : 0) > 0) {
1940 foreach ($typeDef[
'elements'] as $element => $eData) {
1944 } elseif (
'element' == $typeDef[
'typeClass']) {
1945 $str .=
"></$type>";
1970 if (
'struct' == $typeDef[
'phpType']) {
1971 $buffer .=
'<table>';
1972 foreach ($typeDef[
'elements'] as $child => $childDef) {
1974 <tr><td align='right'>$childDef[name] (type: ".$this->getLocalPart($childDef[
'type']).
"):</td>
1975 <td><input type='text' name='parameters[".$name.
"][$childDef[name]]'></td></tr>";
1977 $buffer .=
'</table>';
1979 } elseif (
'array' == $typeDef[
'phpType']) {
1980 $buffer .=
'<table>';
1981 for ($i=0;$i < 3; $i++) {
1983 <tr><td align='right'>array item (type: $typeDef[arrayType]):</td>
1984 <td><input type='text' name='parameters[".$name.
"][]'></td></tr>";
1986 $buffer .=
'</table>';
1989 $buffer .=
"<input type='text' name='parameters[$name]'>";
1992 $buffer .=
"<input type='text' name='parameters[$name]'>";
2033 public function addComplexType($name, $typeClass=
'complexType', $phpType=
'array', $compositor=
'', $restrictionBase=
'', $elements= [], $attrs= [], $arrayType=
'')
2035 $this->complexTypes[$name] = [
2037 'typeClass' => $typeClass,
2038 'phpType' => $phpType,
2039 'compositor'=> $compositor,
2040 'restrictionBase' => $restrictionBase,
2041 'elements' => $elements,
2043 'arrayType' => $arrayType
2046 $this->
xdebug(
"addComplexType $name:");
2062 public function addSimpleType($name, $restrictionBase=
'', $typeClass=
'simpleType', $phpType=
'scalar', $enumeration= [])
2064 $this->simpleTypes[$name] = [
2066 'typeClass' => $typeClass,
2067 'phpType' => $phpType,
2068 'type' => $restrictionBase,
2069 'enumeration' => $enumeration
2072 $this->
xdebug(
"addSimpleType $name:");
2085 if (! $this->
getPrefix($attrs[
'type'])) {
2086 $attrs[
'type'] = $this->schemaTargetNamespace .
':' . $attrs[
'type'];
2088 $this->elements[ $attrs[
'name'] ] = $attrs;
2089 $this->elements[ $attrs[
'name'] ][
'typeClass'] =
'element';
2091 $this->
xdebug(
'addElement ' . $attrs[
'name']);
2174 public function __construct($name=
'soapval', $type=
false, $value=-1, $element_ns=
false, $type_ns=
false, $attributes=
false)
2176 parent::__construct();
2177 $this->name = $name;
2178 $this->type = $type;
2179 $this->value = $value;
2180 $this->element_ns = $element_ns;
2181 $this->type_ns = $type_ns;
2182 $this->attributes = $attributes;
2194 return $this->
serialize_val($this->value, $this->name, $this->type, $this->element_ns, $this->type_ns, $this->attributes, $use,
true);
2205 return $this->value;
2229 public $digest_uri =
'';
2230 public $scheme =
'';
2234 public $request_method =
'POST';
2235 public $protocol_version =
'1.0';
2236 public $encoding =
'';
2237 public $outgoing_headers = [];
2238 public $incoming_headers = [];
2239 public $incoming_cookies = [];
2240 public $outgoing_payload =
'';
2241 public $incoming_payload =
'';
2242 public $response_status_line;
2243 public $useSOAPAction =
true;
2244 public $persistentConnection =
false;
2246 public $ch_options = [];
2247 public $use_curl =
false;
2248 public $proxy =
null;
2249 public $username =
'';
2250 public $password =
'';
2251 public $authtype =
'';
2252 public $digestRequest = [];
2253 public $certRequest = [];
2270 public function __construct($url, $curl_options =
null, $use_curl =
false)
2272 parent::__construct();
2273 $this->
debug(
"ctor url=$url use_curl=$use_curl curl_options:");
2276 if (is_array($curl_options)) {
2277 $this->ch_options = $curl_options;
2279 $this->use_curl = $use_curl;
2280 preg_match(
'/\$Revisio' .
'n: ([^ ]+)/', $this->revision, $rev);
2281 $this->
setHeader(
'User-Agent', $this->title.
'/'.$this->version.
' ('.$rev[1].
')');
2293 $this->
debug(
"setCurlOption option=$option, value=");
2295 curl_setopt($this->ch, $option, $value);
2307 $this->outgoing_headers[$name] = $value;
2308 $this->
debug(
"set header $name: $value");
2319 if (isset($this->outgoing_headers[$name])) {
2320 $this->
debug(
"unset header $name");
2321 unset($this->outgoing_headers[$name]);
2335 $u = parse_url($url);
2336 foreach ($u as $k => $v) {
2337 $this->
debug(
"parsed URL $k = $v");
2342 if (isset($u[
'query']) &&
'' != $u[
'query']) {
2343 $this->path .=
'?' . $u[
'query'];
2347 if (!isset($u[
'port'])) {
2348 if (
'https' == $u[
'scheme']) {
2355 $this->uri = $this->path;
2356 $this->digest_uri = $this->uri;
2359 if (!isset($u[
'port'])) {
2362 $this->
setHeader(
'Host', $this->host.
':'.$this->port);
2365 if (isset($u[
'user']) &&
'' != $u[
'user']) {
2366 $this->
setCredentials(urldecode($u[
'user']), isset($u[
'pass']) ? urldecode($u[
'pass']) :
'');
2378 if ($this->use_curl || (
'https' == $this->scheme) || (
'http' == $this->scheme &&
'ntlm' == $this->authtype) || (
'http' == $this->scheme && is_array($this->proxy) &&
'ntlm' == $this->proxy[
'authtype'])) {
2381 if ((
'http' == $this->scheme ||
'ssl' == $this->scheme) &&
'ntlm' != $this->authtype && (!is_array($this->proxy) ||
'ntlm' != $this->proxy[
'authtype'])) {
2395 public function connect($connection_timeout=0, $response_timeout=30)
2409 $this->
debug(
"connect connection_timeout $connection_timeout, response_timeout $response_timeout, scheme $this->scheme, host $this->host, port $this->port");
2411 if (!is_array($this->proxy)) {
2412 $host = $this->host;
2413 $port = $this->port;
2415 $host = $this->proxy[
'host'];
2416 $port = $this->proxy[
'port'];
2420 if ($this->persistentConnection && isset($this->fp) && is_resource($this->fp)) {
2421 if (!feof($this->fp)) {
2422 $this->
debug(
'Re-use persistent connection');
2426 $this->
debug(
'Closed persistent connection at EOF');
2430 if (
'ssl' == $this->scheme) {
2431 $host =
'ssl://' . $host;
2433 $this->
debug(
'calling fsockopen with host ' . $host .
' connection_timeout ' . $connection_timeout);
2436 if ($connection_timeout > 0) {
2437 $this->fp = @fsockopen($host, $this->port, $this->errno, $this->error_str, $connection_timeout);
2439 $this->fp = @fsockopen($host, $this->port, $this->errno, $this->error_str);
2444 $msg =
'Couldn\'t open socket connection to server ' . $this->url;
2446 $msg .=
', Error ('.$this->errno.
'): '.$this->error_str;
2448 $msg .=
' prior to connect(). This is often a problem looking up the host name.';
2456 $this->
debug(
'set response timeout to ' . $response_timeout);
2457 stream_set_timeout($this->fp, $response_timeout);
2459 $this->
debug(
'socket connected');
2461 } elseif (
'curl' == $this->
io_method()) {
2462 if (!extension_loaded(
'curl')) {
2464 $this->
setError(
'The PHP cURL Extension is required for HTTPS or NLTM. You will need to re-build or update your PHP to include cURL or change php.ini to load the PHP cURL extension.');
2468 if (defined(
'CURLOPT_CONNECTIONTIMEOUT')) {
2469 $CURLOPT_CONNECTIONTIMEOUT = CURLOPT_CONNECTIONTIMEOUT;
2471 $CURLOPT_CONNECTIONTIMEOUT = 78;
2473 if (defined(
'CURLOPT_HTTPAUTH')) {
2474 $CURLOPT_HTTPAUTH = CURLOPT_HTTPAUTH;
2476 $CURLOPT_HTTPAUTH = 107;
2478 if (defined(
'CURLOPT_PROXYAUTH')) {
2479 $CURLOPT_PROXYAUTH = CURLOPT_PROXYAUTH;
2481 $CURLOPT_PROXYAUTH = 111;
2483 if (defined(
'CURLAUTH_BASIC')) {
2484 $CURLAUTH_BASIC = CURLAUTH_BASIC;
2486 $CURLAUTH_BASIC = 1;
2488 if (defined(
'CURLAUTH_DIGEST')) {
2489 $CURLAUTH_DIGEST = CURLAUTH_DIGEST;
2491 $CURLAUTH_DIGEST = 2;
2493 if (defined(
'CURLAUTH_NTLM')) {
2494 $CURLAUTH_NTLM = CURLAUTH_NTLM;
2499 $this->
debug(
'connect using cURL');
2501 $this->ch = curl_init();
2503 $hostURL = (
'' != $this->port) ?
"$this->scheme://$this->host:$this->port" :
"$this->scheme://$this->host";
2505 $hostURL .= $this->path;
2508 if (ini_get(
'safe_mode') || ini_get(
'open_basedir')) {
2509 $this->
debug(
'safe_mode or open_basedir set, so do not set CURLOPT_FOLLOWLOCATION');
2510 $this->
debug(
'safe_mode = ');
2512 $this->
debug(
'open_basedir = ');
2527 if ($this->persistentConnection) {
2533 $this->persistentConnection =
false;
2534 $this->
setHeader(
'Connection',
'close');
2537 if (0 != $connection_timeout) {
2538 $this->
setCurlOption($CURLOPT_CONNECTIONTIMEOUT, $connection_timeout);
2540 if (0 != $response_timeout) {
2544 if (
'https' == $this->scheme) {
2545 $this->
debug(
'set cURL SSL verify options');
2554 if (
'certificate' == $this->authtype) {
2555 $this->
debug(
'set cURL certificate options');
2556 if (isset($this->certRequest[
'cainfofile'])) {
2557 $this->
setCurlOption(CURLOPT_CAINFO, $this->certRequest[
'cainfofile']);
2559 if (isset($this->certRequest[
'verifypeer'])) {
2560 $this->
setCurlOption(CURLOPT_SSL_VERIFYPEER, $this->certRequest[
'verifypeer']);
2564 if (isset($this->certRequest[
'verifyhost'])) {
2565 $this->
setCurlOption(CURLOPT_SSL_VERIFYHOST, $this->certRequest[
'verifyhost']);
2569 if (isset($this->certRequest[
'sslcertfile'])) {
2570 $this->
setCurlOption(CURLOPT_SSLCERT, $this->certRequest[
'sslcertfile']);
2572 if (isset($this->certRequest[
'sslkeyfile'])) {
2573 $this->
setCurlOption(CURLOPT_SSLKEY, $this->certRequest[
'sslkeyfile']);
2575 if (isset($this->certRequest[
'passphrase'])) {
2576 $this->
setCurlOption(CURLOPT_SSLKEYPASSWD, $this->certRequest[
'passphrase']);
2578 if (isset($this->certRequest[
'certpassword'])) {
2579 $this->
setCurlOption(CURLOPT_SSLCERTPASSWD, $this->certRequest[
'certpassword']);
2583 if ($this->authtype && (
'certificate' != $this->authtype)) {
2584 if ($this->username) {
2585 $this->
debug(
'set cURL username/password');
2586 $this->
setCurlOption(CURLOPT_USERPWD,
"$this->username:$this->password");
2588 if (
'basic' == $this->authtype) {
2589 $this->
debug(
'set cURL for Basic authentication');
2592 if (
'digest' == $this->authtype) {
2593 $this->
debug(
'set cURL for digest authentication');
2596 if (
'ntlm' == $this->authtype) {
2597 $this->
debug(
'set cURL for NTLM authentication');
2601 if (is_array($this->proxy)) {
2602 $this->
debug(
'set cURL proxy options');
2603 if (
'' != $this->proxy[
'port']) {
2604 $this->
setCurlOption(CURLOPT_PROXY, $this->proxy[
'host'].
':'.$this->proxy[
'port']);
2608 if ($this->proxy[
'username'] || $this->proxy[
'password']) {
2609 $this->
debug(
'set cURL proxy authentication options');
2610 $this->
setCurlOption(CURLOPT_PROXYUSERPWD, $this->proxy[
'username'].
':'.$this->proxy[
'password']);
2611 if (
'basic' == $this->proxy[
'authtype']) {
2614 if (
'ntlm' == $this->proxy[
'authtype']) {
2619 $this->
debug(
'cURL connection set up');
2622 $this->
setError(
'Unknown scheme ' . $this->scheme);
2623 $this->
debug(
'Unknown scheme ' . $this->scheme);
2638 public function send($data, $timeout=0, $response_timeout=30, $cookies=
null)
2640 $this->
debug(
'entered send() with data of length: '.strlen($data));
2642 $this->tryagain =
true;
2644 while ($this->tryagain) {
2645 $this->tryagain =
false;
2648 if (!$this->
connect($timeout, $response_timeout)) {
2660 $this->
setError(
"Too many tries to get an OK response ($this->response_status_line)");
2663 $this->
debug(
'end of send()');
2679 public function sendHTTPS($data, $timeout=0, $response_timeout=30, $cookies)
2681 return $this->
send($data, $timeout, $response_timeout, $cookies);
2694 public function setCredentials($username, $password, $authtype =
'basic', $digestRequest = [], $certRequest = [])
2696 $this->
debug(
"setCredentials username=$username authtype=$authtype digestRequest=");
2698 $this->
debug(
'certRequest=');
2701 if (
'basic' == $authtype) {
2702 $this->
setHeader(
'Authorization',
'Basic '.base64_encode(str_replace(
':',
'', $username).
':'.$password));
2703 } elseif (
'digest' == $authtype) {
2704 if (isset($digestRequest[
'nonce'])) {
2705 $digestRequest[
'nc'] = isset($digestRequest[
'nc']) ? $digestRequest[
'nc']++ : 1;
2710 $A1 = $username.
':' . ($digestRequest[
'realm'] ??
'') .
':' . $password;
2716 $A2 = $this->request_method .
':' . $this->digest_uri;
2732 $unhashedDigest =
'';
2733 $nonce = $digestRequest[
'nonce'] ??
'';
2735 if (
'' != $digestRequest[
'qop']) {
2736 $unhashedDigest = $HA1 .
':' . $nonce .
':' . sprintf(
'%08d', $digestRequest[
'nc']) .
':' . $cnonce .
':' . $digestRequest[
'qop'] .
':' . $HA2;
2738 $unhashedDigest = $HA1 .
':' . $nonce .
':' . $HA2;
2741 $hashedDigest = md5($unhashedDigest);
2744 if (isset($digestRequest[
'opaque'])) {
2745 $opaque =
', opaque="' . $digestRequest[
'opaque'] .
'"';
2748 $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 .
'"');
2750 } elseif (
'certificate' == $authtype) {
2751 $this->certRequest = $certRequest;
2752 $this->
debug(
'Authorization header not set for certificate');
2753 } elseif (
'ntlm' == $authtype) {
2755 $this->
debug(
'Authorization header not set for ntlm');
2757 $this->username = $username;
2758 $this->password = $password;
2759 $this->authtype = $authtype;
2760 $this->digestRequest = $digestRequest;
2771 $this->
setHeader(
'SOAPAction',
'"' . $soapaction .
'"');
2782 if (function_exists(
'gzdeflate')) {
2783 $this->protocol_version =
'1.1';
2784 $this->
setHeader(
'Accept-Encoding', $enc);
2785 if (!isset($this->outgoing_headers[
'Connection'])) {
2786 $this->
setHeader(
'Connection',
'close');
2787 $this->persistentConnection =
false;
2791 $this->encoding = $enc;
2805 public function setProxy($proxyhost, $proxyport, $proxyusername =
'', $proxypassword =
'', $proxyauthtype =
'basic')
2809 'host' => $proxyhost,
2810 'port' => $proxyport,
2811 'username' => $proxyusername,
2812 'password' => $proxypassword,
2813 'authtype' => $proxyauthtype
2815 if (
'' != $proxyusername &&
'' != $proxypassword && $proxyauthtype =
'basic') {
2816 $this->
setHeader(
'Proxy-Authorization',
' Basic '.base64_encode($proxyusername.
':'.$proxypassword));
2819 $this->
debug(
'remove proxy');
2844 'HTTP/1.0 200 Connection established'
2846 foreach ($skipHeaders as $hd) {
2847 $prefix = substr($data, 0, strlen($hd));
2848 if ($prefix == $hd) {
2875 $chunkend = strpos($buffer, $lb);
2876 if (
false == $chunkend) {
2877 $this->
debug(
'no linebreak found in decodeChunked');
2880 $temp = substr($buffer, 0, $chunkend);
2881 $chunk_size = hexdec(trim($temp));
2882 $chunkstart = $chunkend + strlen($lb);
2884 while ($chunk_size > 0) {
2885 $this->
debug(
"chunkstart: $chunkstart chunk_size: $chunk_size");
2886 $chunkend = strpos($buffer, $lb, $chunkstart + $chunk_size);
2889 if (
false == $chunkend) {
2890 $chunk = substr($buffer, $chunkstart);
2893 $length += strlen($chunk);
2898 $chunk = substr($buffer, $chunkstart, $chunkend-$chunkstart);
2902 $length += strlen($chunk);
2904 $chunkstart = $chunkend + strlen($lb);
2906 $chunkend = strpos($buffer, $lb, $chunkstart) + strlen($lb);
2907 if (
false == $chunkend) {
2910 $temp = substr($buffer, $chunkstart, $chunkend-$chunkstart);
2911 $chunk_size = hexdec(trim($temp));
2912 $chunkstart = $chunkend;
2932 if (
'GET' != $this->request_method) {
2933 $this->
setHeader(
'Content-Length', strlen($data));
2942 $req =
"$this->request_method $uri HTTP/$this->protocol_version";
2943 $this->
debug(
"HTTP request: $req");
2944 $this->outgoing_payload =
"$req\r\n";
2947 foreach ($this->outgoing_headers as $k => $v) {
2949 $this->
debug(
"HTTP header: $hdr");
2950 $this->outgoing_payload .=
"$hdr\r\n";
2954 if (
'' != $cookie_str) {
2955 $hdr =
'Cookie: '.$cookie_str;
2956 $this->
debug(
"HTTP header: $hdr");
2957 $this->outgoing_payload .=
"$hdr\r\n";
2961 $this->outgoing_payload .=
"\r\n";
2964 $this->outgoing_payload .= $data;
2978 $cookie_str = $this->
getCookiesForRequest($cookies, ((
'ssl' == $this->scheme) || (
'https' == $this->scheme)));
2985 if (!fwrite($this->fp, $this->outgoing_payload, strlen($this->outgoing_payload))) {
2986 $this->
setError(
'couldn\'t write message data to socket');
2987 $this->
debug(
'couldn\'t write message data to socket');
2990 $this->
debug(
'wrote data to socket, length = ' . strlen($this->outgoing_payload));
2992 } elseif (
'curl' == $this->
io_method()) {
2999 foreach ($this->outgoing_headers as $k => $v) {
3000 if (
'Connection' == $k ||
'Content-Length' == $k ||
'Host' == $k ||
'Authorization' == $k ||
'Proxy-Authorization' == $k) {
3001 $this->
debug(
"Skip cURL header $k: $v");
3003 $curl_headers[] =
"$k: $v";
3006 if (
'' != $cookie_str) {
3007 $curl_headers[] =
'Cookie: ' . $cookie_str;
3010 $this->
debug(
'set cURL HTTP headers');
3011 if (
'POST' == $this->request_method) {
3014 $this->
debug(
'set cURL POST data');
3018 foreach ($this->ch_options as $key => $val) {
3022 $this->
debug(
'set cURL payload');
3037 $header_data =
null;
3038 $this->incoming_payload =
'';
3043 while (!isset($lb)) {
3046 if (feof($this->fp)) {
3047 $this->incoming_payload = $data;
3048 $this->
debug(
'found no headers before EOF after length ' . strlen($data));
3049 $this->
debug(
"received before EOF:\n" . $data);
3050 $this->
setError(
'server failed to send headers');
3054 $tmp = fgets($this->fp, 256);
3055 $tmplen = strlen($tmp);
3056 $this->
debug(
"read line of $tmplen bytes: " . trim($tmp));
3059 $this->incoming_payload = $data;
3060 $this->
debug(
'socket read of headers timed out after length ' . strlen($data));
3061 $this->
debug(
'read before timeout: ' . $data);
3062 $this->
setError(
'socket read of headers timed out');
3067 $pos = strpos($data,
"\r\n\r\n");
3071 $pos = strpos($data,
"\n\n");
3077 if (isset($lb) && preg_match(
'/^HTTP\/1.1 100/', $data)) {
3083 $this->incoming_payload .= $data;
3084 $this->
debug(
'found end of headers after length ' . strlen($data));
3086 $header_data = trim(substr($data, 0, $pos));
3087 $header_array = explode($lb, $header_data);
3088 $this->incoming_headers = [];
3089 $this->incoming_cookies = [];
3090 foreach ($header_array as $header_line) {
3091 $arr = explode(
':', $header_line, 2);
3092 if (count($arr) > 1) {
3093 $header_name = strtolower(trim($arr[0]));
3094 $this->incoming_headers[$header_name] = trim($arr[1]);
3095 if (
'set-cookie' == $header_name) {
3099 $this->incoming_cookies[] = $cookie;
3100 $this->
debug(
'found cookie: ' . $cookie[
'name'] .
' = ' . $cookie[
'value']);
3102 $this->
debug(
'did not find cookie in ' . trim($arr[1]));
3105 } elseif (isset($header_name)) {
3107 $this->incoming_headers[$header_name] .= $lb .
' ' . $header_line;
3112 if (isset($this->incoming_headers[
'transfer-encoding']) &&
'chunked' == strtolower($this->incoming_headers[
'transfer-encoding'])) {
3113 $content_length = 2_147_483_647;
3115 $this->
debug(
'want to read chunked content');
3116 } elseif (isset($this->incoming_headers[
'content-length'])) {
3117 $content_length = $this->incoming_headers[
'content-length'];
3119 $this->
debug(
"want to read content of length $content_length");
3121 $content_length = 2_147_483_647;
3123 $this->
debug(
'want to read content to EOF');
3128 $tmp = fgets($this->fp, 256);
3129 $tmplen = strlen($tmp);
3130 $this->
debug(
"read chunk line of $tmplen bytes");
3132 $this->incoming_payload = $data;
3133 $this->
debug(
'socket read of chunk length timed out after length ' . strlen($data));
3134 $this->
debug(
"read before timeout:\n" . $data);
3135 $this->
setError(
'socket read of chunk length timed out');
3138 $content_length = hexdec(trim($tmp));
3139 $this->
debug(
"chunk length $content_length");
3142 while (($strlen < $content_length) && (!feof($this->fp))) {
3143 $readlen = min(8192, $content_length - $strlen);
3144 $tmp = fread($this->fp, $readlen);
3145 $tmplen = strlen($tmp);
3146 $this->
debug(
"read buffer of $tmplen bytes");
3147 if ((0 == $tmplen) && (!feof($this->fp))) {
3148 $this->incoming_payload = $data;
3149 $this->
debug(
'socket read of body timed out after length ' . strlen($data));
3150 $this->
debug(
"read before timeout:\n" . $data);
3151 $this->
setError(
'socket read of body timed out');
3157 if ($chunked && ($content_length > 0)) {
3158 $tmp = fgets($this->fp, 256);
3159 $tmplen = strlen($tmp);
3160 $this->
debug(
"read chunk terminator of $tmplen bytes");
3162 $this->incoming_payload = $data;
3163 $this->
debug(
'socket read of chunk terminator timed out after length ' . strlen($data));
3164 $this->
debug(
"read before timeout:\n" . $data);
3165 $this->
setError(
'socket read of chunk terminator timed out');
3169 }
while ($chunked && ($content_length > 0) && (!feof($this->fp)));
3170 if (feof($this->fp)) {
3171 $this->
debug(
'read to EOF');
3173 $this->
debug(
'read body of length ' . strlen($data));
3174 $this->incoming_payload .= $data;
3175 $this->
debug(
'received a total of '.strlen($this->incoming_payload).
' bytes of data from server');
3179 (isset($this->incoming_headers[
'connection']) &&
'close' == strtolower($this->incoming_headers[
'connection'])) ||
3180 (! $this->persistentConnection) || feof($this->fp)) {
3183 $this->
debug(
'closed socket');
3187 if (
'' == $this->incoming_payload) {
3188 $this->
setError(
'no response from server');
3202 } elseif (
'curl' == $this->
io_method()) {
3204 $this->
debug(
'send and receive with cURL');
3205 $this->incoming_payload = curl_exec($this->ch);
3206 $data = $this->incoming_payload;
3208 $cErr = curl_error($this->ch);
3210 $err =
'cURL ERROR: '.curl_errno($this->ch).
': '.$cErr.
'<br>';
3212 foreach (curl_getinfo($this->ch) as $k => $v) {
3213 $err .=
"$k: $v<br>";
3217 curl_close($this->ch);
3225 $this->
debug(
'No cURL error, closing cURL');
3226 curl_close($this->ch);
3231 $this->
debug(
'Found HTTP header to skip');
3232 if ($pos = strpos($data,
"\r\n\r\n")) {
3233 $data = ltrim(substr($data, $pos));
3234 } elseif ($pos = strpos($data,
"\n\n")) {
3235 $data = ltrim(substr($data, $pos));
3242 while (preg_match(
'/^HTTP\/1.1 100/', $data)) {
3243 if ($pos = strpos($data,
"\r\n\r\n")) {
3244 $data = ltrim(substr($data, $pos));
3245 } elseif ($pos = strpos($data,
"\n\n")) {
3246 $data = ltrim(substr($data, $pos));
3252 if ($pos = strpos($data,
"\r\n\r\n")) {
3254 } elseif ($pos = strpos($data,
"\n\n")) {
3257 $this->
debug(
'no proper separation of headers and document');
3258 $this->
setError(
'no proper separation of headers and document');
3261 $header_data = trim(substr($data, 0, $pos));
3262 $header_array = explode($lb, $header_data);
3263 $data = ltrim(substr($data, $pos));
3264 $this->
debug(
'found proper separation of headers and document');
3265 $this->
debug(
'cleaned data, stringlen: '.strlen($data));
3267 foreach ($header_array as $header_line) {
3268 $arr = explode(
':', $header_line, 2);
3269 if (count($arr) > 1) {
3270 $header_name = strtolower(trim($arr[0]));
3271 $this->incoming_headers[$header_name] = trim($arr[1]);
3272 if (
'set-cookie' == $header_name) {
3276 $this->incoming_cookies[] = $cookie;
3277 $this->
debug(
'found cookie: ' . $cookie[
'name'] .
' = ' . $cookie[
'value']);
3279 $this->
debug(
'did not find cookie in ' . trim($arr[1]));
3282 } elseif (isset($header_name)) {
3284 $this->incoming_headers[$header_name] .= $lb .
' ' . $header_line;
3289 $this->response_status_line = $header_array[0];
3290 $arr = explode(
' ', $this->response_status_line, 3);
3291 $http_version = $arr[0];
3292 $http_status = (int)$arr[1];
3293 $http_reason = count($arr) > 2 ? $arr[2] :
'';
3296 if (isset($this->incoming_headers[
'location']) && (301 == $http_status || 302 == $http_status)) {
3297 $this->
debug(
"Got $http_status $http_reason with Location: " . $this->incoming_headers[
'location']);
3298 $this->
setURL($this->incoming_headers[
'location']);
3299 $this->tryagain =
true;
3304 if (isset($this->incoming_headers[
'www-authenticate']) && 401 == $http_status) {
3305 $this->
debug(
"Got 401 $http_reason with WWW-Authenticate: " . $this->incoming_headers[
'www-authenticate']);
3306 if (strstr($this->incoming_headers[
'www-authenticate'],
'Digest ')) {
3307 $this->
debug(
'Server wants digest authentication');
3309 $digestString = str_replace(
'Digest ',
'', $this->incoming_headers[
'www-authenticate']);
3312 $digestElements = explode(
',', $digestString);
3313 foreach ($digestElements as $val) {
3314 $tempElement = explode(
'=', trim($val), 2);
3315 $digestRequest[$tempElement[0]] = str_replace(
'"',
'', $tempElement[1]);
3319 if (isset($digestRequest[
'nonce'])) {
3320 $this->
setCredentials($this->username, $this->password,
'digest', $digestRequest);
3321 $this->tryagain =
true;
3325 $this->
debug(
'HTTP authentication failed');
3326 $this->
setError(
'HTTP authentication failed');
3331 ($http_status >= 300 && $http_status <= 307) ||
3332 ($http_status >= 400 && $http_status <= 417) ||
3333 ($http_status >= 501 && $http_status <= 505)
3335 $this->
setError(
"Unsupported HTTP response status $http_status $http_reason (soapclient->response has contents of the response)");
3340 if (isset($this->incoming_headers[
'content-encoding']) &&
'' != $this->incoming_headers[
'content-encoding']) {
3341 if (
'deflate' == strtolower($this->incoming_headers[
'content-encoding']) ||
'gzip' == strtolower($this->incoming_headers[
'content-encoding'])) {
3343 if (function_exists(
'gzinflate')) {
3347 $this->
debug(
'The gzinflate function exists');
3348 $datalen = strlen($data);
3349 if (
'deflate' == $this->incoming_headers[
'content-encoding']) {
3350 if ($degzdata = @gzinflate($data)) {
3352 $this->
debug(
'The payload has been inflated to ' . strlen($data) .
' bytes');
3353 if (strlen($data) < $datalen) {
3355 $this->
debug(
'The inflated payload is smaller than the gzipped one; try again');
3356 if ($degzdata = @gzinflate($data)) {
3358 $this->
debug(
'The payload has been inflated again to ' . strlen($data) .
' bytes');
3362 $this->
debug(
'Error using gzinflate to inflate the payload');
3363 $this->
setError(
'Error using gzinflate to inflate the payload');
3365 } elseif (
'gzip' == $this->incoming_headers[
'content-encoding']) {
3366 if ($degzdata = @gzinflate(substr($data, 10))) {
3368 $this->
debug(
'The payload has been un-gzipped to ' . strlen($data) .
' bytes');
3369 if (strlen($data) < $datalen) {
3371 $this->
debug(
'The un-gzipped payload is smaller than the gzipped one; try again');
3372 if ($degzdata = @gzinflate(substr($data, 10))) {
3374 $this->
debug(
'The payload has been un-gzipped again to ' . strlen($data) .
' bytes');
3378 $this->
debug(
'Error using gzinflate to un-gzip the payload');
3379 $this->
setError(
'Error using gzinflate to un-gzip the payload');
3385 $this->incoming_payload = $header_data.$lb.$lb.$data;
3387 $this->
debug(
'The server sent compressed data. Your php install must have the Zlib extension compiled in to support this.');
3388 $this->
setError(
'The server sent compressed data. Your php install must have the Zlib extension compiled in to support this.');
3391 $this->
debug(
'Unsupported Content-Encoding ' . $this->incoming_headers[
'content-encoding']);
3392 $this->
setError(
'Unsupported Content-Encoding ' . $this->incoming_headers[
'content-encoding']);
3395 $this->
debug(
'No Content-Encoding header');
3398 if (0 == strlen($data)) {
3399 $this->
debug(
'no data after headers!');
3400 $this->
setError(
'no data present after HTTP headers');
3416 $this->
setHeader(
'Content-Type', $type . ($charset ?
'; charset=' . $charset :
''));
3427 if (isset($this->outgoing_headers[
'Accept-Encoding'])) {
3430 $this->protocol_version =
'1.1';
3431 $this->persistentConnection =
true;
3432 $this->
setHeader(
'Connection',
'Keep-Alive');
3448 $cookie_str = str_replace(
'; ',
';', $cookie_str) .
';';
3449 $data = preg_split(
'/;/', $cookie_str);
3450 $value_str = $data[0];
3452 $cookie_param =
'domain=';
3453 $start = strpos($cookie_str, $cookie_param);
3455 $domain = substr($cookie_str, $start + strlen($cookie_param));
3456 $domain = substr($domain, 0, strpos($domain,
';'));
3461 $cookie_param =
'expires=';
3462 $start = strpos($cookie_str, $cookie_param);
3464 $expires = substr($cookie_str, $start + strlen($cookie_param));
3465 $expires = substr($expires, 0, strpos($expires,
';'));
3470 $cookie_param =
'path=';
3471 $start = strpos($cookie_str, $cookie_param);
3473 $path = substr($cookie_str, $start + strlen($cookie_param));
3474 $path = substr($path, 0, strpos($path,
';'));
3479 $cookie_param =
';secure;';
3480 if (
false !== strpos($cookie_str, $cookie_param)) {
3486 $sep_pos = strpos($value_str,
'=');
3489 $name = substr($value_str, 0, $sep_pos);
3490 $value = substr($value_str, $sep_pos + 1);
3494 'domain' => $domain,
3496 'expires' => $expires,
3515 if ((
null !== $cookies) && (is_array($cookies))) {
3516 foreach ($cookies as $cookie) {
3517 if (! is_array($cookie)) {
3520 $this->
debug(
'check cookie for validity: ' . $cookie[
'name'] .
'=' . $cookie[
'value']);
3521 if ((isset($cookie[
'expires'])) && (! empty($cookie[
'expires']))) {
3522 if (strtotime($cookie[
'expires']) <= time()) {
3523 $this->
debug(
'cookie has expired');
3527 if ((isset($cookie[
'domain'])) && (! empty($cookie[
'domain']))) {
3528 $domain = preg_quote($cookie[
'domain']);
3529 if (! preg_match(
"'.*$domain$'i", $this->host)) {
3530 $this->
debug(
'cookie has different domain');
3534 if ((isset($cookie[
'path'])) && (! empty($cookie[
'path']))) {
3535 $path = preg_quote($cookie[
'path']);
3536 if (! preg_match(
"'^$path.*'i", $this->path)) {
3537 $this->
debug(
'cookie is for a different path');
3541 if ((! $secure) && (isset($cookie[
'secure'])) && ($cookie[
'secure'])) {
3542 $this->
debug(
'cookie is secure, transport is not');
3545 $cookie_str .= $cookie[
'name'] .
'=' . $cookie[
'value'] .
'; ';
3546 $this->
debug(
'add cookie to Cookie-String: ' . $cookie[
'name'] .
'=' . $cookie[
'value']);
3574 public $headers = [];
3580 public $request =
'';
3586 public $requestHeaders =
'';
3592 public $requestHeader =
null;
3598 public $document =
'';
3604 public $requestSOAP =
'';
3610 public $methodURI =
'';
3616 public $methodname =
'';
3622 public $methodparams = [];
3628 public $SOAPAction =
'';
3634 public $xml_encoding =
'';
3640 public $decode_utf8 =
true;
3647 public $outgoing_headers = [];
3653 public $response =
'';
3659 public $responseHeaders =
'';
3665 public $responseSOAP =
'';
3671 public $methodreturn =
false;
3677 public $methodreturnisliteralxml =
false;
3683 public $fault =
false;
3689 public $result =
'successful';
3697 public $operations = [];
3703 public $wsdl =
false;
3709 public $externalWSDLURL =
false;
3715 public $debug_flag =
false;
3727 parent::__construct();
3732 if (isset($_SERVER)) {
3733 $this->
debug(
'_SERVER is defined:');
3735 } elseif (isset($_SERVER)) {
3736 $this->
debug(
'HTTP_SERVER_VARS is defined:');
3739 $this->
debug(
'Neither _SERVER nor HTTP_SERVER_VARS is defined.');
3742 if (isset($debug)) {
3743 $this->
debug(
"In nusoap_server, set debug_flag=$debug based on global flag");
3744 $this->debug_flag = $debug;
3745 } elseif (isset($_SERVER[
'QUERY_STRING'])) {
3746 $qs = explode(
'&', $_SERVER[
'QUERY_STRING']);
3747 foreach ($qs as $v) {
3748 if (
'debug=' == substr($v, 0, 6)) {
3749 $this->
debug(
'In nusoap_server, set debug_flag=' . substr($v, 6) .
' based on query string #1');
3750 $this->debug_flag = substr($v, 6);
3753 } elseif (isset($_SERVER[
'QUERY_STRING'])) {
3754 $qs = explode(
'&', $_SERVER[
'QUERY_STRING']);
3755 foreach ($qs as $v) {
3756 if (
'debug=' == substr($v, 0, 6)) {
3757 $this->
debug(
'In nusoap_server, set debug_flag=' . substr($v, 6) .
' based on query string #2');
3758 $this->debug_flag = substr($v, 6);
3765 $this->
debug(
'In nusoap_server, WSDL is specified');
3766 if (is_object($wsdl) && (
'wsdl' == get_class($wsdl))) {
3767 $this->
wsdl = $wsdl;
3768 $this->externalWSDLURL = $this->
wsdl->wsdl;
3769 $this->
debug(
'Use existing wsdl instance from ' . $this->externalWSDLURL);
3771 $this->
debug(
'Create wsdl from ' . $wsdl);
3773 $this->externalWSDLURL = $wsdl;
3778 die(
'WSDL ERROR: '.$err);
3793 if (isset($_SERVER[
'REQUEST_METHOD'])) {
3794 $rm = $_SERVER[
'REQUEST_METHOD'];
3795 } elseif (isset($_SERVER[
'REQUEST_METHOD'])) {
3796 $rm = $_SERVER[
'REQUEST_METHOD'];
3801 if (isset($_SERVER[
'QUERY_STRING'])) {
3802 $qs = $_SERVER[
'QUERY_STRING'];
3803 } elseif (isset($_SERVER[
'QUERY_STRING'])) {
3804 $qs = $_SERVER[
'QUERY_STRING'];
3808 $this->
debug(
"In service, request method=$rm query string=$qs strlen(\$data)=" . strlen($data));
3810 if (
'POST' == $rm) {
3811 $this->
debug(
'In service, invoke the request');
3813 if (! $this->
fault) {
3816 if (! $this->
fault) {
3820 } elseif (preg_match(
'/wsdl/', $qs)) {
3821 $this->
debug(
'In service, this is a request for WSDL');
3822 if ($this->externalWSDLURL) {
3823 if (
false !== strpos($this->externalWSDLURL,
'https://')) {
3824 $this->
debug(
'In service, re-direct for WSDL');
3825 header(
'Location: '.$this->externalWSDLURL);
3827 $this->
debug(
'In service, use file passthru for WSDL');
3828 header(
"Content-Type: text/xml\r\n");
3829 $pos = strpos($this->externalWSDLURL,
'file://');
3830 if (
false === $pos) {
3831 $filename = $this->externalWSDLURL;
3833 $filename = substr($this->externalWSDLURL, $pos + 7);
3835 $fp = fopen($this->externalWSDLURL,
'r');
3838 } elseif ($this->
wsdl) {
3839 $this->
debug(
'In service, serialize WSDL');
3840 header(
"Content-Type: text/xml; charset=ISO-8859-1\r\n");
3842 if ($this->debug_flag) {
3843 $this->
debug(
'wsdl:');
3848 $this->
debug(
'In service, there is no WSDL');
3849 header(
"Content-Type: text/html; charset=ISO-8859-1\r\n");
3850 print
'This service does not provide WSDL';
3852 } elseif ($this->
wsdl) {
3853 $this->
debug(
'In service, return Web description');
3856 $this->
debug(
'In service, no Web description');
3857 header(
"Content-Type: text/html; charset=ISO-8859-1\r\n");
3858 print
'This service does not provide a Web description';
3878 $this->request =
'';
3879 $this->SOAPAction =
'';
3880 if (function_exists(
'getallheaders')) {
3881 $this->
debug(
'In parse_http_headers, use getallheaders');
3882 $headers = getallheaders();
3883 foreach ($headers as $k=>$v) {
3884 $k = strtolower($k);
3885 $this->headers[$k] = $v;
3886 $this->request .=
"$k: $v\r\n";
3887 $this->
debug(
"$k: $v");
3890 if (isset($this->headers[
'soapaction'])) {
3891 $this->SOAPAction = str_replace(
'"',
'', $this->headers[
'soapaction']);
3894 if (isset($this->headers[
'content-type']) && strpos($this->headers[
'content-type'],
'=')) {
3895 $enc = str_replace(
'"',
'', substr(strstr($this->headers[
'content-type'],
'='), 1));
3896 if (preg_match(
'/^(ISO-8859-1|US-ASCII|UTF-8)$/i', $enc)) {
3897 $this->xml_encoding = strtoupper($enc);
3899 $this->xml_encoding =
'US-ASCII';
3903 $this->xml_encoding =
'ISO-8859-1';
3905 } elseif (isset($_SERVER) && is_array($_SERVER)) {
3906 $this->
debug(
'In parse_http_headers, use _SERVER');
3907 foreach ($_SERVER as $k => $v) {
3908 if (
'HTTP_' == substr($k, 0, 5)) {
3909 $k = str_replace(
' ',
'-', strtolower(str_replace(
'_',
' ', substr($k, 5))));
3911 $k = str_replace(
' ',
'-', strtolower(str_replace(
'_',
' ', $k)));
3913 if (
'soapaction' == $k) {
3916 $v = str_replace(
'"',
'', $v);
3917 $v = str_replace(
'\\',
'', $v);
3918 $this->SOAPAction = $v;
3919 } elseif (
'content-type' == $k) {
3921 if (strpos($v,
'=')) {
3922 $enc = substr(strstr($v,
'='), 1);
3923 $enc = str_replace(
'"',
'', $enc);
3924 $enc = str_replace(
'\\',
'', $enc);
3925 if (preg_match(
'/^(ISO-8859-1|US-ASCII|UTF-8)$/i', $enc)) {
3926 $this->xml_encoding = strtoupper($enc);
3928 $this->xml_encoding =
'US-ASCII';
3932 $this->xml_encoding =
'ISO-8859-1';
3935 $this->headers[$k] = $v;
3936 $this->request .=
"$k: $v\r\n";
3937 $this->
debug(
"$k: $v");
3939 } elseif (is_array($_SERVER)) {
3940 $this->
debug(
'In parse_http_headers, use HTTP_SERVER_VARS');
3941 foreach ($_SERVER as $k => $v) {
3942 if (
'HTTP_' == substr($k, 0, 5)) {
3943 $k = str_replace(
' ',
'-', strtolower(str_replace(
'_',
' ', substr($k, 5))));
3944 $k = strtolower(substr($k, 5));
3946 $k = str_replace(
' ',
'-', strtolower(str_replace(
'_',
' ', $k)));
3947 $k = strtolower($k);
3949 if (
'soapaction' == $k) {
3952 $v = str_replace(
'"',
'', $v);
3953 $v = str_replace(
'\\',
'', $v);
3954 $this->SOAPAction = $v;
3955 } elseif (
'content-type' == $k) {
3957 if (strpos($v,
'=')) {
3958 $enc = substr(strstr($v,
'='), 1);
3959 $enc = str_replace(
'"',
'', $enc);
3960 $enc = str_replace(
'\\',
'', $enc);
3961 if (preg_match(
'/^(ISO-8859-1|US-ASCII|UTF-8)$/i', $enc)) {
3962 $this->xml_encoding = strtoupper($enc);
3964 $this->xml_encoding =
'US-ASCII';
3968 $this->xml_encoding =
'ISO-8859-1';
3971 $this->headers[$k] = $v;
3972 $this->request .=
"$k: $v\r\n";
3973 $this->
debug(
"$k: $v");
3976 $this->
debug(
'In parse_http_headers, HTTP headers not accessible');
3977 $this->
setError(
'HTTP headers not accessible');
4005 $this->
debug(
'entering parse_request()');
4007 $this->
debug(
'got character encoding: '.$this->xml_encoding);
4009 if (isset($this->headers[
'content-encoding']) &&
'' != $this->headers[
'content-encoding']) {
4010 $this->
debug(
'got content encoding: ' . $this->headers[
'content-encoding']);
4011 if (
'deflate' == $this->headers[
'content-encoding'] ||
'gzip' == $this->headers[
'content-encoding']) {
4013 if (function_exists(
'gzuncompress')) {
4014 if (
'deflate' == $this->headers[
'content-encoding'] && $degzdata = @gzuncompress($data)) {
4016 } elseif (
'gzip' == $this->headers[
'content-encoding'] && $degzdata = gzinflate(substr($data, 10))) {
4019 $this->
fault(
'SOAP-ENV:Client',
'Errors occurred when trying to decode the data');
4023 $this->
fault(
'SOAP-ENV:Client',
'This Server does not support compressed data');
4028 $this->request .=
"\r\n".$data;
4030 $this->requestSOAP = $data;
4031 $this->
debug(
'leaving parse_request');
4053 $this->
debug(
'in invoke_method, methodname=' . $this->methodname .
' methodURI=' . $this->methodURI .
' SOAPAction=' . $this->SOAPAction);
4065 $orig_methodname = $this->methodname;
4068 $this->
debug(
'in invoke_method, found WSDL operation=' . $this->methodname);
4072 $this->
debug(
'in invoke_method, found WSDL soapAction=' . $this->SOAPAction .
' for operation=' . $this->opData[
'name']);
4074 $this->methodname = $this->opData[
'name'];
4076 $this->
debug(
'in invoke_method, no WSDL for operation=' . $this->methodname);
4077 $this->
fault(
'SOAP-ENV:Client',
"Operation '" . $this->methodname .
"' is not defined in the WSDL for this service");
4081 $this->
debug(
'in invoke_method, no WSDL to validate method');
4087 if (strpos($this->methodname,
'..') > 0) {
4089 } elseif (strpos($this->methodname,
'.') > 0) {
4094 $this->
debug(
"in invoke_method, delim=$delim");
4098 if (strlen($delim) > 0 && 1 == substr_count($this->methodname, $delim)) {
4099 $try_class = substr($this->methodname, 0, strpos($this->methodname, $delim));
4100 if (class_exists($try_class)) {
4102 $class = $try_class;
4103 $method = substr($this->methodname, strpos($this->methodname, $delim) + strlen($delim));
4104 $this->
debug(
"in invoke_method, class=$class method=$method delim=$delim");
4106 $this->
debug(
"in invoke_method, class=$try_class not found");
4110 $this->
debug(
'in invoke_method, no class to try');
4115 if (!function_exists($this->methodname)) {
4116 $this->
debug(
"in invoke_method, function '$this->methodname' not found!");
4117 $this->result =
'fault: method not found';
4118 $this->
fault(
'SOAP-ENV:Client',
"method '$this->methodname'('$orig_methodname') not defined in service('$try_class' '$delim')");
4122 $method_to_compare = (
'4.' == substr(phpversion(), 0, 2)) ? strtolower($method) : $method;
4123 if (!in_array($method_to_compare, get_class_methods($class))) {
4124 $this->
debug(
"in invoke_method, method '$this->methodname' not found in class '$class'!");
4125 $this->result =
'fault: method not found';
4126 $this->
fault(
'SOAP-ENV:Client',
"method '$this->methodname'/'$method_to_compare'('$orig_methodname') not defined in service/'$class'('$try_class' '$delim')");
4133 if (! $this->
verify_method($this->methodname, $this->methodparams)) {
4135 $this->
debug(
'ERROR: request not verified against method signature');
4136 $this->result =
'fault: request failed validation against method signature';
4138 $this->
fault(
'SOAP-ENV:Client',
"Operation '$this->methodname' not defined in service.");
4143 $this->
debug(
'in invoke_method, params:');
4145 $this->
debug(
"in invoke_method, calling '$this->methodname'");
4146 if (!function_exists(
'call_user_func_array')) {
4148 $this->
debug(
'in invoke_method, calling function using eval()');
4149 $funcCall =
"\$this->methodreturn = $this->methodname(";
4151 if (
'..' == $delim) {
4152 $this->
debug(
'in invoke_method, calling class method using eval()');
4153 $funcCall =
'$this->methodreturn = ' . $class .
'::' . $method .
'(';
4155 $this->
debug(
'in invoke_method, calling instance method using eval()');
4157 $instname =
'$inst_' . time();
4158 $funcCall = $instname .
' = new ' . $class .
'(); ';
4159 $funcCall .=
'$this->methodreturn = ' . $instname .
'->' . $method .
'(';
4162 if ($this->methodparams) {
4163 foreach ($this->methodparams as $param) {
4164 if (is_array($param) || is_object($param)) {
4165 $this->
fault(
'SOAP-ENV:Client',
'NuSOAP does not handle complexType parameters correctly when using eval; call_user_func_array must be available');
4168 $funcCall .=
"\"$param\",";
4170 $funcCall = substr($funcCall, 0, -1);
4173 $this->
debug(
'in invoke_method, function call: '.$funcCall);
4177 $this->
debug(
'in invoke_method, calling function using call_user_func_array()');
4178 $call_arg = (string)$this->methodname;
4179 } elseif (
'..' == $delim) {
4180 $this->
debug(
'in invoke_method, calling class method using call_user_func_array()');
4181 $call_arg = [$class, $method];
4183 $this->
debug(
'in invoke_method, calling instance method using call_user_func_array()');
4184 $instance =
new $class ();
4185 $call_arg = [&$instance, $method];
4187 if (is_array($this->methodparams)) {
4188 $this->methodreturn = call_user_func_array($call_arg, array_values($this->methodparams));
4190 $this->methodreturn = call_user_func_array($call_arg, []);
4193 $this->
debug(
'in invoke_method, methodreturn:');
4195 $this->
debug(
"in invoke_method, called method $this->methodname, received data of type ".gettype($this->methodreturn));
4212 $this->
debug(
'Entering serialize_return methodname: ' . $this->methodname .
' methodURI: ' . $this->methodURI);
4214 if (isset($this->methodreturn) && is_object($this->methodreturn) && ((
'soap_fault' == get_class($this->methodreturn)) || (
'nusoap_fault' == get_class($this->methodreturn)))) {
4215 $this->
debug(
'got a fault object from method');
4216 $this->
fault = $this->methodreturn;
4218 } elseif ($this->methodreturnisliteralxml) {
4219 $return_val = $this->methodreturn;
4222 $this->
debug(
'got a(n) '.gettype($this->methodreturn).
' from method');
4223 $this->
debug(
'serializing return value');
4225 if ((is_countable($this->opData[
'output'][
'parts']) ? count($this->opData[
'output'][
'parts']) : 0) > 1) {
4226 $this->
debug(
'more than one output part, so use the method return unchanged');
4227 $opParams = $this->methodreturn;
4228 } elseif (1 == (is_countable($this->opData[
'output'][
'parts']) ? count($this->opData[
'output'][
'parts']) : 0)) {
4229 $this->
debug(
'exactly one output part, so wrap the method return in a simple array');
4234 $opParams = [$this->methodreturn];
4240 $this->
debug(
'got wsdl error: '.$errstr);
4241 $this->
fault(
'SOAP-ENV:Server',
'unable to serialize result');
4245 if (isset($this->methodreturn)) {
4246 $return_val = $this->
serialize_val($this->methodreturn,
'return');
4249 $this->
debug(
'in absence of WSDL, assume void return for backward compatibility');
4253 $this->
debug(
'return value:');
4256 $this->
debug(
'serializing response');
4258 $this->
debug(
'have WSDL for serialization: style is ' . $this->opData[
'style']);
4259 if (
'rpc' == $this->opData[
'style']) {
4260 $this->
debug(
'style is rpc for serialization: use is ' . $this->opData[
'output'][
'use']);
4261 if (
'literal' == $this->opData[
'output'][
'use']) {
4263 if ($this->methodURI) {
4264 $payload =
'<ns1:'.$this->methodname.
'Response xmlns:ns1="'.$this->methodURI.
'">'.$return_val.
'</ns1:'.$this->methodname .
'Response>';
4266 $payload =
'<'.$this->methodname.
'Response>'.$return_val.
'</'.$this->methodname.
'Response>';
4269 if ($this->methodURI) {
4270 $payload =
'<ns1:'.$this->methodname.
'Response xmlns:ns1="'.$this->methodURI.
'">'.$return_val.
'</ns1:'.$this->methodname .
'Response>';
4272 $payload =
'<'.$this->methodname.
'Response>'.$return_val.
'</'.$this->methodname.
'Response>';
4276 $this->
debug(
'style is not rpc for serialization: assume document');
4277 $payload = $return_val;
4280 $this->
debug(
'do not have WSDL for serialization: assume rpc/encoded');
4281 $payload =
'<ns1:'.$this->methodname.
'Response xmlns:ns1="'.$this->methodURI.
'">'.$return_val.
'</ns1:'.$this->methodname .
'Response>';
4283 $this->result =
'successful';
4288 if (isset($this->opData[
'output'][
'encodingStyle'])) {
4289 $encodingStyle = $this->opData[
'output'][
'encodingStyle'];
4291 $encodingStyle =
'';
4294 $this->responseSOAP = $this->
serializeEnvelope($payload, $this->responseHeaders, $this->
wsdl->usedNamespaces, $this->opData[
'style'], $this->opData[
'output'][
'use'], $encodingStyle);
4296 $this->responseSOAP = $this->
serializeEnvelope($payload, $this->responseHeaders);
4298 $this->
debug(
'Leaving serialize_return');
4313 $this->
debug(
'Enter send_response');
4315 $payload = $this->
fault->serialize();
4316 $this->outgoing_headers[] =
'HTTP/1.0 500 Internal Server Error';
4317 $this->outgoing_headers[] =
'Status: 500 Internal Server Error';
4319 $payload = $this->responseSOAP;
4327 if (isset($this->debug_flag) && $this->debug_flag) {
4330 $this->outgoing_headers[] =
"Server: $this->title Server v$this->version";
4331 preg_match(
'/\$Revisio' .
'n: ([^ ]+)/', $this->revision, $rev);
4332 $this->outgoing_headers[] =
"X-SOAP-Server: $this->title/$this->version (".$rev[1] .
')';
4338 $this->outgoing_headers[] =
"Content-Type: $type" . ($charset ?
'; charset=' . $charset :
'');
4342 if (strlen($payload) > 1024 && isset($this->headers) && isset($this->headers[
'accept-encoding'])) {
4343 if (strstr($this->headers[
'accept-encoding'],
'gzip')) {
4344 if (function_exists(
'gzencode')) {
4345 if (isset($this->debug_flag) && $this->debug_flag) {
4346 $payload .=
'<!-- Content being gzipped -->';
4348 $this->outgoing_headers[] =
'Content-Encoding: gzip';
4349 $payload = gzencode($payload);
4351 if (isset($this->debug_flag) && $this->debug_flag) {
4352 $payload .=
'<!-- Content will not be gzipped: no gzencode -->';
4355 } elseif (strstr($this->headers[
'accept-encoding'],
'deflate')) {
4359 if (function_exists(
'gzdeflate')) {
4360 if (isset($this->debug_flag) && $this->debug_flag) {
4361 $payload .=
'<!-- Content being deflated -->';
4363 $this->outgoing_headers[] =
'Content-Encoding: deflate';
4364 $payload = gzdeflate($payload);
4366 if (isset($this->debug_flag) && $this->debug_flag) {
4367 $payload .=
'<!-- Content will not be deflated: no gzcompress -->';
4373 $this->outgoing_headers[] =
'Content-Length: ' . strlen($payload);
4374 reset($this->outgoing_headers);
4375 foreach ($this->outgoing_headers as $hdr) {
4376 header($hdr,
false);
4379 $this->response = implode(
"\r\n", $this->outgoing_headers) .
"\r\n\r\n" . $payload;
4393 if (isset($this->
wsdl) && is_object($this->
wsdl)) {
4397 } elseif (isset($this->operations[$operation])) {
4413 $this->
debug(
'Entering parseRequest() for data of length ' . strlen($data) .
' headers:');
4415 if (!isset($headers[
'content-type'])) {
4416 $this->
setError(
'Request not of type text/xml (no content-type header)');
4419 if (!strstr($headers[
'content-type'],
'text/xml')) {
4420 $this->
setError(
'Request not of type text/xml');
4423 if (strpos($headers[
'content-type'],
'=')) {
4424 $enc = str_replace(
'"',
'', substr(strstr($headers[
'content-type'],
'='), 1));
4425 $this->
debug(
'Got response encoding: ' . $enc);
4426 if (preg_match(
'/^(ISO-8859-1|US-ASCII|UTF-8)$/i', $enc)) {
4427 $this->xml_encoding = strtoupper($enc);
4429 $this->xml_encoding =
'US-ASCII';
4433 $this->xml_encoding =
'ISO-8859-1';
4435 $this->
debug(
'Use encoding: ' . $this->xml_encoding .
' when creating nusoap_parser');
4437 $parser =
new nusoap_parser($data, $this->xml_encoding,
'', $this->decode_utf8);
4439 $this->
debug(
"parser debug: \n".$parser->getDebug());
4441 if ($err = $parser->getError()) {
4442 $this->result =
'fault: error in msg parsing: '.$err;
4443 $this->
fault(
'SOAP-ENV:Client',
"error in msg parsing:\n".$err);
4447 $this->methodURI = $parser->root_struct_namespace;
4448 $this->methodname = $parser->root_struct_name;
4449 $this->
debug(
'methodname: '.$this->methodname.
' methodURI: '.$this->methodURI);
4450 $this->
debug(
'calling parser->get_soapbody()');
4451 $this->methodparams = $parser->get_soapbody();
4453 $this->requestHeaders = $parser->getHeaders();
4455 $this->requestHeader = $parser->get_soapheader();
4457 $this->document = $parser->document;
4497 return $this->soap_defencoding;
4511 $this->operations[$methodname] = [
'name' => $methodname,
'in' => $in,
'out' => $out];
4529 public function register($name, $in= [], $out= [], $namespace=
false, $soapaction=
false, $style=
false, $use=
false, $documentation=
'', $encodingStyle=
'')
4533 if ($this->externalWSDLURL) {
4534 die(
'You cannot bind to an external WSDL file, and register methods outside of it! Please choose either WSDL or no WSDL.');
4537 die(
'You must specify a name when you register an operation');
4539 if (!is_array($in)) {
4540 die(
'You must provide an array for operation inputs');
4542 if (!is_array($out)) {
4543 die(
'You must provide an array for operation outputs');
4545 if (
false == $namespace) {
4547 if (
false == $soapaction) {
4548 if (isset($_SERVER)) {
4549 $SERVER_NAME = $_SERVER[
'SERVER_NAME'];
4550 $SCRIPT_NAME = $_SERVER[
'PHP_SELF'] ?? $_SERVER[
'SCRIPT_NAME'];
4551 $HTTPS = $_SERVER[
'HTTPS'] ?? $_SERVER[
'HTTPS'] ??
'off';
4552 } elseif (isset($_SERVER)) {
4553 $SERVER_NAME = $_SERVER[
'SERVER_NAME'];
4554 $SCRIPT_NAME = $_SERVER[
'PHP_SELF'] ?? $_SERVER[
'SCRIPT_NAME'];
4555 $HTTPS = $_SERVER[
'HTTPS'] ??
'off';
4557 $this->
setError(
'Neither _SERVER nor HTTP_SERVER_VARS is available');
4559 if (
'1' == $HTTPS ||
'on' == $HTTPS) {
4564 $soapaction =
"$SCHEME://$SERVER_NAME$SCRIPT_NAME/$name";
4566 if (
false == $style) {
4569 if (
false == $use) {
4572 if (
'encoded' == $use &&
'' == $encodingStyle) {
4573 $encodingStyle =
'https://schemas.xmlsoap.org/soap/encoding/';
4576 $this->operations[$name] = [
4580 'namespace' => $namespace,
4581 'soapaction' => $soapaction,
4585 $this->
wsdl->
addOperation($name, $in, $out, $namespace, $soapaction, $style, $use, $documentation, $encodingStyle);
4600 public function fault($faultcode, $faultstring, $faultactor=
'', $faultdetail=
'')
4602 if (
'' == $faultdetail && $this->debug_flag) {
4605 $this->
fault =
new nusoap_fault($faultcode, $faultactor, $faultstring, $faultdetail);
4606 $this->
fault->soap_defencoding = $this->soap_defencoding;
4620 public function configureWSDL($serviceName, $namespace =
false, $endpoint =
false, $style=
'rpc', $transport =
'https://schemas.xmlsoap.org/soap/http', $schemaTargetNamespace =
false)
4624 if (isset($_SERVER)) {
4625 $SERVER_NAME = $_SERVER[
'SERVER_NAME'];
4626 $SERVER_PORT = $_SERVER[
'SERVER_PORT'];
4627 $SCRIPT_NAME = $_SERVER[
'PHP_SELF'] ?? $_SERVER[
'SCRIPT_NAME'];
4628 $HTTPS = $_SERVER[
'HTTPS'] ?? $_SERVER[
'HTTPS'] ??
'off';
4629 } elseif (isset($_SERVER)) {
4630 $SERVER_NAME = $_SERVER[
'SERVER_NAME'];
4631 $SERVER_PORT = $_SERVER[
'SERVER_PORT'];
4632 $SCRIPT_NAME = $_SERVER[
'PHP_SELF'] ?? $_SERVER[
'SCRIPT_NAME'];
4633 $HTTPS = $_SERVER[
'HTTPS'] ??
'off';
4635 $this->
setError(
'Neither _SERVER nor HTTP_SERVER_VARS is available');
4638 $colon = strpos($SERVER_NAME,
':');
4640 $SERVER_NAME = substr($SERVER_NAME, 0, $colon);
4642 if (80 == $SERVER_PORT) {
4645 $SERVER_PORT =
':' . $SERVER_PORT;
4647 if (
false == $namespace) {
4648 $namespace =
"https://$SERVER_NAME/soap/$serviceName";
4651 if (
false == $endpoint) {
4652 if (
'1' == $HTTPS ||
'on' == $HTTPS) {
4657 $endpoint =
"$SCHEME://$SERVER_NAME$SERVER_PORT$SCRIPT_NAME";
4660 if (
false == $schemaTargetNamespace) {
4661 $schemaTargetNamespace = $namespace;
4665 $this->
wsdl->serviceName = $serviceName;
4666 $this->
wsdl->endpoint = $endpoint;
4667 $this->
wsdl->namespaces[
'tns'] = $namespace;
4668 $this->
wsdl->namespaces[
'soap'] =
'https://schemas.xmlsoap.org/wsdl/soap/';
4669 $this->
wsdl->namespaces[
'wsdl'] =
'https://schemas.xmlsoap.org/wsdl/';
4670 if ($schemaTargetNamespace != $namespace) {
4671 $this->
wsdl->namespaces[
'types'] = $schemaTargetNamespace;
4674 if (
'document' == $style) {
4675 $this->
wsdl->schemas[$schemaTargetNamespace][0]->schemaInfo[
'elementFormDefault'] =
'qualified';
4677 $this->
wsdl->schemas[$schemaTargetNamespace][0]->schemaTargetNamespace = $schemaTargetNamespace;
4678 $this->
wsdl->schemas[$schemaTargetNamespace][0]->imports[
'https://schemas.xmlsoap.org/soap/encoding/'][0] = [
'location' =>
'',
'loaded' =>
true];
4679 $this->
wsdl->schemas[$schemaTargetNamespace][0]->imports[
'https://schemas.xmlsoap.org/wsdl/'][0] = [
'location' =>
'',
'loaded' =>
true];
4680 $this->
wsdl->bindings[$serviceName.
'Binding'] = [
4681 'name'=>$serviceName.
'Binding',
4683 'transport'=>$transport,
4684 'portType'=>$serviceName.
'PortType'
4686 $this->
wsdl->ports[$serviceName.
'Port'] = [
4687 'binding'=>$serviceName.
'Binding',
4688 'location'=>$endpoint,
4689 'bindingType'=>
'https://schemas.xmlsoap.org/wsdl/soap/'
4719 public $schemas = [];
4720 public $currentSchema;
4721 public $message = [];
4722 public $complexTypes = [];
4723 public $messages = [];
4724 public $currentMessage;
4725 public $currentOperation;
4726 public $portTypes = [];
4727 public $currentPortType;
4728 public $bindings = [];
4729 public $currentBinding;
4731 public $currentPort;
4732 public $opData = [];
4733 public $status =
'';
4734 public $documentation =
false;
4735 public $endpoint =
'';
4737 public $import = [];
4740 public $position = 0;
4742 public $depth_array = [];
4744 public $proxyhost =
'';
4745 public $proxyport =
'';
4746 public $proxyusername =
'';
4747 public $proxypassword =
'';
4748 public $timeout = 0;
4749 public $response_timeout = 30;
4750 public $curl_options = [];
4751 public $use_curl =
false;
4753 public $username =
'';
4754 public $password =
'';
4755 public $authtype =
'';
4756 public $certRequest = [];
4772 public function __construct($wsdl =
'', $proxyhost=
false, $proxyport=
false, $proxyusername=
false, $proxypassword=
false, $timeout=0, $response_timeout=30, $curl_options=
null, $use_curl=
false)
4774 parent::__construct();
4775 $this->
debug(
"ctor wsdl=$wsdl timeout=$timeout response_timeout=$response_timeout");
4776 $this->proxyhost = $proxyhost;
4777 $this->proxyport = $proxyport;
4778 $this->proxyusername = $proxyusername;
4779 $this->proxypassword = $proxypassword;
4780 $this->timeout = $timeout;
4781 $this->response_timeout = $response_timeout;
4782 if (is_array($curl_options)) {
4783 $this->curl_options = $curl_options;
4785 $this->use_curl = $use_curl;
4797 $this->
debug(
"parse and process WSDL path=$wsdl");
4798 $this->
wsdl = $wsdl;
4800 if (
'' != $this->
wsdl) {
4805 $imported_urls = [];
4807 while ($imported > 0) {
4810 foreach ($this->schemas as $ns => $list) {
4811 foreach ($list as $xs) {
4812 $wsdlparts = parse_url($this->
wsdl);
4813 foreach ($xs->imports as $ns2 => $list2) {
4814 for ($ii = 0; $ii < (is_countable($list2) ? count($list2) : 0); $ii++) {
4815 if (! $list2[$ii][
'loaded']) {
4816 $this->schemas[$ns]->imports[$ns2][$ii][
'loaded'] =
true;
4817 $url = $list2[$ii][
'location'];
4819 $urlparts = parse_url($url);
4820 if (!isset($urlparts[
'host'])) {
4821 $url = $wsdlparts[
'scheme'] .
'://' . $wsdlparts[
'host'] . (isset($wsdlparts[
'port']) ?
':' .$wsdlparts[
'port'] :
'') .
4822 substr($wsdlparts[
'path'], 0, strrpos($wsdlparts[
'path'],
'/') + 1) .$urlparts[
'path'];
4824 if (! in_array($url, $imported_urls)) {
4827 $imported_urls[] = $url;
4830 $this->
debug(
'Unexpected scenario: empty URL for unloaded import');
4838 $wsdlparts = parse_url($this->
wsdl);
4839 foreach ($this->
import as $ns => $list) {
4840 for ($ii = 0; $ii < (is_countable($list) ? count($list) : 0); $ii++) {
4841 if (! $list[$ii][
'loaded']) {
4842 $this->
import[$ns][$ii][
'loaded'] =
true;
4843 $url = $list[$ii][
'location'];
4845 $urlparts = parse_url($url);
4846 if (!isset($urlparts[
'host'])) {
4847 $url = $wsdlparts[
'scheme'] .
'://' . $wsdlparts[
'host'] . (isset($wsdlparts[
'port']) ?
':' . $wsdlparts[
'port'] :
'') .
4848 substr($wsdlparts[
'path'], 0, strrpos($wsdlparts[
'path'],
'/') + 1) .$urlparts[
'path'];
4850 if (! in_array($url, $imported_urls)) {
4853 $imported_urls[] = $url;
4856 $this->
debug(
'Unexpected scenario: empty URL for unloaded import');
4863 foreach ($this->bindings as $binding => $bindingData) {
4864 if (isset($bindingData[
'operations']) && is_array($bindingData[
'operations'])) {
4865 foreach ($bindingData[
'operations'] as $operation => $data) {
4866 $this->
debug(
'post-parse data gathering for ' . $operation);
4867 $this->bindings[$binding][
'operations'][$operation][
'input'] =
4868 isset($this->bindings[$binding][
'operations'][$operation][
'input']) ?
4869 array_merge($this->bindings[$binding][
'operations'][$operation][
'input'], $this->portTypes[ $bindingData[
'portType'] ][$operation][
'input']) :
4870 $this->portTypes[ $bindingData[
'portType'] ][$operation][
'input'];
4871 $this->bindings[$binding][
'operations'][$operation][
'output'] =
4872 isset($this->bindings[$binding][
'operations'][$operation][
'output']) ?
4873 array_merge($this->bindings[$binding][
'operations'][$operation][
'output'], $this->portTypes[ $bindingData[
'portType'] ][$operation][
'output']) :
4874 $this->portTypes[ $bindingData[
'portType'] ][$operation][
'output'];
4875 if (isset($this->messages[ $this->bindings[$binding][
'operations'][$operation][
'input'][
'message'] ])) {
4876 $this->bindings[$binding][
'operations'][$operation][
'input'][
'parts'] = $this->messages[ $this->bindings[$binding][
'operations'][$operation][
'input'][
'message'] ];
4878 if (isset($this->messages[ $this->bindings[$binding][
'operations'][$operation][
'output'][
'message'] ])) {
4879 $this->bindings[$binding][
'operations'][$operation][
'output'][
'parts'] = $this->messages[ $this->bindings[$binding][
'operations'][$operation][
'output'][
'message'] ];
4882 if (isset($bindingData[
'style']) && !isset($this->bindings[$binding][
'operations'][$operation][
'style'])) {
4883 $this->bindings[$binding][
'operations'][$operation][
'style'] = $bindingData[
'style'];
4885 $this->bindings[$binding][
'operations'][$operation][
'transport'] = $bindingData[
'transport'] ??
'';
4886 $this->bindings[$binding][
'operations'][$operation][
'documentation'] = $this->portTypes[ $bindingData[
'portType'] ][$operation][
'documentation'] ??
'';
4887 $this->bindings[$binding][
'operations'][$operation][
'endpoint'] = $bindingData[
'endpoint'] ??
'';
4902 $this->
debug(
"parse WSDL at path=$wsdl");
4905 $this->
debug(
'no wsdl passed to parseWSDL()!!');
4906 $this->
setError(
'no wsdl passed to parseWSDL()!!');
4911 $wsdl_props = parse_url($wsdl);
4913 if (isset($wsdl_props[
'scheme']) && (
'http' == $wsdl_props[
'scheme'] ||
'https' == $wsdl_props[
'scheme'])) {
4914 $this->
debug(
'getting WSDL http(s) URL ' . $wsdl);
4917 $tr->request_method =
'GET';
4918 $tr->useSOAPAction =
false;
4919 if ($this->proxyhost && $this->proxyport) {
4920 $tr->setProxy($this->proxyhost, $this->proxyport, $this->proxyusername, $this->proxypassword);
4922 if (
'' != $this->authtype) {
4923 $tr->setCredentials($this->username, $this->password, $this->authtype, [], $this->certRequest);
4925 $tr->setEncoding(
'gzip, deflate');
4926 $wsdl_string = $tr->send(
'', $this->timeout, $this->response_timeout);
4931 if ($err = $tr->getError()) {
4932 $errstr =
'Getting ' . $wsdl .
' - HTTP ERROR: '.$err;
4933 $this->
debug($errstr);
4939 $this->
debug(
'got WSDL URL');
4942 if (isset($wsdl_props[
'scheme']) && (
'file' == $wsdl_props[
'scheme']) && isset($wsdl_props[
'path'])) {
4943 $path = isset($wsdl_props[
'host']) ? ($wsdl_props[
'host'] .
':' . $wsdl_props[
'path']) : $wsdl_props[
'path'];
4947 $this->
debug(
'getting WSDL file ' . $path);
4948 if ($fp = @fopen($path,
'r')) {
4950 while ($data = fread($fp, 32768)) {
4951 $wsdl_string .= $data;
4955 $errstr =
"Bad path to WSDL file $path";
4956 $this->
debug($errstr);
4961 $this->
debug(
'Parse WSDL');
4964 $this->parser = xml_parser_create();
4967 xml_parser_set_option($this->parser, XML_OPTION_CASE_FOLDING, 0);
4969 xml_set_object($this->parser, $this);
4971 xml_set_element_handler($this->parser,
'start_element',
'end_element');
4972 xml_set_character_data_handler($this->parser,
'character_data');
4974 if (!xml_parse($this->parser, $wsdl_string,
true)) {
4977 'XML error parsing WSDL from %s on line %d: %s',
4979 xml_get_current_line_number($this->parser),
4980 xml_error_string(xml_get_error_code($this->parser))
4982 $this->
debug($errstr);
4983 $this->
debug(
"XML payload:\n" . $wsdl_string);
4988 xml_parser_free($this->parser);
4989 $this->
debug(
'Parsing WSDL done');
5007 if (
'schema' == $this->status) {
5008 $this->currentSchema->schemaStartElement($parser, $name, $attrs);
5009 $this->
appendDebug($this->currentSchema->getDebug());
5010 $this->currentSchema->clearDebug();
5011 } elseif (preg_match(
'/schema$/', $name)) {
5012 $this->
debug(
'Parsing WSDL schema');
5014 $this->status =
'schema';
5016 $this->currentSchema->schemaStartElement($parser, $name, $attrs);
5017 $this->
appendDebug($this->currentSchema->getDebug());
5018 $this->currentSchema->clearDebug();
5021 $pos = $this->position++;
5022 $depth = $this->depth++;
5024 $this->depth_array[$depth] = $pos;
5025 $this->message[$pos] = [
'cdata' =>
''];
5027 if ((is_countable($attrs) ? count($attrs) : 0) > 0) {
5029 foreach ($attrs as $k => $v) {
5030 if (preg_match(
'/^xmlns/', $k)) {
5031 if ($ns_prefix = substr(strrchr($k,
':'), 1)) {
5032 $this->namespaces[$ns_prefix] = $v;
5034 $this->namespaces[
'ns' . (count($this->namespaces) + 1)] = $v;
5036 if (
'https://www.w3.org/2001/XMLSchema' == $v ||
'https://www.w3.org/1999/XMLSchema' == $v ||
'https://www.w3.org/2000/10/XMLSchema' == $v) {
5037 $this->XMLSchemaVersion = $v;
5038 $this->namespaces[
'xsi'] = $v .
'-instance';
5043 foreach ($attrs as $k => $v) {
5044 $k = strpos($k,
':') ? $this->
expandQname($k) : $k;
5045 if (
'location' != $k &&
'soapAction' != $k &&
'namespace' != $k) {
5046 $v = strpos($v,
':') ? $this->
expandQname($v) : $v;
5055 if (preg_match(
'/:/', $name)) {
5057 $prefix = substr($name, 0, strpos($name,
':'));
5059 $namespace = $this->namespaces[$prefix] ??
'';
5061 $name = substr(strstr($name,
':'), 1);
5065 switch ($this->status) {
5067 if (
'part' == $name) {
5068 if (isset($attrs[
'type'])) {
5069 $this->
debug(
'msg ' . $this->currentMessage .
": found part (with type) $attrs[name]: " . implode(
',', $attrs));
5070 $this->messages[$this->currentMessage][$attrs[
'name']] = $attrs[
'type'];
5072 if (isset($attrs[
'element'])) {
5073 $this->
debug(
'msg ' . $this->currentMessage .
": found part (with element) $attrs[name]: " . implode(
',', $attrs));
5074 $this->messages[$this->currentMessage][$attrs[
'name']] = $attrs[
'element'] .
'^';
5081 $this->currentPortOperation = $attrs[
'name'];
5082 $this->
debug(
"portType $this->currentPortType operation: $this->currentPortOperation");
5083 if (isset($attrs[
'parameterOrder'])) {
5084 $this->portTypes[$this->currentPortType][$attrs[
'name']][
'parameterOrder'] = $attrs[
'parameterOrder'];
5087 case 'documentation':
5088 $this->documentation =
true;
5092 $m = isset($attrs[
'message']) ? $this->
getLocalPart($attrs[
'message']) :
'';
5093 $this->portTypes[$this->currentPortType][$this->currentPortOperation][$name][
'message'] = $m;
5101 if (isset($attrs[
'style'])) {
5102 $this->bindings[$this->currentBinding][
'prefix'] = $prefix;
5104 $this->bindings[$this->currentBinding] = array_merge($this->bindings[$this->currentBinding], $attrs);
5107 $this->bindings[$this->currentBinding][
'operations'][$this->currentOperation][$this->opStatus][
'headers'][] = $attrs;
5110 if (isset($attrs[
'soapAction'])) {
5111 $this->bindings[$this->currentBinding][
'operations'][$this->currentOperation][
'soapAction'] = $attrs[
'soapAction'];
5113 if (isset($attrs[
'style'])) {
5114 $this->bindings[$this->currentBinding][
'operations'][$this->currentOperation][
'style'] = $attrs[
'style'];
5116 if (isset($attrs[
'name'])) {
5117 $this->currentOperation = $attrs[
'name'];
5118 $this->
debug(
"current binding operation: $this->currentOperation");
5119 $this->bindings[$this->currentBinding][
'operations'][$this->currentOperation][
'name'] = $attrs[
'name'];
5120 $this->bindings[$this->currentBinding][
'operations'][$this->currentOperation][
'binding'] = $this->currentBinding;
5121 $this->bindings[$this->currentBinding][
'operations'][$this->currentOperation][
'endpoint'] = $this->bindings[$this->currentBinding][
'endpoint'] ??
'';
5125 $this->opStatus =
'input';
5128 $this->opStatus =
'output';
5131 if (isset($this->bindings[$this->currentBinding][
'operations'][$this->currentOperation][$this->opStatus])) {
5132 $this->bindings[$this->currentBinding][
'operations'][$this->currentOperation][$this->opStatus] = array_merge($this->bindings[$this->currentBinding][
'operations'][$this->currentOperation][$this->opStatus], $attrs);
5134 $this->bindings[$this->currentBinding][
'operations'][$this->currentOperation][$this->opStatus] = $attrs;
5142 $this->currentPort = $attrs[
'name'];
5143 $this->
debug(
'current port: ' . $this->currentPort);
5144 $this->ports[$this->currentPort][
'binding'] = $this->
getLocalPart($attrs[
'binding']);
5148 $this->ports[$this->currentPort][
'location'] = $attrs[
'location'];
5149 $this->ports[$this->currentPort][
'bindingType'] = $namespace;
5150 $this->bindings[ $this->ports[$this->currentPort][
'binding'] ][
'bindingType'] = $namespace;
5151 $this->bindings[ $this->ports[$this->currentPort][
'binding'] ][
'endpoint'] = $attrs[
'location'];
5159 if (isset($attrs[
'location'])) {
5160 $this->
import[$attrs[
'namespace']][] = [
'location' => $attrs[
'location'],
'loaded' =>
false];
5161 $this->
debug(
'parsing import ' . $attrs[
'namespace'].
' - ' . $attrs[
'location'] .
' (' . (is_countable($this->
import[$attrs[
'namespace']]) ? count($this->
import[$attrs[
'namespace']]) : 0).
')');
5163 $this->
import[$attrs[
'namespace']][] = [
'location' =>
'',
'loaded' =>
true];
5165 $this->namespaces[
'ns'.(count($this->namespaces)+1)] = $attrs[
'namespace'];
5167 $this->
debug(
'parsing import ' . $attrs[
'namespace'].
' - [no location] (' . (is_countable($this->
import[$attrs[
'namespace']]) ? count($this->
import[$attrs[
'namespace']]) : 0).
')');
5175 $this->status =
'message';
5176 $this->messages[$attrs[
'name']] = [];
5177 $this->currentMessage = $attrs[
'name'];
5180 $this->status =
'portType';
5181 $this->portTypes[$attrs[
'name']] = [];
5182 $this->currentPortType = $attrs[
'name'];
5185 if (isset($attrs[
'name'])) {
5187 if (strpos($attrs[
'name'],
':')) {
5188 $this->currentBinding = $this->
getLocalPart($attrs[
'name']);
5190 $this->currentBinding = $attrs[
'name'];
5192 $this->status =
'binding';
5193 $this->bindings[$this->currentBinding][
'portType'] = $this->
getLocalPart($attrs[
'type']);
5194 $this->
debug(
"current binding: $this->currentBinding of portType: " . $attrs[
'type']);
5198 $this->serviceName = $attrs[
'name'];
5199 $this->status =
'service';
5200 $this->
debug(
'current service: ' . $this->serviceName);
5203 foreach ($attrs as $name => $value) {
5204 $this->wsdl_info[$name] = $value;
5221 if ( preg_match(
'/schema$/', $name)) {
5223 $this->
appendDebug($this->currentSchema->getDebug());
5224 $this->currentSchema->clearDebug();
5225 $this->schemas[$this->currentSchema->schemaTargetNamespace][] = $this->currentSchema;
5226 $this->
debug(
'Parsing WSDL schema done');
5228 if (
'schema' == $this->status) {
5229 $this->currentSchema->schemaEndElement($parser, $name);
5235 if ($this->documentation) {
5238 $this->documentation =
false;
5251 $pos = $this->depth_array[$this->depth] ?? 0;
5252 if (isset($this->message[$pos][
'cdata'])) {
5253 $this->message[$pos][
'cdata'] .= $data;
5255 if ($this->documentation) {
5256 $this->documentation .= $data;
5269 public function setCredentials($username, $password, $authtype =
'basic', $certRequest = [])
5271 $this->
debug(
"setCredentials username=$username authtype=$authtype certRequest=");
5273 $this->username = $username;
5274 $this->password = $password;
5275 $this->authtype = $authtype;
5276 $this->certRequest = $certRequest;
5279 public function getBindingData($binding)
5281 if (is_array($this->bindings[$binding])) {
5282 return $this->bindings[$binding];
5297 if (
'soap' == $bindingType) {
5298 $bindingType =
'https://schemas.xmlsoap.org/wsdl/soap/';
5299 } elseif (
'soap12' == $bindingType) {
5300 $bindingType =
'https://schemas.xmlsoap.org/wsdl/soap12/';
5302 $this->
debug(
"getOperations bindingType $bindingType may not be supported");
5304 $this->
debug(
"getOperations for port '$portName' bindingType $bindingType");
5306 foreach ($this->ports as $port => $portData) {
5307 $this->
debug(
"getOperations checking port $port bindingType " . $portData[
'bindingType']);
5308 if (
'' == $portName || $port == $portName) {
5310 if ($portData[
'bindingType'] == $bindingType) {
5311 $this->
debug(
"getOperations found port $port bindingType $bindingType");
5315 if (isset($this->bindings[ $portData[
'binding'] ][
'operations'])) {
5316 $ops = array_merge($ops, $this->bindings[ $portData[
'binding'] ][
'operations']);
5321 if (0 == count($ops)) {
5322 $this->
debug(
"getOperations found no operations for port '$portName' bindingType $bindingType");
5337 if (
'soap' == $bindingType) {
5338 $bindingType =
'https://schemas.xmlsoap.org/wsdl/soap/';
5339 } elseif (
'soap12' == $bindingType) {
5340 $bindingType =
'https://schemas.xmlsoap.org/wsdl/soap12/';
5343 foreach ($this->ports as $port => $portData) {
5345 if ($portData[
'bindingType'] == $bindingType) {
5348 foreach (array_keys($this->bindings[ $portData[
'binding'] ][
'operations']) as $bOperation) {
5350 if ($operation == $bOperation) {
5351 $opData = $this->bindings[ $portData[
'binding'] ][
'operations'][$operation];
5369 if (
'soap' == $bindingType) {
5370 $bindingType =
'https://schemas.xmlsoap.org/wsdl/soap/';
5371 } elseif (
'soap12' == $bindingType) {
5372 $bindingType =
'https://schemas.xmlsoap.org/wsdl/soap12/';
5375 foreach ($this->ports as $port => $portData) {
5377 if ($portData[
'bindingType'] == $bindingType) {
5379 foreach ($this->bindings[ $portData[
'binding'] ][
'operations'] as $bOperation => $opData) {
5380 if ($opData[
'soapAction'] == $soapAction) {
5408 $this->
debug(
"in getTypeDef: type=$type, ns=$ns");
5409 if ((! $ns) && isset($this->namespaces[
'tns'])) {
5410 $ns = $this->namespaces[
'tns'];
5411 $this->
debug(
"in getTypeDef: type namespace forced to $ns");
5413 if (!isset($this->schemas[$ns])) {
5414 foreach ($this->schemas as $ns0 => $schema0) {
5415 if (0 == strcasecmp($ns, $ns0)) {
5416 $this->
debug(
"in getTypeDef: replacing schema namespace $ns with $ns0");
5422 if (isset($this->schemas[$ns])) {
5423 $this->
debug(
"in getTypeDef: have schema for namespace $ns");
5424 for ($i = 0; $i < (is_countable($this->schemas[$ns]) ? count($this->schemas[$ns]) : 0); $i++) {
5425 $xs = &$this->schemas[$ns][$i];
5426 $t = $xs->getTypeDef($type);
5430 $this->
debug(
"in getTypeDef: found type $type");
5431 if (!isset($t[
'phpType'])) {
5433 $uqType = substr($t[
'type'], strrpos($t[
'type'],
':') + 1);
5434 $ns = substr($t[
'type'], 0, strrpos($t[
'type'],
':'));
5437 $this->
debug(
"found type for [element] $type:");
5439 if (isset($etype[
'phpType'])) {
5440 $t[
'phpType'] = $etype[
'phpType'];
5442 if (isset($etype[
'elements'])) {
5443 $t[
'elements'] = $etype[
'elements'];
5445 if (isset($etype[
'attrs'])) {
5446 $t[
'attrs'] = $etype[
'attrs'];
5449 $this->
debug(
"did not find type for [element] $type");
5455 $this->
debug(
"in getTypeDef: did not find type $type");
5457 $this->
debug(
"in getTypeDef: do not have schema for namespace $ns");
5471 if (isset($_SERVER)) {
5472 $PHP_SELF = $_SERVER[
'PHP_SELF'];
5473 } elseif (isset($_SERVER)) {
5474 $PHP_SELF = $_SERVER[
'PHP_SELF'];
5476 $this->
setError(
'Neither _SERVER nor HTTP_SERVER_VARS is available');
5480 <html><head><title>NuSOAP: '.$this->serviceName.
'</title>
5481 <style type="text/css">
5482 body { font-family: arial; color: #000000; background-color: #ffffff; margin: 0px 0px 0px 0px; }
5483 p { font-family: arial; color: #000000; margin-top: 0px; margin-bottom: 12px; }
5484 pre { background-color: silver; padding: 5px; font-family: Courier New; font-size: x-small; color: #000000;}
5485 ul { margin-top: 10px; margin-left: 20px; }
5486 li { list-style-type: none; margin-top: 10px; color: #000000; }
5488 margin-left: 0px; padding-bottom: 2em; }
5490 padding-top: 10px; padding-bottom: 10px; padding-left: 15px; font-size: .70em;
5491 margin-top: 10px; margin-left: 0px; color: #000000;
5492 background-color: #ccccff; width: 20%; margin-left: 20px; margin-top: 20px; }
5494 font-family: arial; font-size: 26px; color: #ffffff;
5495 background-color: #999999; width: 100%;
5496 margin-left: 0px; margin-right: 0px;
5497 padding-top: 10px; padding-bottom: 10px;}
5499 position: absolute; visibility: hidden; z-index: 200; left: 250px; top: 100px;
5500 font-family: arial; overflow: hidden; width: 600;
5501 padding: 20px; font-size: 10px; background-color: #999999;
5502 layer-background-color:#FFFFFF; }
5503 a,a:active { color: charcoal; font-weight: bold; }
5504 a:visited { color: #666666; font-weight: bold; }
5505 a:hover { color: cc3300; font-weight: bold; }
5507 <script language="JavaScript" type="text/javascript">
5509 // POP-UP CAPTIONS...
5510 function lib_bwcheck(){ //Browsercheck (needed)
5511 this.ver=navigator.appVersion
5512 this.agent=navigator.userAgent
5513 this.dom=document.getElementById?1:0
5514 this.opera5=this.agent.indexOf("Opera 5")>-1
5515 this.ie5=(this.ver.indexOf("MSIE 5")>-1 && this.dom && !this.opera5)?1:0;
5516 this.ie6=(this.ver.indexOf("MSIE 6")>-1 && this.dom && !this.opera5)?1:0;
5517 this.ie4=(document.all && !this.dom && !this.opera5)?1:0;
5518 this.ie=this.ie4||this.ie5||this.ie6
5519 this.mac=this.agent.indexOf("Mac")>-1
5520 this.ns6=(this.dom && parseInt(this.ver) >= 5) ?1:0;
5521 this.ns4=(document.layers && !this.dom)?1:0;
5522 this.bw=(this.ie6 || this.ie5 || this.ie4 || this.ns4 || this.ns6 || this.opera5)
5525 var bw = new lib_bwcheck()
5526 //Makes crossbrowser object.
5527 function makeObj(obj){
5528 this.evnt=bw.dom? document.getElementById(obj):bw.ie4?document.all[obj]:bw.ns4?document.layers[obj]:0;
5529 if(!this.evnt) return false
5530 this.css=bw.dom||bw.ie4?this.evnt.style:bw.ns4?this.evnt:0;
5531 this.wref=bw.dom||bw.ie4?this.evnt:bw.ns4?this.css.document:0;
5532 this.writeIt=b_writeIt;
5535 // A unit of measure that will be added when setting the position of a layer.
5536 //var px = bw.ns4||window.opera?"":"px";
5537 function b_writeIt(text){
5538 if (bw.ns4){this.wref.write(text);this.wref.close()}
5539 else this.wref.innerHTML = text
5541 //Shows the messages
5543 function popup(divid){
5544 if(oDesc = new makeObj(divid)){
5545 oDesc.css.visibility = "visible"
5548 function popout(){ // Hides message
5549 if(oDesc) oDesc.css.visibility = "hidden"
5557 <div class=title>'.$this->serviceName.
'</div>
5559 <p>View the <a href="'.$PHP_SELF.
'?wsdl">WSDL</a> for the service.
5560 Click on an operation name to view it's details.</p>
5563 $b .=
"<li><a href='#' onclick=\"popout();popup('$op')\">$op</a></li>";
5565 $b .=
"<div id='$op' class='hidden'>
5566 <a href='#' onclick='popout()'><font color='#ffffff'>Close</font></a><br><br>";
5567 foreach ($data as $donnie => $marie) {
5568 if (
'input' == $donnie ||
'output' == $donnie) {
5569 $b .=
"<font color='white'>".ucfirst($donnie).
':</font><br>';
5570 foreach ($marie as $captain => $tenille) {
5571 if (
'parts' == $captain) {
5572 $b .=
" $captain:<br>";
5574 foreach ($tenille as $joanie => $chachi) {
5575 $b .=
" $joanie: $chachi<br>";
5579 $b .=
" $captain: $tenille<br>";
5583 $b .=
"<font color='white'>".ucfirst($donnie).
":</font> $marie<br>";
5591 </div></body></html>';
5604 $xml =
'<?xml version="1.0" encoding="ISO-8859-1"?>';
5605 $xml .=
"\n<definitions";
5606 foreach ($this->namespaces as $k => $v) {
5607 $xml .=
" xmlns:$k=\"$v\"";
5610 if (isset($this->namespaces[
'wsdl'])) {
5611 $xml .=
' xmlns="' . $this->namespaces[
'wsdl'] .
'"';
5613 if (isset($this->namespaces[
'tns'])) {
5614 $xml .=
' targetNamespace="' . $this->namespaces[
'tns'] .
'"';
5618 if (count($this->
import) > 0) {
5619 foreach ($this->
import as $ns => $list) {
5620 foreach ($list as $ii) {
5621 if (
'' != $ii[
'location']) {
5622 $xml .=
'<import location="' . $ii[
'location'] .
'" namespace="' . $ns .
'" />';
5624 $xml .=
'<import namespace="' . $ns .
'" />';
5630 if (count($this->schemas)>=1) {
5631 $xml .=
"\n<types>\n";
5632 foreach ($this->schemas as $ns => $list) {
5633 foreach ($list as $xs) {
5634 $xml .= $xs->serializeSchema();
5640 if (count($this->messages) >= 1) {
5641 foreach ($this->messages as $msgName => $msgParts) {
5642 $xml .=
"\n<message name=\"" . $msgName .
'">';
5643 if (is_array($msgParts)) {
5644 foreach ($msgParts as $partName => $partType) {
5646 if (strpos($partType,
':')) {
5648 } elseif (isset($this->typemap[$this->namespaces[
'xsd']][$partType])) {
5650 $typePrefix =
'xsd';
5652 foreach ($this->typemap as $ns => $types) {
5653 if (isset($types[$partType])) {
5657 if (!isset($typePrefix)) {
5658 die(
"$partType has no namespace!");
5663 $typeDef = $this->
getTypeDef($localPart, $ns);
5664 if (
'element' == $typeDef[
'typeClass']) {
5665 $elementortype =
'element';
5666 if (
'^' == substr($localPart, -1)) {
5667 $localPart = substr($localPart, 0, -1);
5670 $elementortype =
'type';
5672 $xml .=
"\n" .
' <part name="' . $partName .
'" ' . $elementortype .
'="' . $typePrefix .
':' . $localPart .
'" />';
5675 $xml .=
'</message>';
5679 if (count($this->bindings) >= 1) {
5682 foreach ($this->bindings as $bindingName => $attrs) {
5683 $binding_xml .=
"\n<binding name=\"" . $bindingName .
'" type="tns:' . $attrs[
'portType'] .
'">';
5684 $binding_xml .=
"\n" .
' <soap:binding style="' . $attrs[
'style'] .
'" transport="' . $attrs[
'transport'] .
'"/>';
5685 $portType_xml .=
"\n<portType name=\"" . $attrs[
'portType'] .
'">';
5686 foreach ($attrs[
'operations'] as $opName => $opParts) {
5687 $binding_xml .=
"\n" .
' <operation name="' . $opName .
'">';
5688 $binding_xml .=
"\n" .
' <soap:operation soapAction="' . $opParts[
'soapAction'] .
'" style="'. $opParts[
'style'] .
'"/>';
5689 if (isset($opParts[
'input'][
'encodingStyle']) &&
'' != $opParts[
'input'][
'encodingStyle']) {
5690 $enc_style =
' encodingStyle="' . $opParts[
'input'][
'encodingStyle'] .
'"';
5694 $binding_xml .=
"\n" .
' <input><soap:body use="' . $opParts[
'input'][
'use'] .
'" namespace="' . $opParts[
'input'][
'namespace'] .
'"' . $enc_style .
'/></input>';
5695 if (isset($opParts[
'output'][
'encodingStyle']) &&
'' != $opParts[
'output'][
'encodingStyle']) {
5696 $enc_style =
' encodingStyle="' . $opParts[
'output'][
'encodingStyle'] .
'"';
5700 $binding_xml .=
"\n" .
' <output><soap:body use="' . $opParts[
'output'][
'use'] .
'" namespace="' . $opParts[
'output'][
'namespace'] .
'"' . $enc_style .
'/></output>';
5701 $binding_xml .=
"\n" .
' </operation>';
5702 $portType_xml .=
"\n" .
' <operation name="' . $opParts[
'name'] .
'"';
5703 if (isset($opParts[
'parameterOrder'])) {
5704 $portType_xml .=
' parameterOrder="' . $opParts[
'parameterOrder'] .
'"';
5706 $portType_xml .=
'>';
5707 if (isset($opParts[
'documentation']) &&
'' != $opParts[
'documentation']) {
5708 $portType_xml .=
"\n" .
' <documentation>' . htmlspecialchars($opParts[
'documentation']) .
'</documentation>';
5710 $portType_xml .=
"\n" .
' <input message="tns:' . $opParts[
'input'][
'message'] .
'"/>';
5711 $portType_xml .=
"\n" .
' <output message="tns:' . $opParts[
'output'][
'message'] .
'"/>';
5712 $portType_xml .=
"\n" .
' </operation>';
5714 $portType_xml .=
"\n" .
'</portType>';
5715 $binding_xml .=
"\n" .
'</binding>';
5717 $xml .= $portType_xml . $binding_xml;
5720 $xml .=
"\n<service name=\"" . $this->serviceName .
'">';
5721 if (count($this->ports) >= 1) {
5722 foreach ($this->ports as $pName => $attrs) {
5723 $xml .=
"\n" .
' <port name="' . $pName .
'" binding="tns:' . $attrs[
'binding'] .
'">';
5724 $xml .=
"\n" .
' <soap:address location="' . $attrs[
'location'] . ($debug ?
'?debug=1' :
'') .
'"/>';
5725 $xml .=
"\n" .
' </port>';
5728 $xml .=
"\n" .
'</service>';
5729 return $xml .
"\n</definitions>";
5743 $this->
debug(
"in parametersMatchWrapped type=$type, parameters=");
5747 if (strpos($type,
':')) {
5748 $uqType = substr($type, strrpos($type,
':') + 1);
5749 $ns = substr($type, 0, strrpos($type,
':'));
5750 $this->
debug(
"in parametersMatchWrapped: got a prefixed type: $uqType, $ns");
5753 $this->
debug(
"in parametersMatchWrapped: expanded prefixed type: $uqType, $ns");
5758 $this->
debug(
"in parametersMatchWrapped: No namespace for type $type");
5764 if (!$typeDef = $this->
getTypeDef($uqType, $ns)) {
5765 $this->
debug(
"in parametersMatchWrapped: $type ($uqType) is not a supported type.");
5768 $this->
debug(
'in parametersMatchWrapped: found typeDef=');
5770 if (
'^' == substr($uqType, -1)) {
5771 $uqType = substr($uqType, 0, -1);
5773 $phpType = $typeDef[
'phpType'];
5774 $arrayType = ($typeDef[
'arrayType'] ??
'');
5775 $this->
debug(
"in parametersMatchWrapped: uqType: $uqType, ns: $ns, phptype: $phpType, arrayType: $arrayType");
5778 if (
'struct' != $phpType) {
5779 $this->
debug(
'in parametersMatchWrapped: not a struct');
5784 if (isset($typeDef[
'elements']) && is_array($typeDef[
'elements'])) {
5787 foreach ($typeDef[
'elements'] as $name => $attrs) {
5788 if (isset($parameters[$name])) {
5789 $this->
debug(
"in parametersMatchWrapped: have parameter named $name");
5792 $this->
debug(
"in parametersMatchWrapped: do not have parameter named $name");
5797 $this->
debug(
"in parametersMatchWrapped: $matches parameter names match $elements wrapped parameter names");
5798 if (0 == $matches) {
5806 $this->
debug(
"in parametersMatchWrapped: no elements type $ns:$uqType");
5807 return 0 == count($parameters);
5827 $this->
debug(
"in serializeRPCParameters: operation=$operation, direction=$direction, XMLSchemaVersion=$this->XMLSchemaVersion, bindingType=$bindingType");
5830 if (
'input' != $direction &&
'output' != $direction) {
5831 $this->
debug(
'The value of the \$direction argument needs to be either "input" or "output"');
5832 $this->
setError(
'The value of the \$direction argument needs to be either "input" or "output"');
5836 $this->
debug(
'Unable to retrieve WSDL data for operation: ' . $operation .
' bindingType: ' . $bindingType);
5837 $this->
setError(
'Unable to retrieve WSDL data for operation: ' . $operation .
' bindingType: ' . $bindingType);
5840 $this->
debug(
'in serializeRPCParameters: opData:');
5844 $encodingStyle =
'https://schemas.xmlsoap.org/soap/encoding/';
5845 if ((
'input' == $direction) && isset($opData[
'output'][
'encodingStyle']) && ($opData[
'output'][
'encodingStyle'] != $encodingStyle)) {
5846 $encodingStyle = $opData[
'output'][
'encodingStyle'];
5847 $enc_style = $encodingStyle;
5852 if (isset($opData[$direction][
'parts']) && (is_countable($opData[$direction][
'parts']) ? count($opData[$direction][
'parts']) : 0) > 0) {
5853 $parts = &$opData[$direction][
'parts'];
5854 $part_count = is_countable($parts) ? count($parts) : 0;
5855 $style = $opData[
'style'];
5856 $use = $opData[$direction][
'use'];
5857 $this->
debug(
"have $part_count part(s) to serialize using $style/$use");
5858 if (is_array($parameters)) {
5860 $parameter_count = count($parameters);
5861 $this->
debug(
"have $parameter_count parameter(s) provided as $parametersArrayType to serialize");
5863 if (
'document' == $style &&
'literal' == $use && 1 == $part_count && isset($parts[
'parameters'])) {
5864 $this->
debug(
'check whether the caller has wrapped the parameters');
5865 if (
'output' == $direction &&
'arraySimple' == $parametersArrayType && 1 == $parameter_count) {
5868 $this->
debug(
"change simple array to associative with 'parameters' element");
5869 $parameters[
'parameters'] = $parameters[0];
5870 unset($parameters[0]);
5872 if ((
'arrayStruct' == $parametersArrayType || 0 == $parameter_count) && !isset($parameters[
'parameters'])) {
5873 $this->
debug(
'check whether caller\'s parameters match the wrapped ones');
5875 $this->
debug(
'wrap the parameters for the caller');
5876 $parameters = [
'parameters' => $parameters];
5877 $parameter_count = 1;
5881 foreach ($parts as $name => $type) {
5882 $this->
debug(
"serializing part $name of type $type");
5884 if (isset($opData[$direction][
'encodingStyle']) && $encodingStyle != $opData[$direction][
'encodingStyle']) {
5885 $encodingStyle = $opData[$direction][
'encodingStyle'];
5886 $enc_style = $encodingStyle;
5892 if (
'arraySimple' == $parametersArrayType) {
5893 $p = array_shift($parameters);
5894 $this->
debug(
'calling serializeType w/indexed param');
5895 $xml .= $this->
serializeType($name, $type, $p, $use, $enc_style);
5896 } elseif (isset($parameters[$name])) {
5897 $this->
debug(
'calling serializeType w/named param');
5898 $xml .= $this->
serializeType($name, $type, $parameters[$name], $use, $enc_style);
5901 $this->
debug(
'calling serializeType w/null param');
5902 $xml .= $this->
serializeType($name, $type,
null, $use, $enc_style);
5906 $this->
debug(
'no parameters passed.');
5909 $this->
debug(
"serializeRPCParameters returning: $xml");
5929 $this->
debug(
"in serializeParameters: operation=$operation, direction=$direction, XMLSchemaVersion=$this->XMLSchemaVersion");
5932 if (
'input' != $direction &&
'output' != $direction) {
5933 $this->
debug(
'The value of the \$direction argument needs to be either "input" or "output"');
5934 $this->
setError(
'The value of the \$direction argument needs to be either "input" or "output"');
5938 $this->
debug(
'Unable to retrieve WSDL data for operation: ' . $operation);
5939 $this->
setError(
'Unable to retrieve WSDL data for operation: ' . $operation);
5942 $this->
debug(
'opData:');
5946 $encodingStyle =
'https://schemas.xmlsoap.org/soap/encoding/';
5947 if ((
'input' == $direction) && isset($opData[
'output'][
'encodingStyle']) && ($opData[
'output'][
'encodingStyle'] != $encodingStyle)) {
5948 $encodingStyle = $opData[
'output'][
'encodingStyle'];
5949 $enc_style = $encodingStyle;
5954 if (isset($opData[$direction][
'parts']) && (is_countable($opData[$direction][
'parts']) ? count($opData[$direction][
'parts']) : 0) > 0) {
5955 $use = $opData[$direction][
'use'];
5956 $this->
debug(
"use=$use");
5957 $this->
debug(
'got ' . (is_countable($opData[$direction][
'parts']) ? count($opData[$direction][
'parts']) : 0) .
' part(s)');
5958 if (is_array($parameters)) {
5960 $this->
debug(
'have ' . $parametersArrayType .
' parameters');
5961 foreach ($opData[$direction][
'parts'] as $name => $type) {
5962 $this->
debug(
'serializing part "'.$name.
'" of type "'.$type.
'"');
5964 if (isset($opData[$direction][
'encodingStyle']) && $encodingStyle != $opData[$direction][
'encodingStyle']) {
5965 $encodingStyle = $opData[$direction][
'encodingStyle'];
5966 $enc_style = $encodingStyle;
5972 if (
'arraySimple' == $parametersArrayType) {
5973 $p = array_shift($parameters);
5974 $this->
debug(
'calling serializeType w/indexed param');
5975 $xml .= $this->
serializeType($name, $type, $p, $use, $enc_style);
5976 } elseif (isset($parameters[$name])) {
5977 $this->
debug(
'calling serializeType w/named param');
5978 $xml .= $this->
serializeType($name, $type, $parameters[$name], $use, $enc_style);
5981 $this->
debug(
'calling serializeType w/null param');
5982 $xml .= $this->
serializeType($name, $type,
null, $use, $enc_style);
5986 $this->
debug(
'no parameters passed.');
5989 $this->
debug(
"serializeParameters returning: $xml");
6005 public function serializeType($name, $type, $value, $use=
'encoded', $encodingStyle=
false, $unqualified=
false)
6008 $this->
debug(
"in serializeType: name=$name, type=$type, use=$use, encodingStyle=$encodingStyle, unqualified=" . ($unqualified ?
'unqualified' :
'qualified'));
6010 if (
'encoded' == $use && $encodingStyle) {
6011 $encodingStyle =
' SOAP-ENV:encodingStyle="' . $encodingStyle .
'"';
6015 if (is_object($value) &&
'soapval' == get_class($value)) {
6016 if ($value->type_ns) {
6017 $type = $value->type_ns .
':' . $value->type;
6019 $this->
debug(
"in serializeType: soapval overrides type to $type");
6020 } elseif ($value->type) {
6021 $type = $value->type;
6023 $this->
debug(
"in serializeType: soapval overrides type to $type");
6026 $this->
debug(
'in serializeType: soapval does not override type');
6028 $attrs = $value->attributes;
6029 $value = $value->value;
6030 $this->
debug(
"in serializeType: soapval overrides value to $value");
6032 if (!is_array($value)) {
6033 $value[
'!'] = $value;
6035 foreach ($attrs as $n => $v) {
6036 $value[
'!' . $n] = $v;
6038 $this->
debug(
'in serializeType: soapval provides attributes');
6045 if (strpos($type,
':')) {
6046 $uqType = substr($type, strrpos($type,
':') + 1);
6047 $ns = substr($type, 0, strrpos($type,
':'));
6048 $this->
debug(
"in serializeType: got a prefixed type: $uqType, $ns");
6051 $this->
debug(
"in serializeType: expanded prefixed type: $uqType, $ns");
6054 if ($ns == $this->XMLSchemaVersion ||
'https://schemas.xmlsoap.org/soap/encoding/' == $ns) {
6055 $this->
debug(
'in serializeType: type namespace indicates XML Schema or SOAP Encoding type');
6056 if ($unqualified &&
'literal' == $use) {
6057 $elementNS =
' xmlns=""';
6061 if (
null === $value) {
6062 if (
'literal' == $use) {
6064 $xml =
"<$name$elementNS/>";
6067 $xml =
"<$name$elementNS xsi:nil=\"true\" xsi:type=\"" . $this->
getPrefixFromNamespace($ns) .
":$uqType\"/>";
6069 $this->
debug(
"in serializeType: returning: $xml");
6072 if (
'Array' == $uqType) {
6074 return $this->
serialize_val($value, $name,
false,
false,
false,
false, $use);
6076 if (
'boolean' == $uqType) {
6077 if ((is_string($value) &&
'false' == $value) || (! $value)) {
6083 if (
'string' == $uqType &&
'string' == gettype($value)) {
6086 if ((
'long' == $uqType ||
'unsignedLong' == $uqType) &&
'double' == gettype($value)) {
6087 $value = sprintf(
'%.0lf', $value);
6093 if (
'literal' == $use) {
6095 $xml =
"<$name$elementNS xsi:type=\"" . $this->
getPrefixFromNamespace($ns) .
":$uqType\">$value</$name>";
6097 $xml =
"<$name$elementNS>$value</$name>";
6100 $xml =
"<$name$elementNS xsi:type=\"" . $this->
getPrefixFromNamespace($ns) .
":$uqType\"$encodingStyle>$value</$name>";
6102 $this->
debug(
"in serializeType: returning: $xml");
6105 $this->
debug(
'custom type extends XML Schema or SOAP Encoding namespace (yuck)');
6106 } elseif (
'https://xml.apache.org/xml-soap' == $ns) {
6107 $this->
debug(
'in serializeType: appears to be Apache SOAP type');
6108 if (
'Map' == $uqType) {
6111 $this->
debug(
'in serializeType: Add namespace for Apache SOAP type');
6112 $tt_prefix =
'ns' . random_int(1000, 9999);
6113 $this->namespaces[$tt_prefix] =
'https://xml.apache.org/xml-soap';
6118 foreach ($value as $k => $v) {
6119 $this->
debug(
"serializing map element: key $k, value $v");
6120 $contents .=
'<item>';
6121 $contents .= $this->
serialize_val($k,
'key',
false,
false,
false,
false, $use);
6122 $contents .= $this->
serialize_val($v,
'value',
false,
false,
false,
false, $use);
6123 $contents .=
'</item>';
6125 if (
'literal' == $use) {
6127 $xml =
"<$name xsi:type=\"" . $tt_prefix .
":$uqType\">$contents</$name>";
6129 $xml =
"<$name>$contents</$name>";
6132 $xml =
"<$name xsi:type=\"" . $tt_prefix .
":$uqType\"$encodingStyle>$contents</$name>";
6134 $this->
debug(
"in serializeType: returning: $xml");
6137 $this->
debug(
'in serializeType: Apache SOAP type, but only support Map');
6142 $this->
debug(
"in serializeType: No namespace for type $type");
6146 if (!$typeDef = $this->
getTypeDef($uqType, $ns)) {
6147 $this->
setError(
"$type ($uqType) is not a supported type.");
6148 $this->
debug(
"in serializeType: $type ($uqType) is not a supported type.");
6151 $this->
debug(
'in serializeType: found typeDef');
6153 if (
'^' == substr($uqType, -1)) {
6154 $uqType = substr($uqType, 0, -1);
6157 if (!isset($typeDef[
'phpType'])) {
6158 $this->
setError(
"$type ($uqType) has no phpType.");
6159 $this->
debug(
"in serializeType: $type ($uqType) has no phpType.");
6162 $phpType = $typeDef[
'phpType'];
6163 $this->
debug(
"in serializeType: uqType: $uqType, ns: $ns, phptype: $phpType, arrayType: " . ($typeDef[
'arrayType'] ??
''));
6165 if (
'struct' == $phpType) {
6166 if (isset($typeDef[
'typeClass']) &&
'element' == $typeDef[
'typeClass']) {
6167 $elementName = $uqType;
6168 if (isset($typeDef[
'form']) && (
'qualified' == $typeDef[
'form'])) {
6169 $elementNS =
" xmlns=\"$ns\"";
6171 $elementNS =
' xmlns=""';
6174 $elementName = $name;
6176 $elementNS =
' xmlns=""';
6181 if (
null === $value) {
6182 if (
'literal' == $use) {
6184 $xml =
"<$elementName$elementNS/>";
6186 $xml =
"<$elementName$elementNS xsi:nil=\"true\" xsi:type=\"" . $this->
getPrefixFromNamespace($ns) .
":$uqType\"/>";
6188 $this->
debug(
"in serializeType: returning: $xml");
6191 if (is_object($value)) {
6192 $value = get_object_vars($value);
6194 if (is_array($value)) {
6196 if (
'literal' == $use) {
6198 $xml =
"<$elementName$elementNS$elementAttrs xsi:type=\"" . $this->
getPrefixFromNamespace($ns) .
":$uqType\">";
6200 $xml =
"<$elementName$elementNS$elementAttrs>";
6203 $xml =
"<$elementName$elementNS$elementAttrs xsi:type=\"" . $this->
getPrefixFromNamespace($ns) .
":$uqType\"$encodingStyle>";
6206 if (isset($typeDef[
'simpleContent']) &&
'true' == $typeDef[
'simpleContent']) {
6207 if (isset($value[
'!'])) {
6208 $xml .= $value[
'!'];
6209 $this->
debug(
"in serializeType: serialized simpleContent for type $type");
6211 $this->
debug(
"in serializeType: no simpleContent to serialize for type $type");
6217 $xml .=
"</$elementName>";
6219 $this->
debug(
'in serializeType: phpType is struct, but value is not an array');
6220 $this->
setError(
'phpType is struct, but value is not an array: see debug output for details');
6223 } elseif (
'array' == $phpType) {
6224 if (isset($typeDef[
'form']) && (
'qualified' == $typeDef[
'form'])) {
6225 $elementNS =
" xmlns=\"$ns\"";
6228 $elementNS =
' xmlns=""';
6233 if (
null === $value) {
6234 if (
'literal' == $use) {
6236 $xml =
"<$name$elementNS/>";
6238 $xml =
"<$name$elementNS xsi:nil=\"true\" xsi:type=\"" .
6246 $this->
debug(
"in serializeType: returning: $xml");
6249 if (isset($typeDef[
'multidimensional'])) {
6251 foreach ($value as $v) {
6252 $cols =
',' . (is_countable($v) ? count($v) : 0);
6253 $nv = array_merge($nv, $v);
6259 if (is_array($value) && count($value) >= 1) {
6260 $rows = count($value);
6262 foreach ($value as $k => $v) {
6263 $this->
debug(
"serializing array element: $k, $v of type: $typeDef[arrayType]");
6265 if (!in_array($typeDef[
'arrayType'], $this->typemap[
'https://www.w3.org/2001/XMLSchema'])) {
6266 $contents .= $this->
serializeType(
'item', $typeDef[
'arrayType'], $v, $use);
6268 $contents .= $this->
serialize_val($v,
'item', $typeDef[
'arrayType'],
null, $this->XMLSchemaVersion,
false, $use);
6277 if (
'literal' == $use) {
6278 $xml =
"<$name$elementNS>"
6282 $xml =
"<$name$elementNS xsi:type=\"".$this->getPrefixFromNamespace(
'https://schemas.xmlsoap.org/soap/encoding/').
':Array" '.
6285 .$this->getPrefixFromNamespace($this->
getPrefix($typeDef[
'arrayType']))
6286 .
':' . $this->
getLocalPart($typeDef[
'arrayType']) .
"[$rows$cols]\">"
6290 } elseif (
'scalar' == $phpType) {
6291 if (isset($typeDef[
'form']) && (
'qualified' == $typeDef[
'form'])) {
6292 $elementNS =
" xmlns=\"$ns\"";
6295 $elementNS =
' xmlns=""';
6300 if (
'literal' == $use) {
6302 $xml =
"<$name$elementNS xsi:type=\"" . $this->
getPrefixFromNamespace($ns) .
":$uqType\">$value</$name>";
6304 $xml =
"<$name$elementNS>$value</$name>";
6307 $xml =
"<$name$elementNS xsi:type=\"" . $this->
getPrefixFromNamespace($ns) .
":$uqType\"$encodingStyle>$value</$name>";
6310 $this->
debug(
"in serializeType: returning: $xml");
6326 $this->
debug(
"serializeComplexTypeAttributes for XML Schema type $ns:$uqType");
6328 if (isset($typeDef[
'extensionBase'])) {
6329 $nsx = $this->
getPrefix($typeDef[
'extensionBase']);
6330 $uqTypex = $this->
getLocalPart($typeDef[
'extensionBase']);
6334 if ($typeDefx = $this->
getTypeDef($uqTypex, $nsx)) {
6335 $this->
debug(
"serialize attributes for extension base $nsx:$uqTypex");
6338 $this->
debug(
"extension base $nsx:$uqTypex is not a supported type");
6341 if (isset($typeDef[
'attrs']) && is_array($typeDef[
'attrs'])) {
6342 $this->
debug(
"serialize attributes for XML Schema type $ns:$uqType");
6343 if (is_array($value)) {
6345 } elseif (is_object($value)) {
6346 $xvalue = get_object_vars($value);
6348 $this->
debug(
"value is neither an array nor an object for XML Schema type $ns:$uqType");
6351 foreach ($typeDef[
'attrs'] as $aName => $attrs) {
6352 if (isset($xvalue[
'!' . $aName])) {
6353 $xname =
'!' . $aName;
6354 $this->
debug(
"value provided for attribute $aName with key $xname");
6355 } elseif (isset($xvalue[$aName])) {
6357 $this->
debug(
"value provided for attribute $aName with key $xname");
6358 } elseif (isset($attrs[
'default'])) {
6359 $xname =
'!' . $aName;
6360 $xvalue[$xname] = $attrs[
'default'];
6361 $this->
debug(
'use default value of ' . $xvalue[$aName] .
' for attribute ' . $aName);
6364 $this->
debug(
"no value provided for attribute $aName");
6367 $xml .=
" $aName=\"" . $this->
expandEntities($xvalue[$xname]) .
'"';
6371 $this->
debug(
"no attributes to serialize for XML Schema type $ns:$uqType");
6390 $this->
debug(
"in serializeComplexTypeElements for XML Schema type $ns:$uqType");
6392 if (isset($typeDef[
'extensionBase'])) {
6393 $nsx = $this->
getPrefix($typeDef[
'extensionBase']);
6394 $uqTypex = $this->
getLocalPart($typeDef[
'extensionBase']);
6398 if ($typeDefx = $this->
getTypeDef($uqTypex, $nsx)) {
6399 $this->
debug(
"serialize elements for extension base $nsx:$uqTypex");
6402 $this->
debug(
"extension base $nsx:$uqTypex is not a supported type");
6405 if (isset($typeDef[
'elements']) && is_array($typeDef[
'elements'])) {
6406 $this->
debug(
"in serializeComplexTypeElements, serialize elements for XML Schema type $ns:$uqType");
6407 if (is_array($value)) {
6409 } elseif (is_object($value)) {
6410 $xvalue = get_object_vars($value);
6412 $this->
debug(
"value is neither an array nor an object for XML Schema type $ns:$uqType");
6416 if (count($typeDef[
'elements']) != count($xvalue)) {
6419 foreach ($typeDef[
'elements'] as $eName => $attrs) {
6420 if (!isset($xvalue[$eName])) {
6421 if (isset($attrs[
'default'])) {
6422 $xvalue[$eName] = $attrs[
'default'];
6423 $this->
debug(
'use default value of ' . $xvalue[$eName] .
' for element ' . $eName);
6427 if (isset($optionals)
6428 && (!isset($xvalue[$eName]))
6429 && ((!isset($attrs[
'nillable'])) ||
'true' != $attrs[
'nillable'])
6431 if (isset($attrs[
'minOccurs']) &&
'0' <> $attrs[
'minOccurs']) {
6432 $this->
debug(
"apparent error: no value provided for element $eName with minOccurs=" . $attrs[
'minOccurs']);
6435 $this->
debug(
"no value provided for complexType element $eName and element is not nillable, so serialize nothing");
6438 if (isset($xvalue[$eName])) {
6439 $v = $xvalue[$eName];
6443 if (isset($attrs[
'form'])) {
6444 $unqualified = (
'unqualified' == $attrs[
'form']);
6446 $unqualified =
false;
6448 if (isset($attrs[
'maxOccurs']) && (
'unbounded' == $attrs[
'maxOccurs'] || $attrs[
'maxOccurs'] > 1) && isset($v) && is_array($v) &&
'arraySimple' == $this->
isArraySimpleOrStruct($v)) {
6450 foreach ($vv as $k => $v) {
6451 if (isset($attrs[
'type']) || isset($attrs[
'ref'])) {
6453 $xml .= $this->
serializeType($eName, $attrs[
'type'] ?? $attrs[
'ref'], $v, $use, $encodingStyle, $unqualified);
6456 $this->
debug(
"calling serialize_val() for $v, $eName, false, false, false, false, $use");
6457 $xml .= $this->
serialize_val($v, $eName,
false,
false,
false,
false, $use);
6461 if (
null === $v && isset($attrs[
'minOccurs']) &&
'0' == $attrs[
'minOccurs']) {
6463 } elseif (
null === $v && isset($attrs[
'nillable']) &&
'true' == $attrs[
'nillable']) {
6465 $xml .= $this->
serializeType($eName, $attrs[
'type'] ?? $attrs[
'ref'], $v, $use, $encodingStyle, $unqualified);
6466 } elseif (isset($attrs[
'type']) || isset($attrs[
'ref'])) {
6468 $xml .= $this->
serializeType($eName, $attrs[
'type'] ?? $attrs[
'ref'], $v, $use, $encodingStyle, $unqualified);
6471 $this->
debug(
"calling serialize_val() for $v, $eName, false, false, false, false, $use");
6472 $xml .= $this->
serialize_val($v, $eName,
false,
false,
false,
false, $use);
6478 $this->
debug(
"no elements to serialize for XML Schema type $ns:$uqType");
6497 public function addComplexType($name, $typeClass=
'complexType', $phpType=
'array', $compositor=
'', $restrictionBase=
'', $elements= [], $attrs= [], $arrayType=
'')
6499 if (count($elements) > 0) {
6501 foreach ($elements as $n => $e) {
6504 foreach ($e as $k => $v) {
6505 $k = strpos($k,
':') ? $this->
expandQname($k) : $k;
6506 $v = strpos($v,
':') ? $this->
expandQname($v) : $v;
6509 $eElements[$n] = $ee;
6511 $elements = $eElements;
6514 if (count($attrs) > 0) {
6515 foreach ($attrs as $n => $a) {
6517 foreach ($a as $k => $v) {
6518 $k = strpos($k,
':') ? $this->
expandQname($k) : $k;
6519 $v = strpos($v,
':') ? $this->
expandQname($v) : $v;
6527 $restrictionBase = strpos($restrictionBase,
':') ? $this->
expandQname($restrictionBase) : $restrictionBase;
6528 $arrayType = strpos($arrayType,
':') ? $this->
expandQname($arrayType) : $arrayType;
6530 $typens = $this->namespaces[
'types'] ?? $this->namespaces[
'tns'];
6531 $this->schemas[$typens][0]->addComplexType($name, $typeClass, $phpType, $compositor, $restrictionBase, $elements, $attrs, $arrayType);
6545 public function addSimpleType($name, $restrictionBase=
'', $typeClass=
'simpleType', $phpType=
'scalar', $enumeration= [])
6547 $restrictionBase = strpos($restrictionBase,
':') ? $this->
expandQname($restrictionBase) : $restrictionBase;
6549 $typens = $this->namespaces[
'types'] ?? $this->namespaces[
'tns'];
6550 $this->schemas[$typens][0]->addSimpleType($name, $restrictionBase, $typeClass, $phpType, $enumeration);
6562 $typens = $this->namespaces[
'types'] ?? $this->namespaces[
'tns'];
6563 $this->schemas[$typens][0]->addElement($attrs);
6581 public function addOperation($name, $in =
false, $out =
false, $namespace =
false, $soapaction =
false, $style =
'rpc', $use =
'encoded', $documentation =
'', $encodingStyle =
'')
6583 if (
'encoded' == $use &&
'' == $encodingStyle) {
6584 $encodingStyle =
'https://schemas.xmlsoap.org/soap/encoding/';
6587 if (
'document' == $style) {
6589 foreach ($in as $n => $t) {
6590 $elements[$n] = [
'name' => $n,
'type' => $t,
'form' =>
'unqualified'];
6592 $this->
addComplexType($name .
'RequestType',
'complexType',
'struct',
'all',
'', $elements);
6593 $this->
addElement([
'name' => $name,
'type' => $name .
'RequestType']);
6594 $in = [
'parameters' =>
'tns:' . $name .
'^'];
6597 foreach ($out as $n => $t) {
6598 $elements[$n] = [
'name' => $n,
'type' => $t,
'form' =>
'unqualified'];
6600 $this->
addComplexType($name .
'ResponseType',
'complexType',
'struct',
'all',
'', $elements);
6601 $this->
addElement([
'name' => $name .
'Response',
'type' => $name .
'ResponseType',
'form' =>
'qualified']);
6602 $out = [
'parameters' =>
'tns:' . $name .
'Response' .
'^'];
6606 $this->bindings[ $this->serviceName .
'Binding' ][
'operations'][$name] =
6609 'binding' => $this->serviceName .
'Binding',
6610 'endpoint' => $this->endpoint,
6611 'soapAction' => $soapaction,
6615 'namespace' => $namespace,
6616 'encodingStyle' => $encodingStyle,
6617 'message' => $name .
'Request',
6622 'namespace' => $namespace,
6623 'encodingStyle' => $encodingStyle,
6624 'message' => $name .
'Response',
6627 'namespace' => $namespace,
6628 'transport' =>
'https://schemas.xmlsoap.org/soap/http',
6629 'documentation' => $documentation
6634 foreach ($in as $pName => $pType) {
6635 if (strpos($pType,
':')) {
6638 $this->messages[$name.
'Request'][$pName] = $pType;
6641 $this->messages[$name.
'Request']=
'0';
6644 foreach ($out as $pName => $pType) {
6645 if (strpos($pType,
':')) {
6648 $this->messages[$name.
'Response'][$pName] = $pType;
6651 $this->messages[$name.
'Response']=
'0';
6673 public $xml_encoding =
'';
6674 public $method =
'';
6675 public $root_struct =
'';
6676 public $root_struct_name =
'';
6677 public $root_struct_namespace =
'';
6678 public $root_header =
'';
6679 public $document =
'';
6681 public $status =
'';
6682 public $position = 0;
6684 public $default_namespace =
'';
6685 public $namespaces = [];
6686 public $message = [];
6687 public $parent =
'';
6688 public $fault =
false;
6689 public $fault_code =
'';
6690 public $fault_str =
'';
6691 public $fault_detail =
'';
6692 public $depth_array = [];
6693 public $debug_flag =
true;
6694 public $soapresponse =
null;
6695 public $soapheader =
null;
6696 public $responseHeaders =
'';
6697 public $body_position = 0;
6702 public $multirefs = [];
6704 public $decode_utf8 =
true;
6715 public function __construct($xml, $encoding=
'UTF-8', $method=
'', $decode_utf8=
true)
6717 parent::__construct();
6719 $this->xml_encoding = $encoding;
6720 $this->method = $method;
6721 $this->decode_utf8 = $decode_utf8;
6726 $pos_xml = strpos($xml,
'<?xml');
6727 if (
false !== $pos_xml) {
6728 $xml_decl = substr($xml, $pos_xml, strpos($xml,
'?>', $pos_xml + 2) - $pos_xml + 1);
6729 if (preg_match(
"/encoding=[\"']([^\"']*)[\"']/", $xml_decl, $res)) {
6730 $xml_encoding = $res[1];
6731 if (strtoupper($xml_encoding) != $encoding) {
6732 $err =
"Charset from HTTP Content-Type '" . $encoding .
"' does not match encoding from XML declaration '" . $xml_encoding .
"'";
6734 if (
'ISO-8859-1' != $encoding ||
'UTF-8' != strtoupper($xml_encoding)) {
6740 $this->
debug(
'Charset from HTTP Content-Type matches encoding from XML declaration');
6743 $this->
debug(
'No encoding specified in XML declaration');
6746 $this->
debug(
'No XML declaration');
6748 $this->
debug(
'Entering nusoap_parser(), length='.strlen($xml).
', encoding='.$encoding);
6750 $this->parser = xml_parser_create($this->xml_encoding);
6753 xml_parser_set_option($this->parser, XML_OPTION_CASE_FOLDING, 0);
6754 xml_parser_set_option($this->parser, XML_OPTION_TARGET_ENCODING, $this->xml_encoding);
6756 xml_set_object($this->parser, $this);
6758 xml_set_element_handler($this->parser,
'start_element',
'end_element');
6759 xml_set_character_data_handler($this->parser,
'character_data');
6762 if (!xml_parse($this->parser, $xml,
true)) {
6764 $err = sprintf(
'XML error parsing SOAP payload on line %d: %s',
6765 xml_get_current_line_number($this->parser),
6766 xml_error_string(xml_get_error_code($this->parser)));
6768 $this->
debug(
"XML payload:\n" . $xml);
6771 $this->
debug(
'in nusoap_parser ctor, message:');
6773 $this->
debug(
'parsed successfully, found root struct: '.$this->root_struct.
' of name '.$this->root_struct_name);
6775 $this->soapresponse = $this->message[$this->root_struct][
'result'];
6777 if (
'' != $this->root_header && isset($this->message[$this->root_header][
'result'])) {
6778 $this->soapheader = $this->message[$this->root_header][
'result'];
6781 if (count($this->multirefs) > 0) {
6782 foreach ($this->multirefs as $id => $hrefs) {
6783 $this->
debug(
'resolving multirefs for id: '.$id);
6784 $idVal = $this->
buildVal($this->ids[$id]);
6785 if (is_array($idVal) && isset($idVal[
'!id'])) {
6786 unset($idVal[
'!id']);
6788 foreach ($hrefs as $refPos => $ref) {
6789 $this->
debug(
'resolving href at pos '.$refPos);
6790 $this->multirefs[$id][$refPos] = $idVal;
6795 xml_parser_free($this->parser);
6797 $this->
debug(
'xml was empty, didn\'t parse!');
6798 $this->
setError(
'xml was empty, didn\'t parse!');
6814 $pos = $this->position++;
6816 $this->message[$pos] = [
'pos' => $pos,
'children' =>
'',
'cdata' =>
''];
6819 $this->message[$pos][
'depth'] = $this->depth++;
6823 $this->message[$this->parent][
'children'] .=
'|'.$pos;
6826 $this->message[$pos][
'parent'] = $this->parent;
6828 $this->parent = $pos;
6830 $this->depth_array[$this->depth] = $pos;
6832 if (strpos($name,
':')) {
6834 $prefix = substr($name, 0, strpos($name,
':'));
6836 $name = substr(strstr($name,
':'), 1);
6839 if (
'Envelope' == $name &&
'' == $this->status) {
6840 $this->status =
'envelope';
6841 } elseif (
'Header' == $name &&
'envelope' == $this->status) {
6842 $this->root_header = $pos;
6843 $this->status =
'header';
6844 } elseif (
'Body' == $name &&
'envelope' == $this->status) {
6845 $this->status =
'body';
6846 $this->body_position = $pos;
6848 } elseif (
'body' == $this->status && $pos == ($this->body_position + 1)) {
6849 $this->status =
'method';
6850 $this->root_struct_name = $name;
6851 $this->root_struct = $pos;
6852 $this->message[$pos][
'type'] =
'struct';
6853 $this->
debug(
"found root struct $this->root_struct_name, pos $this->root_struct");
6856 $this->message[$pos][
'status'] = $this->status;
6858 $this->message[$pos][
'name'] = htmlspecialchars($name);
6860 $this->message[$pos][
'attrs'] = $attrs;
6864 foreach ($attrs as $key => $value) {
6868 if (
'xmlns' == $key_prefix) {
6869 if (preg_match(
'/^http:\/\/www.w3.org\/[0-9]{4}\/XMLSchema$/', $value)) {
6870 $this->XMLSchemaVersion = $value;
6871 $this->namespaces[
'xsd'] = $this->XMLSchemaVersion;
6872 $this->namespaces[
'xsi'] = $this->XMLSchemaVersion.
'-instance';
6874 $this->namespaces[$key_localpart] = $value;
6876 if ($name == $this->root_struct_name) {
6877 $this->methodNamespace = $value;
6880 } elseif (
'type' == $key_localpart) {
6881 if (isset($this->message[$pos][
'type']) &&
'array' == $this->message[$pos][
'type']) {
6884 $value_prefix = $this->
getPrefix($value);
6886 $this->message[$pos][
'type'] = $value_localpart;
6887 $this->message[$pos][
'typePrefix'] = $value_prefix;
6888 if (isset($this->namespaces[$value_prefix])) {
6889 $this->message[$pos][
'type_namespace'] = $this->namespaces[$value_prefix];
6890 } elseif (isset($attrs[
'xmlns:'.$value_prefix])) {
6891 $this->message[$pos][
'type_namespace'] = $attrs[
'xmlns:'.$value_prefix];
6895 } elseif (
'arrayType' == $key_localpart) {
6896 $this->message[$pos][
'type'] =
'array';
6905 $expr =
'/([A-Za-z0-9_]+):([A-Za-z]+[A-Za-z0-9_]+)\[([0-9]+),?([0-9]*)\]/';
6906 if (preg_match($expr, $value, $regs)) {
6907 $this->message[$pos][
'typePrefix'] = $regs[1];
6908 $this->message[$pos][
'arrayTypePrefix'] = $regs[1];
6909 if (isset($this->namespaces[$regs[1]])) {
6910 $this->message[$pos][
'arrayTypeNamespace'] = $this->namespaces[$regs[1]];
6911 } elseif (isset($attrs[
'xmlns:'.$regs[1]])) {
6912 $this->message[$pos][
'arrayTypeNamespace'] = $attrs[
'xmlns:'.$regs[1]];
6914 $this->message[$pos][
'arrayType'] = $regs[2];
6915 $this->message[$pos][
'arraySize'] = $regs[3];
6916 $this->message[$pos][
'arrayCols'] = $regs[4];
6919 } elseif (
'nil' == $key_localpart) {
6920 $this->message[$pos][
'nil'] = (
'true' == $value ||
'1' == $value);
6922 } elseif (
'href' != $key &&
'xmlns' != $key &&
'encodingStyle' != $key_localpart &&
'root' != $key_localpart) {
6923 $this->message[$pos][
'xattrs'][
'!' . $key] = $value;
6926 if (
'xmlns' == $key) {
6927 $this->default_namespace = $value;
6931 $this->ids[$value] = $pos;
6934 if (
'root' == $key_localpart && 1 == $value) {
6935 $this->status =
'method';
6936 $this->root_struct_name = $name;
6937 $this->root_struct = $pos;
6938 $this->
debug(
"found root struct $this->root_struct_name, pos $pos");
6941 $attstr .=
" $key=\"$value\"";
6944 if (isset($prefix)) {
6945 $this->message[$pos][
'namespace'] = $this->namespaces[$prefix];
6946 $this->default_namespace = $this->namespaces[$prefix];
6948 $this->message[$pos][
'namespace'] = $this->default_namespace;
6950 if (
'header' == $this->status) {
6951 if ($this->root_header != $pos) {
6952 $this->responseHeaders .=
'<' . (isset($prefix) ? $prefix .
':' :
'') .
"$name$attstr>";
6954 } elseif (
'' != $this->root_struct_name) {
6955 $this->document .=
'<' . (isset($prefix) ? $prefix .
':' :
'') .
"$name$attstr>";
6969 $pos = $this->depth_array[$this->depth--];
6972 if (strpos($name,
':')) {
6974 $prefix = substr($name, 0, strpos($name,
':'));
6976 $name = substr(strstr($name,
':'), 1);
6980 if (isset($this->body_position) && $pos > $this->body_position) {
6982 if (isset($this->message[$pos][
'attrs'][
'href'])) {
6984 $id = substr($this->message[$pos][
'attrs'][
'href'], 1);
6986 $this->multirefs[$id][$pos] =
'placeholder';
6988 $this->message[$pos][
'result'] =& $this->multirefs[$id][$pos];
6990 } elseif (
'' != $this->message[$pos][
'children']) {
6992 if (!isset($this->message[$pos][
'result'])) {
6993 $this->message[$pos][
'result'] = $this->
buildVal($pos);
6996 } elseif (isset($this->message[$pos][
'xattrs'])) {
6997 if (isset($this->message[$pos][
'nil']) && $this->message[$pos][
'nil']) {
6998 $this->message[$pos][
'xattrs'][
'!'] =
null;
6999 } elseif (isset($this->message[$pos][
'cdata']) &&
'' != trim($this->message[$pos][
'cdata'])) {
7000 if (isset($this->message[$pos][
'type'])) {
7001 $this->message[$pos][
'xattrs'][
'!'] = $this->
decodeSimple($this->message[$pos][
'cdata'], $this->message[$pos][
'type'], $this->message[$pos][
'type_namespace'] ??
'');
7003 $parent = $this->message[$pos][
'parent'];
7004 if (isset($this->message[$parent][
'type']) && (
'array' == $this->message[$parent][
'type']) && isset($this->message[$parent][
'arrayType'])) {
7005 $this->message[$pos][
'xattrs'][
'!'] = $this->
decodeSimple($this->message[$pos][
'cdata'], $this->message[$parent][
'arrayType'], $this->message[$parent][
'arrayTypeNamespace'] ??
'');
7007 $this->message[$pos][
'xattrs'][
'!'] = $this->message[$pos][
'cdata'];
7011 $this->message[$pos][
'result'] = $this->message[$pos][
'xattrs'];
7015 if (isset($this->message[$pos][
'nil']) && $this->message[$pos][
'nil']) {
7016 $this->message[$pos][
'xattrs'][
'!'] =
null;
7017 } elseif (isset($this->message[$pos][
'type'])) {
7018 $this->message[$pos][
'result'] = $this->
decodeSimple($this->message[$pos][
'cdata'], $this->message[$pos][
'type'], $this->message[$pos][
'type_namespace'] ??
'');
7020 $parent = $this->message[$pos][
'parent'];
7021 if (isset($this->message[$parent][
'type']) && (
'array' == $this->message[$parent][
'type']) && isset($this->message[$parent][
'arrayType'])) {
7022 $this->message[$pos][
'result'] = $this->
decodeSimple($this->message[$pos][
'cdata'], $this->message[$parent][
'arrayType'], $this->message[$parent][
'arrayTypeNamespace'] ??
'');
7024 $this->message[$pos][
'result'] = $this->message[$pos][
'cdata'];
7042 if (
'header' == $this->status) {
7043 if ($this->root_header != $pos) {
7044 $this->responseHeaders .=
'</' . (isset($prefix) ? $prefix .
':' :
'') .
"$name>";
7046 } elseif ($pos >= $this->root_struct) {
7047 $this->document .=
'</' . (isset($prefix) ? $prefix .
':' :
'') .
"$name>";
7050 if ($pos == $this->root_struct) {
7051 $this->status =
'body';
7052 $this->root_struct_namespace = $this->message[$pos][
'namespace'];
7053 } elseif ($pos == $this->root_header) {
7054 $this->status =
'envelope';
7055 } elseif (
'Body' == $name &&
'body' == $this->status) {
7056 $this->status =
'envelope';
7057 } elseif (
'Header' == $name &&
'header' == $this->status) {
7058 $this->status =
'envelope';
7059 } elseif (
'Envelope' == $name &&
'envelope' == $this->status) {
7063 $this->parent = $this->message[$pos][
'parent'];
7075 $pos = $this->depth_array[$this->depth];
7076 if (
'UTF-8' == $this->xml_encoding) {
7080 if ($this->decode_utf8) {
7081 $data = utf8_decode($data);
7084 $this->message[$pos][
'cdata'] .= $data;
7086 if (
'header' == $this->status) {
7087 $this->responseHeaders .= $data;
7089 $this->document .= $data;
7102 return $this->soapresponse;
7113 return $this->soapresponse;
7124 return $this->soapheader;
7135 return $this->responseHeaders;
7150 if ((!isset($type)) ||
'string' == $type ||
'long' == $type ||
'unsignedLong' == $type) {
7151 return (
string) $value;
7153 if (
'int' == $type ||
'integer' == $type ||
'short' == $type ||
'byte' == $type) {
7154 return (
int) $value;
7156 if (
'float' == $type ||
'double' == $type ||
'decimal' == $type) {
7157 return (
double) $value;
7159 if (
'boolean' == $type) {
7160 if (
'false' == strtolower($value) ||
'f' == strtolower($value)) {
7163 return (
boolean) $value;
7165 if (
'base64' == $type ||
'base64Binary' == $type) {
7166 $this->
debug(
'Decode base64 value');
7167 return base64_decode($value);
7170 if (
'nonPositiveInteger' == $type ||
'negativeInteger' == $type
7171 ||
'nonNegativeInteger' == $type
7172 ||
'positiveInteger' == $type
7173 ||
'unsignedInt' == $type
7174 ||
'unsignedShort' == $type
7175 ||
'unsignedByte' == $type) {
7176 return (
int) $value;
7179 if (
'array' == $type) {
7183 return (
string) $value;
7197 if (!isset($this->message[$pos][
'type'])) {
7198 $this->message[$pos][
'type'] =
'';
7200 $this->
debug(
'in buildVal() for '.$this->message[$pos][
'name'].
"(pos $pos) of type ".$this->message[$pos][
'type']);
7202 if (
'' != $this->message[$pos][
'children']) {
7203 $this->
debug(
'in buildVal, there are children');
7204 $children = explode(
'|', $this->message[$pos][
'children']);
7205 array_shift($children);
7207 if (isset($this->message[$pos][
'arrayCols']) &&
'' != $this->message[$pos][
'arrayCols']) {
7210 foreach ($children as $child_pos) {
7211 $this->
debug(
"in buildVal, got an MD array element: $r, $c");
7212 $params[$r][] = $this->message[$child_pos][
'result'];
7214 if ($c == $this->message[$pos][
'arrayCols']) {
7220 } elseif (
'array' == $this->message[$pos][
'type'] ||
'Array' == $this->message[$pos][
'type']) {
7221 $this->
debug(
'in buildVal, adding array '.$this->message[$pos][
'name']);
7222 foreach ($children as $child_pos) {
7223 $params[] = &$this->message[$child_pos][
'result'];
7226 } elseif (
'Map' == $this->message[$pos][
'type'] &&
'https://xml.apache.org/xml-soap' == $this->message[$pos][
'type_namespace']) {
7227 $this->
debug(
'in buildVal, Java Map '.$this->message[$pos][
'name']);
7228 foreach ($children as $child_pos) {
7229 $kv = explode(
'|', $this->message[$child_pos][
'children']);
7230 $params[$this->message[$kv[1]][
'result']] = &$this->message[$kv[2]][
'result'];
7236 $this->
debug(
'in buildVal, adding Java Vector or generic compound type '.$this->message[$pos][
'name']);
7237 if (
'Vector' == $this->message[$pos][
'type'] &&
'https://xml.apache.org/xml-soap' == $this->message[$pos][
'type_namespace']) {
7243 foreach ($children as $child_pos) {
7245 $params[] = &$this->message[$child_pos][
'result'];
7247 if (isset($params[$this->message[$child_pos][
'name']])) {
7249 if ((!is_array($params[$this->message[$child_pos][
'name']])) || (!isset($params[$this->message[$child_pos][
'name']][0]))) {
7250 $params[$this->message[$child_pos][
'name']] = [$params[$this->message[$child_pos][
'name']]];
7252 $params[$this->message[$child_pos][
'name']][] = &$this->message[$child_pos][
'result'];
7254 $params[$this->message[$child_pos][
'name']] = &$this->message[$child_pos][
'result'];
7259 if (isset($this->message[$pos][
'xattrs'])) {
7260 $this->
debug(
'in buildVal, handling attributes');
7261 foreach ($this->message[$pos][
'xattrs'] as $n => $v) {
7266 if (isset($this->message[$pos][
'cdata']) &&
'' != trim($this->message[$pos][
'cdata'])) {
7267 $this->
debug(
'in buildVal, handling simpleContent');
7268 if (isset($this->message[$pos][
'type'])) {
7269 $params[
'!'] = $this->
decodeSimple($this->message[$pos][
'cdata'], $this->message[$pos][
'type'], $this->message[$pos][
'type_namespace'] ??
'');
7271 $parent = $this->message[$pos][
'parent'];
7272 if (isset($this->message[$parent][
'type']) && (
'array' == $this->message[$parent][
'type']) && isset($this->message[$parent][
'arrayType'])) {
7273 $params[
'!'] = $this->
decodeSimple($this->message[$pos][
'cdata'], $this->message[$parent][
'arrayType'], $this->message[$parent][
'arrayTypeNamespace'] ??
'');
7275 $params[
'!'] = $this->message[$pos][
'cdata'];
7279 $ret = is_array($params) ? $params : [];
7280 $this->
debug(
'in buildVal, return:');
7284 $this->
debug(
'in buildVal, no children, building scalar');
7285 $cdata = $this->message[$pos][
'cdata'] ??
'';
7286 if (isset($this->message[$pos][
'type'])) {
7287 $ret = $this->
decodeSimple($cdata, $this->message[$pos][
'type'], $this->message[$pos][
'type_namespace'] ??
'');
7288 $this->
debug(
"in buildVal, return: $ret");
7291 $parent = $this->message[$pos][
'parent'];
7292 if (isset($this->message[$parent][
'type']) && (
'array' == $this->message[$parent][
'type']) && isset($this->message[$parent][
'arrayType'])) {
7293 $ret = $this->
decodeSimple($cdata, $this->message[$parent][
'arrayType'], $this->message[$parent][
'arrayTypeNamespace'] ??
'');
7294 $this->
debug(
"in buildVal, return: $ret");
7297 $ret = $this->message[$pos][
'cdata'];
7298 $this->
debug(
"in buildVal, return: $ret");
7338 public $username =
'';
7339 public $password =
'';
7340 public $authtype =
'';
7341 public $certRequest = [];
7342 public $requestHeaders =
false;
7343 public $responseHeaders =
'';
7344 public $responseHeader =
null;
7345 public $document =
'';
7347 public $forceEndpoint =
'';
7348 public $proxyhost =
'';
7349 public $proxyport =
'';
7350 public $proxyusername =
'';
7351 public $proxypassword =
'';
7352 public $portName =
'';
7353 public $xml_encoding =
'';
7354 public $http_encoding =
false;
7355 public $timeout = 0;
7356 public $response_timeout = 30;
7357 public $endpointType =
'';
7358 public $persistentConnection =
false;
7359 public $defaultRpcParams =
false;
7360 public $request =
'';
7361 public $response =
'';
7362 public $responseData =
'';
7363 public $cookies = [];
7364 public $decode_utf8 =
true;
7365 public $operations = [];
7366 public $curl_options = [];
7367 public $bindingType =
'';
7368 public $use_curl =
false;
7387 public $faultstring;
7392 public $faultdetail;
7408 public function __construct($endpoint, $wsdl =
false, $proxyhost =
false, $proxyport =
false, $proxyusername =
false, $proxypassword =
false, $timeout = 0, $response_timeout = 30, $portName =
'')
7410 parent::__construct();
7411 $this->endpoint = $endpoint;
7412 $this->proxyhost = $proxyhost;
7413 $this->proxyport = $proxyport;
7414 $this->proxyusername = $proxyusername;
7415 $this->proxypassword = $proxypassword;
7416 $this->timeout = $timeout;
7417 $this->response_timeout = $response_timeout;
7418 $this->portName = $portName;
7420 $this->
debug(
"ctor wsdl=$wsdl timeout=$timeout response_timeout=$response_timeout");
7425 if (is_object($endpoint) && (
'wsdl' == get_class($endpoint))) {
7426 $this->
wsdl = $endpoint;
7427 $this->endpoint = $this->
wsdl->wsdl;
7428 $this->wsdlFile = $this->endpoint;
7429 $this->
debug(
'existing wsdl instance created from ' . $this->endpoint);
7432 $this->wsdlFile = $this->endpoint;
7434 $this->
debug(
'will use lazy evaluation of wsdl from ' . $this->endpoint);
7436 $this->endpointType =
'wsdl';
7438 $this->
debug(
"instantiate SOAP with endpoint at $endpoint");
7439 $this->endpointType =
'soap';
7468 public function call($operation, $params= [], $namespace=
'https://tempuri.org', $soapAction=
'', $headers=
false, $rpcParams=
null, $style=
'rpc', $use=
'encoded')
7470 $this->operation = $operation;
7471 $this->fault =
false;
7473 $this->request =
'';
7474 $this->response =
'';
7475 $this->responseData =
'';
7476 $this->faultstring =
'';
7477 $this->faultcode =
'';
7480 $this->
debug(
"call: operation=$operation, namespace=$namespace, soapAction=$soapAction, rpcParams=$rpcParams, style=$style, use=$use, endpointType=$this->endpointType");
7484 $this->requestHeaders = $headers;
7486 if (
'wsdl' == $this->endpointType &&
null === $this->
wsdl) {
7493 if (
'wsdl' == $this->endpointType && $opData = $this->
getOperationData($operation)) {
7495 $this->opData = $opData;
7496 $this->
debug(
'found operation');
7498 if (isset($opData[
'soapAction'])) {
7499 $soapAction = $opData[
'soapAction'];
7501 if (! $this->forceEndpoint) {
7502 $this->endpoint = $opData[
'endpoint'];
7504 $this->endpoint = $this->forceEndpoint;
7506 $namespace = $opData[
'input'][
'namespace'] ?? $namespace;
7507 $style = $opData[
'style'];
7508 $use = $opData[
'input'][
'use'];
7510 if (
'' != $namespace && !isset($this->
wsdl->namespaces[$namespace])) {
7511 $nsPrefix =
'ns' . random_int(1000, 9999);
7512 $this->
wsdl->namespaces[$nsPrefix] = $namespace;
7516 if (is_string($params)) {
7517 $this->
debug(
"serializing param string for WSDL operation $operation");
7519 } elseif (is_array($params)) {
7520 $this->
debug(
"serializing param array for WSDL operation $operation");
7523 $this->
debug(
'params must be array or string');
7524 $this->
setError(
'params must be array or string');
7527 $usedNamespaces = $this->
wsdl->usedNamespaces;
7528 if (isset($opData[
'input'][
'encodingStyle'])) {
7529 $encodingStyle = $opData[
'input'][
'encodingStyle'];
7531 $encodingStyle =
'';
7536 $this->
debug(
'got wsdl error: '.$errstr);
7537 $this->
setError(
'wsdl error: '.$errstr);
7540 } elseif (
'wsdl' == $this->endpointType) {
7544 $this->
setError(
'operation '.$operation.
' not present in WSDL.');
7545 $this->
debug(
"operation '$operation' not present in WSDL.");
7550 $nsPrefix =
'ns' . random_int(1000, 9999);
7553 if (is_string($params)) {
7554 $this->
debug(
"serializing param string for operation $operation");
7556 } elseif (is_array($params)) {
7557 $this->
debug(
"serializing param array for operation $operation");
7558 foreach ($params as $k => $v) {
7559 $payload .= $this->
serialize_val($v, $k,
false,
false,
false,
false, $use);
7562 $this->
debug(
'params must be array or string');
7563 $this->
setError(
'params must be array or string');
7566 $usedNamespaces = [];
7567 if (
'encoded' == $use) {
7568 $encodingStyle =
'https://schemas.xmlsoap.org/soap/encoding/';
7570 $encodingStyle =
'';
7574 if (
'rpc' == $style) {
7575 if (
'literal' == $use) {
7576 $this->
debug(
'wrapping RPC request with literal method element');
7579 $payload =
"<$nsPrefix:$operation xmlns:$nsPrefix=\"$namespace\">" .
7581 "</$nsPrefix:$operation>";
7583 $payload =
"<$operation>" . $payload .
"</$operation>";
7586 $this->
debug(
'wrapping RPC request with encoded method element');
7588 $payload =
"<$nsPrefix:$operation xmlns:$nsPrefix=\"$namespace\">" .
7590 "</$nsPrefix:$operation>";
7592 $payload =
"<$operation>" .
7599 $soapmsg = $this->
serializeEnvelope($payload, $this->requestHeaders, $usedNamespaces, $style, $use, $encodingStyle);
7600 $this->
debug(
"endpoint=$this->endpoint, soapAction=$soapAction, namespace=$namespace, style=$style, use=$use, encodingStyle=$encodingStyle");
7601 $this->
debug(
'SOAP message length=' . strlen($soapmsg) .
' contents (max 1000 bytes)=' . substr($soapmsg, 0, 1000));
7603 $return = $this->
send($this->
getHTTPBody($soapmsg), $soapAction, $this->timeout, $this->response_timeout);
7605 $this->
debug(
'Error: '.$errstr);
7608 $this->
return = $return;
7609 $this->
debug(
'sent message successfully and got a(n) '.gettype($return));
7613 if (is_array($return) && isset($return[
'faultcode'])) {
7614 $this->
debug(
'got fault');
7615 $this->
setError($return[
'faultcode'].
': '.$return[
'faultstring']);
7616 $this->fault =
true;
7617 foreach ($return as $k => $v) {
7619 $this->
debug(
"$k = $v<br>");
7622 } elseif (
'document' == $style) {
7628 if (is_array($return)) {
7631 if (count($return) > 1) {
7635 $return = array_shift($return);
7636 $this->
debug(
'return shifted value: ');
7656 $this->
debug(
'checkWSDL');
7661 $this->
debug(
'got wsdl error: '.$errstr);
7662 $this->
setError(
'wsdl error: '.$errstr);
7663 } elseif ($this->operations = $this->
wsdl->
getOperations($this->portName,
'soap')) {
7666 $this->bindingType =
'soap';
7667 $this->
debug(
'got '.count($this->operations).
' operations from wsdl '.$this->wsdlFile.
' for binding type '.$this->bindingType);
7668 } elseif ($this->operations = $this->
wsdl->
getOperations($this->portName,
'soap12')) {
7671 $this->bindingType =
'soap12';
7672 $this->
debug(
'got '.count($this->operations).
' operations from wsdl '.$this->wsdlFile.
' for binding type '.$this->bindingType);
7673 $this->
debug(
'**************** WARNING: SOAP 1.2 BINDING *****************');
7677 $this->
debug(
'getOperations returned false');
7678 $this->
setError(
'no operations defined in the WSDL document!');
7689 $this->
debug(
'instantiating wsdl class with doc: '.$this->wsdlFile);
7690 $this->
wsdl =
new wsdl(
'', $this->proxyhost, $this->proxyport, $this->proxyusername, $this->proxypassword, $this->timeout, $this->response_timeout, $this->curl_options, $this->use_curl);
7691 $this->
wsdl->
setCredentials($this->username, $this->password, $this->authtype, $this->certRequest);
7705 if (
'wsdl' == $this->endpointType &&
null === $this->
wsdl) {
7711 if (isset($this->operations[$operation])) {
7712 return $this->operations[$operation];
7714 $this->
debug(
"No data for operation: $operation");
7731 public function send($msg, $soapaction =
'', $timeout=0, $response_timeout=30)
7737 case preg_match(
'/^http/', $this->endpoint):
7738 $this->
debug(
'transporting via HTTP');
7739 if (
true == $this->persistentConnection && is_object($this->persistentConnection)) {
7740 $http =& $this->persistentConnection;
7743 if ($this->persistentConnection) {
7744 $http->usePersistentConnection();
7748 $http->setSOAPAction($soapaction);
7749 if ($this->proxyhost && $this->proxyport) {
7750 $http->setProxy($this->proxyhost, $this->proxyport, $this->proxyusername, $this->proxypassword);
7752 if (
'' != $this->authtype) {
7753 $http->setCredentials($this->username, $this->password, $this->authtype, [], $this->certRequest);
7755 if (
'' != $this->http_encoding) {
7756 $http->setEncoding($this->http_encoding);
7758 $this->
debug(
'sending message, length='.strlen($msg));
7759 if (preg_match(
'/^http:/', $this->endpoint)) {
7761 $this->responseData = $http->send($msg, $timeout, $response_timeout, $this->cookies);
7762 } elseif (preg_match(
'/^https/', $this->endpoint)) {
7769 $this->responseData = $http->sendHTTPS($msg, $timeout, $response_timeout, $this->cookies);
7771 $this->
setError(
'no http/s in endpoint url');
7773 $this->request = $http->outgoing_payload;
7774 $this->response = $http->incoming_payload;
7779 if ($this->persistentConnection) {
7780 $http->clearDebug();
7781 if (!is_object($this->persistentConnection)) {
7782 $this->persistentConnection = $http;
7786 if ($err = $http->getError()) {
7787 $this->
setError(
'HTTP Error: '.$err);
7792 $this->
debug(
'got response, length='. strlen($this->responseData).
' type='.$http->incoming_headers[
'content-type']);
7793 return $this->
parseResponse($http->incoming_headers, $this->responseData);
7797 $this->
setError(
'no transport found, or selected transport is not yet supported!');
7813 $this->
debug(
'Entering parseResponse() for data of length ' . strlen($data) .
' headers:');
7815 if (!isset($headers[
'content-type'])) {
7816 $this->
setError(
'Response not of type text/xml (no content-type header)');
7819 if (!strstr($headers[
'content-type'],
'text/xml')) {
7820 $this->
setError(
'Response not of type text/xml: ' . $headers[
'content-type']);
7823 if (strpos($headers[
'content-type'],
'=')) {
7824 $enc = str_replace(
'"',
'', substr(strstr($headers[
'content-type'],
'='), 1));
7825 $this->
debug(
'Got response encoding: ' . $enc);
7826 if (preg_match(
'/^(ISO-8859-1|US-ASCII|UTF-8)$/i', $enc)) {
7827 $this->xml_encoding = strtoupper($enc);
7829 $this->xml_encoding =
'US-ASCII';
7833 $this->xml_encoding =
'ISO-8859-1';
7835 $this->
debug(
'Use encoding: ' . $this->xml_encoding .
' when creating nusoap_parser');
7836 $parser =
new nusoap_parser($data, $this->xml_encoding, $this->operation, $this->decode_utf8);
7840 if ($errstr = $parser->getError()) {
7847 $this->responseHeaders = $parser->getHeaders();
7849 $this->responseHeader = $parser->get_soapheader();
7851 $return = $parser->get_soapbody();
7853 $this->document = $parser->document;
7870 $this->
debug(
"setCurlOption option=$option, value=");
7872 $this->curl_options[$option] = $value;
7883 $this->
debug(
"setEndpoint(\"$endpoint\")");
7884 $this->forceEndpoint = $endpoint;
7895 $this->
debug(
'setHeaders headers=');
7897 $this->requestHeaders = $headers;
7908 return $this->responseHeaders;
7919 return $this->responseHeader;
7931 public function setHTTPProxy($proxyhost, $proxyport, $proxyusername =
'', $proxypassword =
'')
7933 $this->proxyhost = $proxyhost;
7934 $this->proxyport = $proxyport;
7935 $this->proxyusername = $proxyusername;
7936 $this->proxypassword = $proxypassword;
7948 public function setCredentials($username, $password, $authtype =
'basic', $certRequest = [])
7950 $this->
debug(
"setCredentials username=$username authtype=$authtype certRequest=");
7952 $this->username = $username;
7953 $this->password = $password;
7954 $this->authtype = $authtype;
7955 $this->certRequest = $certRequest;
7966 $this->
debug(
"setHTTPEncoding(\"$enc\")");
7967 $this->http_encoding = $enc;
7978 $this->
debug(
"setUseCURL($use)");
7979 $this->use_curl = $use;
7989 $this->
debug(
'useHTTPPersistentConnection');
7990 $this->persistentConnection =
true;
8006 return $this->defaultRpcParams;
8022 $this->defaultRpcParams = $rpcParams;
8035 $r = random_int(0, mt_getrandmax());
8039 $this->
debug(
'Error from _getProxyClassCode, so return NULL');
8045 eval(
"\$proxy = new nusoap_proxy_()$r('');");
8047 $proxy->endpointType =
'wsdl';
8048 $proxy->wsdlFile = $this->wsdlFile;
8049 $proxy->wsdl = $this->wsdl;
8050 $proxy->operations = $this->operations;
8051 $proxy->defaultRpcParams = $this->defaultRpcParams;
8053 $proxy->soap_defencoding = $this->soap_defencoding;
8054 $proxy->username = $this->username;
8055 $proxy->password = $this->password;
8056 $proxy->authtype = $this->authtype;
8057 $proxy->certRequest = $this->certRequest;
8058 $proxy->requestHeaders = $this->requestHeaders;
8059 $proxy->endpoint = $this->endpoint;
8060 $proxy->forceEndpoint = $this->forceEndpoint;
8061 $proxy->proxyhost = $this->proxyhost;
8062 $proxy->proxyport = $this->proxyport;
8063 $proxy->proxyusername = $this->proxyusername;
8064 $proxy->proxypassword = $this->proxypassword;
8065 $proxy->http_encoding = $this->http_encoding;
8066 $proxy->timeout = $this->timeout;
8067 $proxy->response_timeout = $this->response_timeout;
8068 $proxy->persistentConnection = &$this->persistentConnection;
8069 $proxy->decode_utf8 = $this->decode_utf8;
8070 $proxy->curl_options = $this->curl_options;
8071 $proxy->bindingType = $this->bindingType;
8072 $proxy->use_curl = $this->use_curl;
8085 $this->
debug(
"in getProxy endpointType=$this->endpointType");
8087 if (
'wsdl' != $this->endpointType) {
8088 $evalStr =
'A proxy can only be created for a WSDL client';
8090 $evalStr =
"echo \"$evalStr\";";
8093 if (
'wsdl' == $this->endpointType &&
null === $this->
wsdl) {
8096 return 'echo "' . $this->
getError() .
'";';
8100 foreach ($this->operations as $operation => $opData) {
8101 if (
'' != $operation) {
8103 if ((is_countable($opData[
'input'][
'parts']) ? count($opData[
'input'][
'parts']) : 0) > 0) {
8105 $paramArrayStr =
'';
8106 $paramCommentStr =
'';
8107 foreach ($opData[
'input'][
'parts'] as $name => $type) {
8108 $paramStr .=
"\$$name, ";
8109 $paramArrayStr .=
"'$name' => \$$name, ";
8110 $paramCommentStr .=
"$type \$$name, ";
8112 $paramStr = substr($paramStr, 0, strlen($paramStr)-2);
8113 $paramArrayStr = substr($paramArrayStr, 0, strlen($paramArrayStr)-2);
8114 $paramCommentStr = substr($paramCommentStr, 0, strlen($paramCommentStr)-2);
8117 $paramArrayStr =
'';
8118 $paramCommentStr =
'void';
8120 $opData[
'namespace'] = !isset($opData[
'namespace']) ?
'https://testuri.com' : $opData[
'namespace'];
8121 $evalStr .=
"// $paramCommentStr
8122 function " . str_replace(
'.',
'__', $operation) .
"($paramStr) {
8123 \$params = array($paramArrayStr);
8124 return \$this->call('$operation', \$params, '".$opData[
'namespace'].
"', '".($opData[
'soapAction'] ??
'').
"');
8128 unset($paramCommentStr);
8131 $evalStr =
'class nusoap_proxy_'.$r.
' extends nusoap_client {
8145 $r = random_int(0, mt_getrandmax());
8185 return $this->soap_defencoding;
8194 public function decodeUTF8($bool)
8196 $this->decode_utf8 = $bool;
8210 if (0 == strlen($name)) {
8213 $this->cookies[] = [
'name' => $name,
'value' => $value];
8225 return $this->cookies;
8236 if (0 == count($this->cookies)) {
8239 $this->
debug(
'checkCookie: check ' . count($this->cookies) .
' cookies');
8240 $curr_cookies = $this->cookies;
8241 $this->cookies = [];
8242 foreach ($curr_cookies as $cookie) {
8243 if (! is_array($cookie)) {
8244 $this->
debug(
'Remove cookie that is not an array');
8247 if ((isset($cookie[
'expires'])) && (! empty($cookie[
'expires']))) {
8248 if (strtotime($cookie[
'expires']) > time()) {
8249 $this->cookies[] = $cookie;
8251 $this->
debug(
'Remove expired cookie ' . $cookie[
'name']);
8254 $this->cookies[] = $cookie;
8257 $this->
debug(
'checkCookie: ' . count($this->cookies) .
' cookies left in array');
8270 if (0 == count($this->cookies)) {
8272 if (count($cookies) > 0) {
8273 $this->
debug(
'Setting new cookie(s)');
8274 $this->cookies = $cookies;
8278 if (0 == count($cookies)) {
8283 foreach ($cookies as $newCookie) {
8284 if (!is_array($newCookie)) {
8287 if ((!isset($newCookie[
'name'])) || (!isset($newCookie[
'value']))) {
8290 $newName = $newCookie[
'name'];
8293 for ($i = 0; $i < count($this->cookies); $i++) {
8294 $cookie = $this->cookies[$i];
8295 if (!is_array($cookie)) {
8298 if (!isset($cookie[
'name'])) {
8301 if ($newName != $cookie[
'name']) {
8304 $newDomain = $newCookie[
'domain'] ??
'NODOMAIN';
8305 $domain = $cookie[
'domain'] ??
'NODOMAIN';
8306 if ($newDomain != $domain) {
8309 $newPath = $newCookie[
'path'] ??
'NOPATH';
8310 $path = $cookie[
'path'] ??
'NOPATH';
8311 if ($newPath != $path) {
8314 $this->cookies[$i] = $newCookie;
8316 $this->
debug(
'Update cookie ' . $newName .
'=' . $newCookie[
'value']);
8320 $this->
debug(
'Add cookie ' . $newName .
'=' . $newCookie[
'value']);
8321 $this->cookies[] = $newCookie;
8328if (!extension_loaded(
'soap')) {
setGlobalDebugLevel($level)
isArraySimpleOrStruct($val)
serialize_val($val, $name=false, $type=false, $name_ns=false, $type_ns=false, $attributes=false, $use='encoded', $soapval=false)
getNamespaceFromPrefix($prefix)
getPrefixFromNamespace($ns)
serializeEnvelope($body, $headers=false, $namespaces=[], $style='rpc', $use='encoded', $encodingStyle='https://schemas.xmlsoap.org/soap/encoding/')
send($msg, $soapaction='', $timeout=0, $response_timeout=30)
__construct($endpoint, $wsdl=false, $proxyhost=false, $proxyport=false, $proxyusername=false, $proxypassword=false, $timeout=0, $response_timeout=30, $portName='')
setCurlOption($option, $value)
setCredentials($username, $password, $authtype='basic', $certRequest=[])
useHTTPPersistentConnection()
call($operation, $params=[], $namespace='https://tempuri.org', $soapAction='', $headers=false, $rpcParams=null, $style='rpc', $use='encoded')
setHTTPProxy($proxyhost, $proxyport, $proxyusername='', $proxypassword='')
getHTTPContentTypeCharset()
setHTTPEncoding($enc='gzip, deflate')
setDefaultRpcParams($rpcParams)
parseResponse($headers, $data)
getOperationData($operation)
__construct($faultcode, $faultactor='', $faultstring='', $faultdetail='')
character_data($parser, $data)
decodeSimple($value, $type, $typens)
start_element($parser, $name, $attrs)
__construct($xml, $encoding='UTF-8', $method='', $decode_utf8=true)
end_element($parser, $name)
verify_method($operation, $request)
parseRequest($headers, $data)
getHTTPContentTypeCharset()
fault($faultcode, $faultstring, $faultactor='', $faultdetail='')
add_to_map($methodname, $in, $out)
configureWSDL($serviceName, $namespace=false, $endpoint=false, $style='rpc', $transport='https://schemas.xmlsoap.org/soap/http', $schemaTargetNamespace=false)
addSimpleType($name, $restrictionBase='', $typeClass='simpleType', $phpType='scalar', $enumeration=[])
addComplexType($name, $typeClass='complexType', $phpType='array', $compositor='', $restrictionBase='', $elements=[], $attrs=[], $arrayType='')
schemaEndElement($parser, $name)
__construct($schema='', $xml='', $namespaces=[])
schemaStartElement($parser, $name, $attrs)
schemaCharacterData($parser, $data)
buildPayload($data, $cookie_str='')
setContentType($type, $charset=false)
sendRequest($data, $cookies=null)
__construct($url, $curl_options=null, $use_curl=false)
setCurlOption($option, $value)
getCookiesForRequest($cookies, $secure=false)
decodeChunked($buffer, $lb)
setSOAPAction($soapaction)
send($data, $timeout=0, $response_timeout=30, $cookies=null)
connect($connection_timeout=0, $response_timeout=30)
usePersistentConnection()
setEncoding($enc='gzip, deflate')
setProxy($proxyhost, $proxyport, $proxyusername='', $proxypassword='', $proxyauthtype='basic')
sendHTTPS($data, $timeout=0, $response_timeout=30, $cookies)
setCredentials($username, $password, $authtype='basic', $digestRequest=[], $certRequest=[])
isSkippableCurlHeader(&$data)
__construct($name='soapval', $type=false, $value=-1, $element_ns=false, $type_ns=false, $attributes=false)
serialize($use='encoded')
serializeType($name, $type, $value, $use='encoded', $encodingStyle=false, $unqualified=false)
serializeComplexTypeAttributes($typeDef, $value, $ns, $uqType)
addSimpleType($name, $restrictionBase='', $typeClass='simpleType', $phpType='scalar', $enumeration=[])
getOperationData($operation, $bindingType='soap')
addComplexType($name, $typeClass='complexType', $phpType='array', $compositor='', $restrictionBase='', $elements=[], $attrs=[], $arrayType='')
character_data($parser, $data)
parametersMatchWrapped($type, &$parameters)
setCredentials($username, $password, $authtype='basic', $certRequest=[])
getOperationDataForSoapAction($soapAction, $bindingType='soap')
serializeComplexTypeElements($typeDef, $value, $ns, $uqType, $use='encoded', $encodingStyle=false)
start_element($parser, $name, $attrs)
serializeRPCParameters($operation, $direction, $parameters, $bindingType='soap')
__construct($wsdl='', $proxyhost=false, $proxyport=false, $proxyusername=false, $proxypassword=false, $timeout=0, $response_timeout=30, $curl_options=null, $use_curl=false)
end_element($parser, $name)
addOperation($name, $in=false, $out=false, $namespace=false, $soapaction=false, $style='rpc', $use='encoded', $documentation='', $encodingStyle='')
getOperations($portName='', $bindingType='soap')
serializeParameters($operation, $direction, $parameters)