ILIAS  trunk Revision v12.0_alpha-1227-g7ff6d300864
nusoap.php
Go to the documentation of this file.
1<?php
2
19/*
20 * Some of the standards implmented in whole or part by NuSOAP:
21 *
22 * SOAP 1.1 (http://www.w3.org/TR/2000/NOTE-SOAP-20000508/)
23 * WSDL 1.1 (http://www.w3.org/TR/2001/NOTE-wsdl-20010315)
24 * SOAP Messages With Attachments (http://www.w3.org/TR/SOAP-attachments)
25 * XML 1.0 (http://www.w3.org/TR/2006/REC-xml-20060816/)
26 * Namespaces in XML 1.0 (http://www.w3.org/TR/2006/REC-xml-names-20060816/)
27 * XML Schema 1.0 (http://www.w3.org/TR/xmlschema-0/)
28 * RFC 2045 Multipurpose Internet Mail Extensions (MIME) Part One: Format of Internet Message Bodies
29 * RFC 2068 Hypertext Transfer Protocol -- HTTP/1.1
30 * RFC 2617 HTTP Authentication: Basic and Digest Access Authentication
31 */
32// class variable emulation
33// cf. http://www.webkreator.com/php/techniques/php-static-class-variables.html
34// alex patch: we need an object here, otherwise we will get a warning in php 5.4
35if (
36 !isset($GLOBALS['_transient']) ||
37 !isset($GLOBALS['_transient']['static']) ||
38 !isset($GLOBALS['_transient']['static']['nusoap_base']) ||
39 !is_object($GLOBALS['_transient']['static']['nusoap_base'])
40) {
41 $GLOBALS['_transient']['static']['nusoap_base'] = new stdClass();
42}
43$GLOBALS['_transient']['static']['nusoap_base']->globalDebugLevel = 0;
44
55{
62 public $title = 'NuSOAP';
69 public $version = '0.7.3';
76 public $revision = '$Revision$';
83 public $error_str = '';
90 public $debug_str = '';
98 public $charencoding = true;
106
113 public $XMLSchemaVersion = 'http://www.w3.org/2001/XMLSchema';
114
121 //var $soap_defencoding = 'ISO-8859-1';
122 public $soap_defencoding = 'UTF-8';
123
132 public $namespaces = array(
133 'SOAP-ENV' => 'http://schemas.xmlsoap.org/soap/envelope/',
134 'xsd' => 'http://www.w3.org/2001/XMLSchema',
135 'xsi' => 'http://www.w3.org/2001/XMLSchema-instance',
136 'SOAP-ENC' => 'http://schemas.xmlsoap.org/soap/encoding/'
137 );
138
145 public $usedNamespaces = array();
146
154 public $typemap = array(
155 'http://www.w3.org/2001/XMLSchema' => array(
156 'string' => 'string','boolean' => 'boolean','float' => 'double','double' => 'double','decimal' => 'double',
157 'duration' => '','dateTime' => 'string','time' => 'string','date' => 'string','gYearMonth' => '',
158 'gYear' => '','gMonthDay' => '','gDay' => '','gMonth' => '','hexBinary' => 'string','base64Binary' => 'string',
159 // abstract "any" types
160 'anyType' => 'string','anySimpleType' => 'string',
161 // derived datatypes
162 'normalizedString' => 'string','token' => 'string','language' => '','NMTOKEN' => '','NMTOKENS' => '','Name' => '','NCName' => '','ID' => '',
163 'IDREF' => '','IDREFS' => '','ENTITY' => '','ENTITIES' => '','integer' => 'integer','nonPositiveInteger' => 'integer',
164 'negativeInteger' => 'integer','long' => 'integer','int' => 'integer','short' => 'integer','byte' => 'integer','nonNegativeInteger' => 'integer',
165 'unsignedLong' => '','unsignedInt' => '','unsignedShort' => '','unsignedByte' => '','positiveInteger' => ''),
166 'http://www.w3.org/2000/10/XMLSchema' => array(
167 'i4' => '','int' => 'integer','boolean' => 'boolean','string' => 'string','double' => 'double',
168 'float' => 'double','dateTime' => 'string',
169 'timeInstant' => 'string','base64Binary' => 'string','base64' => 'string','ur-type' => 'array'),
170 'http://www.w3.org/1999/XMLSchema' => array(
171 'i4' => '','int' => 'integer','boolean' => 'boolean','string' => 'string','double' => 'double',
172 'float' => 'double','dateTime' => 'string',
173 'timeInstant' => 'string','base64Binary' => 'string','base64' => 'string','ur-type' => 'array'),
174 'http://soapinterop.org/xsd' => array('SOAPStruct' => 'struct'),
175 'http://schemas.xmlsoap.org/soap/encoding/' => array('base64' => 'string','array' => 'array','Array' => 'array'),
176 'http://xml.apache.org/xml-soap' => array('Map')
177 );
178
187 public $xmlEntities = array('quot' => '"','amp' => '&',
188 'lt' => '<','gt' => '>','apos' => "'");
189
195 public function __construct()
196 {
197 $this->debugLevel = $GLOBALS['_transient']['static']['nusoap_base']->globalDebugLevel;
198 }
199
206 public function getGlobalDebugLevel()
207 {
208 return $GLOBALS['_transient']['static']['nusoap_base']->globalDebugLevel;
209 }
210
217 public function setGlobalDebugLevel($level)
218 {
219 $GLOBALS['_transient']['static']['nusoap_base']->globalDebugLevel = $level;
220 }
221
228 public function getDebugLevel()
229 {
230 return $this->debugLevel;
231 }
232
239 public function setDebugLevel($level)
240 {
241 $this->debugLevel = $level;
242 }
243
250 public function debug($string)
251 {
252 if ($this->debugLevel > 0) {
253 $this->appendDebug($this->getmicrotime() . ' ' . get_class($this) . ": $string\n");
254 }
255 }
256
263 public function appendDebug($string)
264 {
265 if ($this->debugLevel > 0) {
266 // it would be nice to use a memory stream here to use
267 // memory more efficiently
268 $this->debug_str .= $string;
269 }
270 }
271
277 public function clearDebug()
278 {
279 // it would be nice to use a memory stream here to use
280 // memory more efficiently
281 $this->debug_str = '';
282 }
283
290 public function &getDebug()
291 {
292 // it would be nice to use a memory stream here to use
293 // memory more efficiently
294 return $this->debug_str;
295 }
296
304 public function &getDebugAsXMLComment()
305 {
306 // it would be nice to use a memory stream here to use
307 // memory more efficiently
308 while (strpos($this->debug_str, '--')) {
309 $this->debug_str = str_replace('--', '- -', $this->debug_str);
310 }
311 $ret = "<!--\n" . $this->debug_str . "\n-->";
312 return $ret;
313 }
314
321 public function expandEntities($val)
322 {
323 if ($this->charencoding) {
324 $val = str_replace('&', '&amp;', $val);
325 $val = str_replace("'", '&apos;', $val);
326 $val = str_replace('"', '&quot;', $val);
327 $val = str_replace('<', '&lt;', $val);
328 $val = str_replace('>', '&gt;', $val);
329 }
330 return $val;
331 }
332
339 public function getError()
340 {
341 if ($this->error_str != '') {
342 return $this->error_str;
343 }
344 return false;
345 }
346
353 public function setError($str)
354 {
355 $this->error_str = $str;
356 }
357
365 public function isArraySimpleOrStruct($val)
366 {
367 $keyList = array_keys($val);
368 foreach ($keyList as $keyListValue) {
369 if (!is_int($keyListValue)) {
370 return 'arrayStruct';
371 }
372 }
373 return 'arraySimple';
374 }
375
391 public function serialize_val($val, $name = false, $type = false, $name_ns = false, $type_ns = false, $attributes = false, $use = 'encoded', $soapval = false)
392 {
393 $this->debug("in serialize_val: name=$name, type=$type, name_ns=$name_ns, type_ns=$type_ns, use=$use, soapval=$soapval");
394 $this->appendDebug('value=' . $this->varDump($val));
395 $this->appendDebug('attributes=' . $this->varDump($attributes));
396
397 if (is_object($val) && get_class($val) == 'soapval' && (! $soapval)) {
398 $this->debug("serialize_val: serialize soapval");
399 $xml = $val->serialize($use);
400 $this->appendDebug($val->getDebug());
401 $val->clearDebug();
402 $this->debug("serialize_val of soapval returning $xml");
403 return $xml;
404 }
405 // force valid name if necessary
406 if (is_numeric($name)) {
407 $name = '__numeric_' . $name;
408 } elseif (! $name) {
409 $name = 'noname';
410 }
411 // if name has ns, add ns prefix to name
412 $xmlns = '';
413 if ($name_ns) {
414 $prefix = 'nu' . rand(1000, 9999);
415 $name = $prefix . ':' . $name;
416 $xmlns .= " xmlns:$prefix=\"$name_ns\"";
417 }
418 // if type is prefixed, create type prefix
419 if ($type_ns != '' && $type_ns == $this->namespaces['xsd']) {
420 // need to fix this. shouldn't default to xsd if no ns specified
421 // w/o checking against typemap
422 $type_prefix = 'xsd';
423 } elseif ($type_ns) {
424 $type_prefix = 'ns' . rand(1000, 9999);
425 $xmlns .= " xmlns:$type_prefix=\"$type_ns\"";
426 }
427 // serialize attributes if present
428 $atts = '';
429 if ($attributes) {
430 foreach ($attributes as $k => $v) {
431 $atts .= " $k=\"" . $this->expandEntities($v) . '"';
432 }
433 }
434 // serialize null value
435 if (is_null($val)) {
436 $this->debug("serialize_val: serialize null");
437 if ($use == 'literal') {
438 // TODO: depends on minOccurs
439 $xml = "<$name$xmlns$atts/>";
440 $this->debug("serialize_val returning $xml");
441 return $xml;
442 } else {
443 if (isset($type) && isset($type_prefix)) {
444 $type_str = " xsi:type=\"$type_prefix:$type\"";
445 } else {
446 $type_str = '';
447 }
448 $xml = "<$name$xmlns$type_str$atts xsi:nil=\"true\"/>";
449 $this->debug("serialize_val returning $xml");
450 return $xml;
451 }
452 }
453 // serialize if an xsd built-in primitive type
454 if ($type != '' && isset($this->typemap[$this->XMLSchemaVersion][$type])) {
455 $this->debug("serialize_val: serialize xsd built-in primitive type");
456 if (is_bool($val)) {
457 if ($type == 'boolean') {
458 $val = $val ? 'true' : 'false';
459 } elseif (! $val) {
460 $val = 0;
461 }
462 } elseif (is_string($val)) {
463 $val = $this->expandEntities($val);
464 }
465 if ($use == 'literal') {
466 $xml = "<$name$xmlns$atts>$val</$name>";
467 $this->debug("serialize_val returning $xml");
468 return $xml;
469 } else {
470 $xml = "<$name$xmlns xsi:type=\"xsd:$type\"$atts>$val</$name>";
471 $this->debug("serialize_val returning $xml");
472 return $xml;
473 }
474 }
475 // detect type and serialize
476 $xml = '';
477 switch (true) {
478 case (is_bool($val) || $type == 'boolean'):
479 $this->debug("serialize_val: serialize boolean");
480 if ($type == 'boolean') {
481 $val = $val ? 'true' : 'false';
482 } elseif (! $val) {
483 $val = 0;
484 }
485 if ($use == 'literal') {
486 $xml .= "<$name$xmlns$atts>$val</$name>";
487 } else {
488 $xml .= "<$name$xmlns xsi:type=\"xsd:boolean\"$atts>$val</$name>";
489 }
490 break;
491 case (is_int($val) || is_long($val) || $type == 'int'):
492 $this->debug("serialize_val: serialize int");
493 if ($use == 'literal') {
494 $xml .= "<$name$xmlns$atts>$val</$name>";
495 } else {
496 $xml .= "<$name$xmlns xsi:type=\"xsd:int\"$atts>$val</$name>";
497 }
498 break;
499 case (is_float($val) || is_double($val) || $type == 'float'):
500 $this->debug("serialize_val: serialize float");
501 if ($use == 'literal') {
502 $xml .= "<$name$xmlns$atts>$val</$name>";
503 } else {
504 $xml .= "<$name$xmlns xsi:type=\"xsd:float\"$atts>$val</$name>";
505 }
506 break;
507 case (is_string($val) || $type == 'string'):
508 $this->debug("serialize_val: serialize string");
509 $val = $this->expandEntities($val);
510 if ($use == 'literal') {
511 $xml .= "<$name$xmlns$atts>$val</$name>";
512 } else {
513 $xml .= "<$name$xmlns xsi:type=\"xsd:string\"$atts>$val</$name>";
514 }
515 break;
516 case is_object($val):
517 $this->debug("serialize_val: serialize object");
518 if (get_class($val) == 'soapval') {
519 $this->debug("serialize_val: serialize soapval object");
520 $pXml = $val->serialize($use);
521 $this->appendDebug($val->getDebug());
522 $val->clearDebug();
523 } else {
524 if (! $name) {
525 $name = get_class($val);
526 $this->debug("In serialize_val, used class name $name as element name");
527 } else {
528 $this->debug("In serialize_val, do not override name $name for element name for class " . get_class($val));
529 }
530 foreach (get_object_vars($val) as $k => $v) {
531 $pXml = isset($pXml) ? $pXml . $this->serialize_val($v, $k, false, false, false, false, $use) : $this->serialize_val($v, $k, false, false, false, false, $use);
532 }
533 }
534 if (isset($type) && isset($type_prefix)) {
535 $type_str = " xsi:type=\"$type_prefix:$type\"";
536 } else {
537 $type_str = '';
538 }
539 if ($use == 'literal') {
540 $xml .= "<$name$xmlns$atts>$pXml</$name>";
541 } else {
542 $xml .= "<$name$xmlns$type_str$atts>$pXml</$name>";
543 }
544 break;
545 break;
546 case (is_array($val) || $type):
547 // detect if struct or array
548 $valueType = $this->isArraySimpleOrStruct($val);
549 if ($valueType == 'arraySimple' || preg_match('/^ArrayOf/', $type)) {
550 $this->debug("serialize_val: serialize array");
551 $i = 0;
552 if (is_array($val) && count($val) > 0) {
553 foreach ($val as $v) {
554 if (is_object($v) && get_class($v) == 'soapval') {
555 $tt_ns = $v->type_ns;
556 $tt = $v->type;
557 } elseif (is_array($v)) {
558 $tt = $this->isArraySimpleOrStruct($v);
559 } else {
560 $tt = gettype($v);
561 }
562 $array_types[$tt] = 1;
563 // TODO: for literal, the name should be $name
564 $xml .= $this->serialize_val($v, 'item', false, false, false, false, $use);
565 ++$i;
566 }
567 if (count($array_types) > 1) {
568 $array_typename = 'xsd:anyType';
569 } elseif (isset($tt) && isset($this->typemap[$this->XMLSchemaVersion][$tt])) {
570 if ($tt == 'integer') {
571 $tt = 'int';
572 }
573 $array_typename = 'xsd:' . $tt;
574 } elseif (isset($tt) && $tt == 'arraySimple') {
575 $array_typename = 'SOAP-ENC:Array';
576 } elseif (isset($tt) && $tt == 'arrayStruct') {
577 $array_typename = 'unnamed_struct_use_soapval';
578 } else {
579 // if type is prefixed, create type prefix
580 if ($tt_ns != '' && $tt_ns == $this->namespaces['xsd']) {
581 $array_typename = 'xsd:' . $tt;
582 } elseif ($tt_ns) {
583 $tt_prefix = 'ns' . rand(1000, 9999);
584 $array_typename = "$tt_prefix:$tt";
585 $xmlns .= " xmlns:$tt_prefix=\"$tt_ns\"";
586 } else {
587 $array_typename = $tt;
588 }
589 }
590 $array_type = $i;
591 if ($use == 'literal') {
592 $type_str = '';
593 } elseif (isset($type) && isset($type_prefix)) {
594 $type_str = " xsi:type=\"$type_prefix:$type\"";
595 } else {
596 $type_str = " xsi:type=\"SOAP-ENC:Array\" SOAP-ENC:arrayType=\"" . $array_typename . "[$array_type]\"";
597 }
598 // empty array
599 } else {
600 if ($use == 'literal') {
601 $type_str = '';
602 } elseif (isset($type) && isset($type_prefix)) {
603 $type_str = " xsi:type=\"$type_prefix:$type\"";
604 } else {
605 $type_str = " xsi:type=\"SOAP-ENC:Array\" SOAP-ENC:arrayType=\"xsd:anyType[0]\"";
606 }
607 }
608 // TODO: for array in literal, there is no wrapper here
609 $xml = "<$name$xmlns$type_str$atts>" . $xml . "</$name>";
610 } else {
611 // got a struct
612 $this->debug("serialize_val: serialize struct");
613 if (isset($type) && isset($type_prefix)) {
614 $type_str = " xsi:type=\"$type_prefix:$type\"";
615 } else {
616 $type_str = '';
617 }
618 if ($use == 'literal') {
619 $xml .= "<$name$xmlns$atts>";
620 } else {
621 $xml .= "<$name$xmlns$type_str$atts>";
622 }
623 foreach ($val as $k => $v) {
624 // Apache Map
625 if ($type == 'Map' && $type_ns == 'http://xml.apache.org/xml-soap') {
626 $xml .= '<item>';
627 $xml .= $this->serialize_val($k, 'key', false, false, false, false, $use);
628 $xml .= $this->serialize_val($v, 'value', false, false, false, false, $use);
629 $xml .= '</item>';
630 } else {
631 $xml .= $this->serialize_val($v, $k, false, false, false, false, $use);
632 }
633 }
634 $xml .= "</$name>";
635 }
636 break;
637 default:
638 $this->debug("serialize_val: serialize unknown");
639 $xml .= 'not detected, got ' . gettype($val) . ' for ' . $val;
640 break;
641 }
642 $this->debug("serialize_val returning $xml");
643 return $xml;
644 }
645
658 public function serializeEnvelope($body, $headers = false, $namespaces = array(), $style = 'rpc', $use = 'encoded', $encodingStyle = 'http://schemas.xmlsoap.org/soap/encoding/')
659 {
660 // TODO: add an option to automatically run utf8_encode on $body and $headers
661 // if $this->soap_defencoding is UTF-8. Not doing this automatically allows
662 // one to send arbitrary UTF-8 characters, not just characters that map to ISO-8859-1
663
664 $this->debug("In serializeEnvelope length=" . strlen($body) . " body (max 1000 characters)=" . substr($body, 0, 1000) . " style=$style use=$use encodingStyle=$encodingStyle");
665 $this->debug("headers:");
666 $this->appendDebug($this->varDump($headers));
667 $this->debug("namespaces:");
668 $this->appendDebug($this->varDump($namespaces));
669
670 // serialize namespaces
671 $ns_string = '';
672 foreach (array_merge($this->namespaces, $namespaces) as $k => $v) {
673 $ns_string .= " xmlns:$k=\"$v\"";
674 }
675 if ($encodingStyle) {
676 $ns_string = " SOAP-ENV:encodingStyle=\"$encodingStyle\"$ns_string";
677 }
678
679 // serialize headers
680 if ($headers) {
681 if (is_array($headers)) {
682 $xml = '';
683 foreach ($headers as $k => $v) {
684 if (is_object($v) && get_class($v) == 'soapval') {
685 $xml .= $this->serialize_val($v, false, false, false, false, false, $use);
686 } else {
687 $xml .= $this->serialize_val($v, $k, false, false, false, false, $use);
688 }
689 }
690 $headers = $xml;
691 $this->debug("In serializeEnvelope, serialized array of headers to $headers");
692 }
693 $headers = "<SOAP-ENV:Header>" . $headers . "</SOAP-ENV:Header>";
694 }
695 // serialize envelope
696 return
697 '<?xml version="1.0" encoding="' . $this->soap_defencoding . '"?' . ">" .
698 '<SOAP-ENV:Envelope' . $ns_string . ">" .
699 $headers .
700 "<SOAP-ENV:Body>" .
701 $body .
702 "</SOAP-ENV:Body>" .
703 "</SOAP-ENV:Envelope>";
704 }
705
714 public function formatDump($str)
715 {
716 $str = htmlspecialchars($str);
717 return nl2br($str);
718 }
719
727 public function contractQname($qname)
728 {
729 // get element namespace
730 //$this->xdebug("Contract $qname");
731 if (strrpos($qname, ':')) {
732 // get unqualified name
733 $name = substr($qname, strrpos($qname, ':') + 1);
734 // get ns
735 $ns = substr($qname, 0, strrpos($qname, ':'));
736 $p = $this->getPrefixFromNamespace($ns);
737 if ($p) {
738 return $p . ':' . $name;
739 }
740 return $qname;
741 } else {
742 return $qname;
743 }
744 }
745
753 public function expandQname($qname)
754 {
755 // get element prefix
756 if (strpos($qname, ':') && !preg_match('/^http:\/\//', $qname)) {
757 // get unqualified name
758 $name = substr(strstr($qname, ':'), 1);
759 // get ns prefix
760 $prefix = substr($qname, 0, strpos($qname, ':'));
761 if (isset($this->namespaces[$prefix])) {
762 return $this->namespaces[$prefix] . ':' . $name;
763 } else {
764 return $qname;
765 }
766 } else {
767 return $qname;
768 }
769 }
770
779 public function getLocalPart($str)
780 {
781 if ($sstr = strrchr($str, ':')) {
782 // get unqualified name
783 return substr($sstr, 1);
784 } else {
785 return $str;
786 }
787 }
788
797 public function getPrefix($str)
798 {
799 if ($pos = strrpos($str, ':')) {
800 // get prefix
801 return substr($str, 0, $pos);
802 }
803 return false;
804 }
805
813 public function getNamespaceFromPrefix($prefix)
814 {
815 if (isset($this->namespaces[$prefix])) {
816 return $this->namespaces[$prefix];
817 }
818 //$this->setError("No namespace registered for prefix '$prefix'");
819 return false;
820 }
821
830 public function getPrefixFromNamespace($ns)
831 {
832 foreach ($this->namespaces as $p => $n) {
833 if ($ns == $n || $ns == $p) {
834 $this->usedNamespaces[$p] = $n;
835 return $p;
836 }
837 }
838 return false;
839 }
840
847 public function getmicrotime()
848 {
849 if (function_exists('gettimeofday')) {
850 $tod = gettimeofday();
851 $sec = $tod['sec'];
852 $usec = $tod['usec'];
853 } else {
854 $sec = time();
855 $usec = 0;
856 }
857 return strftime('%Y-%m-%d %H:%M:%S', $sec) . '.' . sprintf('%06d', $usec);
858 }
859
867 public function varDump($data)
868 {
869 ob_start();
870 var_dump($data);
871 $ret_val = ob_get_contents();
872 ob_end_clean();
873 return $ret_val;
874 }
875
882 public function __toString()
883 {
884 return $this->varDump($this);
885 }
886}
887
888// XML Schema Datatype Helper Functions
889
890//xsd:dateTime helpers
891
899function timestamp_to_iso8601($timestamp, $utc = true)
900{
901 $datestr = date('Y-m-d\TH:i:sO', $timestamp);
902 if ($utc) {
903 $pattern = '/' .
904 '([0-9]{4})-' . // centuries & years CCYY-
905 '([0-9]{2})-' . // months MM-
906 '([0-9]{2})' . // days DD
907 'T' . // separator T
908 '([0-9]{2}):' . // hours hh:
909 '([0-9]{2}):' . // minutes mm:
910 '([0-9]{2})(\.[0-9]*)?' . // seconds ss.ss...
911 '(Z|[+\-][0-9]{2}:?[0-9]{2})?' . // Z to indicate UTC, -/+HH:MM:SS.SS... for local tz's
912 '/';
913
914 if (preg_match($pattern, $datestr, $regs)) {
915 return sprintf('%04d-%02d-%02dT%02d:%02d:%02dZ', $regs[1], $regs[2], $regs[3], $regs[4], $regs[5], $regs[6]);
916 }
917 return false;
918 } else {
919 return $datestr;
920 }
921}
922
929function iso8601_to_timestamp($datestr)
930{
931 $pattern = '/' .
932 '([0-9]{4})-' . // centuries & years CCYY-
933 '([0-9]{2})-' . // months MM-
934 '([0-9]{2})' . // days DD
935 'T' . // separator T
936 '([0-9]{2}):' . // hours hh:
937 '([0-9]{2}):' . // minutes mm:
938 '([0-9]{2})(\.[0-9]+)?' . // seconds ss.ss...
939 '(Z|[+\-][0-9]{2}:?[0-9]{2})?' . // Z to indicate UTC, -/+HH:MM:SS.SS... for local tz's
940 '/';
941
942 if (preg_match($pattern, $datestr, $regs)) {
943 // not utc
944 if ($regs[8] != 'Z') {
945 $op = substr($regs[8], 0, 1);
946 $h = substr($regs[8], 1, 2);
947 $m = substr($regs[8], strlen($regs[8]) - 2, 2);
948 if ($op == '-') {
949 $regs[4] = $regs[4] + $h;
950 $regs[5] = $regs[5] + $m;
951 } elseif ($op == '+') {
952 $regs[4] = $regs[4] - $h;
953 $regs[5] = $regs[5] - $m;
954 }
955 }
956 return gmmktime($regs[4], $regs[5], $regs[6], $regs[2], $regs[3], $regs[1]);
957 // return strtotime("$regs[1]-$regs[2]-$regs[3] $regs[4]:$regs[5]:$regs[6]Z");
958 } else {
959 return false;
960 }
961}
962
970function usleepWindows($usec)
971{
972 $start = gettimeofday();
973
974 do {
975 $stop = gettimeofday();
976 $timePassed = 1000000 * ($stop['sec'] - $start['sec'])
977 + $stop['usec'] - $start['usec'];
978 } while ($timePassed < $usec);
979}
980
981?><?php
982
983
984
994{
1019
1029 {
1031 $this->faultcode = $faultcode;
1032 $this->faultactor = $faultactor;
1033 $this->faultstring = $faultstring;
1034 $this->faultdetail = $faultdetail;
1035 }
1036
1043 public function serialize()
1044 {
1045 $ns_string = '';
1046 foreach ($this->namespaces as $k => $v) {
1047 $ns_string .= "\n xmlns:$k=\"$v\"";
1048 }
1049 $return_msg =
1050 '<?xml version="1.0" encoding="' . $this->soap_defencoding . '"?>' .
1051 '<SOAP-ENV:Envelope SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"' . $ns_string . ">\n" .
1052 '<SOAP-ENV:Body>' .
1053 '<SOAP-ENV:Fault>' .
1054 $this->serialize_val($this->faultcode, 'faultcode') .
1055 $this->serialize_val($this->faultstring, 'faultstring') .
1056 $this->serialize_val($this->faultactor, 'faultactor') .
1057 $this->serialize_val($this->faultdetail, 'detail') .
1058 '</SOAP-ENV:Fault>' .
1059 '</SOAP-ENV:Body>' .
1060 '</SOAP-ENV:Envelope>';
1061 return $return_msg;
1062 }
1063}
1064
1069{
1070}
1071
1072?><?php
1073
1074
1075
1086{
1087 // files
1088 public $schema = '';
1089 public $xml = '';
1090 // namespaces
1092 // schema info
1093 public $schemaInfo = array();
1095 // types, elements, attributes defined by the schema
1096 public $attributes = array();
1097 public $complexTypes = array();
1098 public $complexTypeStack = array();
1099 public $currentComplexType = null;
1100 public $elements = array();
1101 public $elementStack = array();
1102 public $currentElement = null;
1103 public $simpleTypes = array();
1104 public $simpleTypeStack = array();
1105 public $currentSimpleType = null;
1106 // imports
1107 public $imports = array();
1108 // parser vars
1109 public $parser;
1110 public $position = 0;
1111 public $depth = 0;
1112 public $depth_array = array();
1113 public $message = array();
1114 public $defaultNamespace = array();
1115
1124 public function __construct($schema = '', $xml = '', $namespaces = array())
1125 {
1127 $this->debug('nusoap_xmlschema class instantiated, inside constructor');
1128 // files
1129 $this->schema = $schema;
1130 $this->xml = $xml;
1131
1132 // namespaces
1133 $this->enclosingNamespaces = $namespaces;
1134 $this->namespaces = array_merge($this->namespaces, $namespaces);
1135
1136 // parse schema file
1137 if ($schema != '') {
1138 $this->debug('initial schema file: ' . $schema);
1139 $this->parseFile($schema, 'schema');
1140 }
1141
1142 // parse xml file
1143 if ($xml != '') {
1144 $this->debug('initial xml file: ' . $xml);
1145 $this->parseFile($xml, 'xml');
1146 }
1147 }
1148
1157 public function parseFile($xml, $type)
1158 {
1159 // parse xml file
1160 if ($xml != "") {
1161 $xmlStr = @join("", @file($xml));
1162 if ($xmlStr == "") {
1163 $msg = 'Error reading XML from ' . $xml;
1164 $this->setError($msg);
1165 $this->debug($msg);
1166 return false;
1167 } else {
1168 $this->debug("parsing $xml");
1169 $this->parseString($xmlStr, $type);
1170 $this->debug("done parsing $xml");
1171 return true;
1172 }
1173 }
1174 return false;
1175 }
1176
1184 public function parseString($xml, $type)
1185 {
1186 // parse xml string
1187 if ($xml != "") {
1188 // Create an XML parser.
1189 $this->parser = xml_parser_create();
1190 // Set the options for parsing the XML data.
1191 xml_parser_set_option($this->parser, XML_OPTION_CASE_FOLDING, 0);
1192
1193 // Set the element handlers for the parser.
1194 if ($type == "schema") {
1195 xml_set_element_handler($this->parser, $this->schemaStartElement(...), $this->schemaEndElement(...));
1196 xml_set_character_data_handler($this->parser, $this->schemaCharacterData(...));
1197 } elseif ($type == "xml") {
1198 xml_set_element_handler($this->parser, $this->xmlStartElement(...), $this->xmlEndElement(...));
1199 xml_set_character_data_handler($this->parser, $this->xmlCharacterData(...));
1200 }
1201
1202 // Parse the XML file.
1203 if (!xml_parse($this->parser, $xml, true)) {
1204 // Display an error message.
1205 $errstr = sprintf(
1206 'XML error parsing XML schema on line %d: %s',
1207 xml_get_current_line_number($this->parser),
1208 xml_error_string(xml_get_error_code($this->parser))
1209 );
1210 $this->debug($errstr);
1211 $this->debug("XML payload:\n" . $xml);
1212 $this->setError($errstr);
1213 }
1214 } else {
1215 $this->debug('no xml passed to parseString()!!');
1216 $this->setError('no xml passed to parseString()!!');
1217 }
1218 }
1219
1227 public function CreateTypeName($ename)
1228 {
1229 $scope = '';
1230 for ($i = 0; $i < count($this->complexTypeStack); $i++) {
1231 $scope .= $this->complexTypeStack[$i] . '_';
1232 }
1233 return $scope . $ename . '_ContainedType';
1234 }
1235
1244 public function schemaStartElement($parser, $name, $attrs)
1245 {
1246
1247 // position in the total number of elements, starting from 0
1248 $pos = $this->position++;
1249 $depth = $this->depth++;
1250 // set self as current value for this depth
1251 $this->depth_array[$depth] = $pos;
1252 $this->message[$pos] = array('cdata' => '');
1253 if ($depth > 0) {
1254 $this->defaultNamespace[$pos] = $this->defaultNamespace[$this->depth_array[$depth - 1]];
1255 } else {
1256 $this->defaultNamespace[$pos] = false;
1257 }
1258
1259 // get element prefix
1260 if ($prefix = $this->getPrefix($name)) {
1261 // get unqualified name
1262 $name = $this->getLocalPart($name);
1263 } else {
1264 $prefix = '';
1265 }
1266
1267 // loop thru attributes, expanding, and registering namespace declarations
1268 if (count($attrs) > 0) {
1269 foreach ($attrs as $k => $v) {
1270 // if ns declarations, add to class level array of valid namespaces
1271 if (preg_match('/^xmlns/', $k)) {
1272 //$this->xdebug("$k: $v");
1273 //$this->xdebug('ns_prefix: '.$this->getPrefix($k));
1274 if ($ns_prefix = substr(strrchr($k, ':'), 1)) {
1275 //$this->xdebug("Add namespace[$ns_prefix] = $v");
1276 $this->namespaces[$ns_prefix] = $v;
1277 } else {
1278 $this->defaultNamespace[$pos] = $v;
1279 if (! $this->getPrefixFromNamespace($v)) {
1280 $this->namespaces['ns' . (count($this->namespaces) + 1)] = $v;
1281 }
1282 }
1283 if ($v == 'http://www.w3.org/2001/XMLSchema' || $v == 'http://www.w3.org/1999/XMLSchema' || $v == 'http://www.w3.org/2000/10/XMLSchema') {
1284 $this->XMLSchemaVersion = $v;
1285 $this->namespaces['xsi'] = $v . '-instance';
1286 }
1287 }
1288 }
1289 foreach ($attrs as $k => $v) {
1290 // expand each attribute
1291 $k = strpos($k, ':') ? $this->expandQname($k) : $k;
1292 $v = strpos($v, ':') ? $this->expandQname($v) : $v;
1293 $eAttrs[$k] = $v;
1294 }
1295 $attrs = $eAttrs;
1296 } else {
1297 $attrs = array();
1298 }
1299 // find status, register data
1300 switch ($name) {
1301 case 'all': // (optional) compositor content for a complexType
1302 case 'choice':
1303 case 'group':
1304 case 'sequence':
1305 //$this->xdebug("compositor $name for currentComplexType: $this->currentComplexType and currentElement: $this->currentElement");
1306 $this->complexTypes[$this->currentComplexType]['compositor'] = $name;
1307 //if($name == 'all' || $name == 'sequence'){
1308 // $this->complexTypes[$this->currentComplexType]['phpType'] = 'struct';
1309 //}
1310 break;
1311 case 'attribute': // complexType attribute
1312 //$this->xdebug("parsing attribute $attrs[name] $attrs[ref] of value: ".$attrs['http://schemas.xmlsoap.org/wsdl/:arrayType']);
1313 $this->xdebug("parsing attribute:");
1314 $this->appendDebug($this->varDump($attrs));
1315 if (!isset($attrs['form'])) {
1316 $attrs['form'] = $this->schemaInfo['attributeFormDefault'];
1317 }
1318 if (isset($attrs['http://schemas.xmlsoap.org/wsdl/:arrayType'])) {
1319 $v = $attrs['http://schemas.xmlsoap.org/wsdl/:arrayType'];
1320 if (!strpos($v, ':')) {
1321 // no namespace in arrayType attribute value...
1322 if ($this->defaultNamespace[$pos]) {
1323 // ...so use the default
1324 $attrs['http://schemas.xmlsoap.org/wsdl/:arrayType'] = $this->defaultNamespace[$pos] . ':' . $attrs['http://schemas.xmlsoap.org/wsdl/:arrayType'];
1325 }
1326 }
1327 }
1328 if (isset($attrs['name'])) {
1329 $this->attributes[$attrs['name']] = $attrs;
1330 $aname = $attrs['name'];
1331 } elseif (isset($attrs['ref']) && $attrs['ref'] == 'http://schemas.xmlsoap.org/soap/encoding/:arrayType') {
1332 if (isset($attrs['http://schemas.xmlsoap.org/wsdl/:arrayType'])) {
1333 $aname = $attrs['http://schemas.xmlsoap.org/wsdl/:arrayType'];
1334 } else {
1335 $aname = '';
1336 }
1337 } elseif (isset($attrs['ref'])) {
1338 $aname = $attrs['ref'];
1339 $this->attributes[$attrs['ref']] = $attrs;
1340 }
1341
1342 if ($this->currentComplexType) { // This should *always* be
1343 $this->complexTypes[$this->currentComplexType]['attrs'][$aname] = $attrs;
1344 }
1345 // arrayType attribute
1346 if (isset($attrs['http://schemas.xmlsoap.org/wsdl/:arrayType']) || $this->getLocalPart($aname) == 'arrayType') {
1347 $this->complexTypes[$this->currentComplexType]['phpType'] = 'array';
1348 $prefix = $this->getPrefix($aname);
1349 if (isset($attrs['http://schemas.xmlsoap.org/wsdl/:arrayType'])) {
1350 $v = $attrs['http://schemas.xmlsoap.org/wsdl/:arrayType'];
1351 } else {
1352 $v = '';
1353 }
1354 if (strpos($v, '[,]')) {
1355 $this->complexTypes[$this->currentComplexType]['multidimensional'] = true;
1356 }
1357 $v = substr($v, 0, strpos($v, '[')); // clip the []
1358 if (!strpos($v, ':') && isset($this->typemap[$this->XMLSchemaVersion][$v])) {
1359 $v = $this->XMLSchemaVersion . ':' . $v;
1360 }
1361 $this->complexTypes[$this->currentComplexType]['arrayType'] = $v;
1362 }
1363 break;
1364 case 'complexContent': // (optional) content for a complexType
1365 break;
1366 case 'complexType':
1367 array_push($this->complexTypeStack, $this->currentComplexType);
1368 if (isset($attrs['name'])) {
1369 // TODO: what is the scope of named complexTypes that appear
1370 // nested within other c complexTypes?
1371 $this->xdebug('processing named complexType ' . $attrs['name']);
1372 //$this->currentElement = false;
1373 $this->currentComplexType = $attrs['name'];
1374 $this->complexTypes[$this->currentComplexType] = $attrs;
1375 $this->complexTypes[$this->currentComplexType]['typeClass'] = 'complexType';
1376 // This is for constructs like
1377 // <complexType name="ListOfString" base="soap:Array">
1378 // <sequence>
1379 // <element name="string" type="xsd:string"
1380 // minOccurs="0" maxOccurs="unbounded" />
1381 // </sequence>
1382 // </complexType>
1383 if (isset($attrs['base']) && preg_match('/:Array$/', $attrs['base'])) {
1384 $this->xdebug('complexType is unusual array');
1385 $this->complexTypes[$this->currentComplexType]['phpType'] = 'array';
1386 } else {
1387 $this->complexTypes[$this->currentComplexType]['phpType'] = 'struct';
1388 }
1389 } else {
1390 $name = $this->CreateTypeName($this->currentElement);
1391 $this->xdebug('processing unnamed complexType for element ' . $this->currentElement . ' named ' . $name);
1392 $this->currentComplexType = $name;
1393 //$this->currentElement = false;
1394 $this->complexTypes[$this->currentComplexType] = $attrs;
1395 $this->complexTypes[$this->currentComplexType]['typeClass'] = 'complexType';
1396 // This is for constructs like
1397 // <complexType name="ListOfString" base="soap:Array">
1398 // <sequence>
1399 // <element name="string" type="xsd:string"
1400 // minOccurs="0" maxOccurs="unbounded" />
1401 // </sequence>
1402 // </complexType>
1403 if (isset($attrs['base']) && preg_match('/:Array$/', $attrs['base'])) {
1404 $this->xdebug('complexType is unusual array');
1405 $this->complexTypes[$this->currentComplexType]['phpType'] = 'array';
1406 } else {
1407 $this->complexTypes[$this->currentComplexType]['phpType'] = 'struct';
1408 }
1409 }
1410 break;
1411 case 'element':
1412 array_push($this->elementStack, $this->currentElement);
1413 if (!isset($attrs['form'])) {
1414 $attrs['form'] = $this->schemaInfo['elementFormDefault'];
1415 }
1416 if (isset($attrs['type'])) {
1417 $this->xdebug("processing typed element " . $attrs['name'] . " of type " . $attrs['type']);
1418 if (! $this->getPrefix($attrs['type'])) {
1419 if ($this->defaultNamespace[$pos]) {
1420 $attrs['type'] = $this->defaultNamespace[$pos] . ':' . $attrs['type'];
1421 $this->xdebug('used default namespace to make type ' . $attrs['type']);
1422 }
1423 }
1424 // This is for constructs like
1425 // <complexType name="ListOfString" base="soap:Array">
1426 // <sequence>
1427 // <element name="string" type="xsd:string"
1428 // minOccurs="0" maxOccurs="unbounded" />
1429 // </sequence>
1430 // </complexType>
1431 if ($this->currentComplexType && $this->complexTypes[$this->currentComplexType]['phpType'] == 'array') {
1432 $this->xdebug('arrayType for unusual array is ' . $attrs['type']);
1433 $this->complexTypes[$this->currentComplexType]['arrayType'] = $attrs['type'];
1434 }
1435 $this->currentElement = $attrs['name'];
1436 $ename = $attrs['name'];
1437 } elseif (isset($attrs['ref'])) {
1438 $this->xdebug("processing element as ref to " . $attrs['ref']);
1439 $this->currentElement = "ref to " . $attrs['ref'];
1440 $ename = $this->getLocalPart($attrs['ref']);
1441 } else {
1442 $type = $this->CreateTypeName($this->currentComplexType . '_' . $attrs['name']);
1443 $this->xdebug("processing untyped element " . $attrs['name'] . ' type ' . $type);
1444 $this->currentElement = $attrs['name'];
1445 $attrs['type'] = $this->schemaTargetNamespace . ':' . $type;
1446 $ename = $attrs['name'];
1447 }
1448 if (isset($ename) && $this->currentComplexType) {
1449 $this->xdebug("add element $ename to complexType $this->currentComplexType");
1450 $this->complexTypes[$this->currentComplexType]['elements'][$ename] = $attrs;
1451 } elseif (!isset($attrs['ref'])) {
1452 $this->xdebug("add element $ename to elements array");
1453 $this->elements[ $attrs['name'] ] = $attrs;
1454 $this->elements[ $attrs['name'] ]['typeClass'] = 'element';
1455 }
1456 break;
1457 case 'enumeration': // restriction value list member
1458 $this->xdebug('enumeration ' . $attrs['value']);
1459 if ($this->currentSimpleType) {
1460 $this->simpleTypes[$this->currentSimpleType]['enumeration'][] = $attrs['value'];
1461 } elseif ($this->currentComplexType) {
1462 $this->complexTypes[$this->currentComplexType]['enumeration'][] = $attrs['value'];
1463 }
1464 break;
1465 case 'extension': // simpleContent or complexContent type extension
1466 $this->xdebug('extension ' . $attrs['base']);
1467 if ($this->currentComplexType) {
1468 $this->complexTypes[$this->currentComplexType]['extensionBase'] = $attrs['base'];
1469 }
1470 break;
1471 case 'import':
1472 if (isset($attrs['schemaLocation'])) {
1473 //$this->xdebug('import namespace ' . $attrs['namespace'] . ' from ' . $attrs['schemaLocation']);
1474 $this->imports[$attrs['namespace']][] = array('location' => $attrs['schemaLocation'], 'loaded' => false);
1475 } else {
1476 //$this->xdebug('import namespace ' . $attrs['namespace']);
1477 $this->imports[$attrs['namespace']][] = array('location' => '', 'loaded' => true);
1478 if (! $this->getPrefixFromNamespace($attrs['namespace'])) {
1479 $this->namespaces['ns' . (count($this->namespaces) + 1)] = $attrs['namespace'];
1480 }
1481 }
1482 break;
1483 case 'list': // simpleType value list
1484 break;
1485 case 'restriction': // simpleType, simpleContent or complexContent value restriction
1486 $this->xdebug('restriction ' . $attrs['base']);
1487 if ($this->currentSimpleType) {
1488 $this->simpleTypes[$this->currentSimpleType]['type'] = $attrs['base'];
1489 } elseif ($this->currentComplexType) {
1490 $this->complexTypes[$this->currentComplexType]['restrictionBase'] = $attrs['base'];
1491 if (strstr($attrs['base'], ':') == ':Array') {
1492 $this->complexTypes[$this->currentComplexType]['phpType'] = 'array';
1493 }
1494 }
1495 break;
1496 case 'schema':
1497 $this->schemaInfo = $attrs;
1498 $this->schemaInfo['schemaVersion'] = $this->getNamespaceFromPrefix($prefix);
1499 if (isset($attrs['targetNamespace'])) {
1500 $this->schemaTargetNamespace = $attrs['targetNamespace'];
1501 }
1502 if (!isset($attrs['elementFormDefault'])) {
1503 $this->schemaInfo['elementFormDefault'] = 'unqualified';
1504 }
1505 if (!isset($attrs['attributeFormDefault'])) {
1506 $this->schemaInfo['attributeFormDefault'] = 'unqualified';
1507 }
1508 break;
1509 case 'simpleContent': // (optional) content for a complexType
1510 break;
1511 case 'simpleType':
1512 array_push($this->simpleTypeStack, $this->currentSimpleType);
1513 if (isset($attrs['name'])) {
1514 $this->xdebug("processing simpleType for name " . $attrs['name']);
1515 $this->currentSimpleType = $attrs['name'];
1516 $this->simpleTypes[ $attrs['name'] ] = $attrs;
1517 $this->simpleTypes[ $attrs['name'] ]['typeClass'] = 'simpleType';
1518 $this->simpleTypes[ $attrs['name'] ]['phpType'] = 'scalar';
1519 } else {
1520 $name = $this->CreateTypeName($this->currentComplexType . '_' . $this->currentElement);
1521 $this->xdebug('processing unnamed simpleType for element ' . $this->currentElement . ' named ' . $name);
1522 $this->currentSimpleType = $name;
1523 //$this->currentElement = false;
1524 $this->simpleTypes[$this->currentSimpleType] = $attrs;
1525 $this->simpleTypes[$this->currentSimpleType]['phpType'] = 'scalar';
1526 }
1527 break;
1528 case 'union': // simpleType type list
1529 break;
1530 default:
1531 //$this->xdebug("do not have anything to do for element $name");
1532 }
1533 }
1534
1542 public function schemaEndElement($parser, $name)
1543 {
1544 // bring depth down a notch
1545 $this->depth--;
1546 // position of current element is equal to the last value left in depth_array for my depth
1547 if (isset($this->depth_array[$this->depth])) {
1548 $pos = $this->depth_array[$this->depth];
1549 }
1550 // get element prefix
1551 if ($prefix = $this->getPrefix($name)) {
1552 // get unqualified name
1553 $name = $this->getLocalPart($name);
1554 } else {
1555 $prefix = '';
1556 }
1557 // move on...
1558 if ($name == 'complexType') {
1559 $this->xdebug('done processing complexType ' . ($this->currentComplexType ? $this->currentComplexType : '(unknown)'));
1560 $this->currentComplexType = array_pop($this->complexTypeStack);
1561 //$this->currentElement = false;
1562 }
1563 if ($name == 'element') {
1564 $this->xdebug('done processing element ' . ($this->currentElement ? $this->currentElement : '(unknown)'));
1565 $this->currentElement = array_pop($this->elementStack);
1566 }
1567 if ($name == 'simpleType') {
1568 $this->xdebug('done processing simpleType ' . ($this->currentSimpleType ? $this->currentSimpleType : '(unknown)'));
1569 $this->currentSimpleType = array_pop($this->simpleTypeStack);
1570 }
1571 }
1572
1581 {
1582 $pos = $this->depth_array[$this->depth - 1];
1583 $this->message[$pos]['cdata'] .= $data;
1584 }
1585
1591 public function serializeSchema()
1592 {
1593 $schemaPrefix = $this->getPrefixFromNamespace($this->XMLSchemaVersion);
1594 $xml = '';
1595 // imports
1596 if (sizeof($this->imports) > 0) {
1597 foreach ($this->imports as $ns => $list) {
1598 foreach ($list as $ii) {
1599 if ($ii['location'] != '') {
1600 $xml .= " <$schemaPrefix:import location=\"" . $ii['location'] . '" namespace="' . $ns . "\" />\n";
1601 } else {
1602 $xml .= " <$schemaPrefix:import namespace=\"" . $ns . "\" />\n";
1603 }
1604 }
1605 }
1606 }
1607 // complex types
1608 foreach ($this->complexTypes as $typeName => $attrs) {
1609 $contentStr = '';
1610 // serialize child elements
1611 if (isset($attrs['elements']) && (count($attrs['elements']) > 0)) {
1612 foreach ($attrs['elements'] as $element => $eParts) {
1613 if (isset($eParts['ref'])) {
1614 $contentStr .= " <$schemaPrefix:element ref=\"$element\"/>\n";
1615 } else {
1616 $contentStr .= " <$schemaPrefix:element name=\"$element\" type=\"" . $this->contractQName($eParts['type']) . "\"";
1617 foreach ($eParts as $aName => $aValue) {
1618 // handle, e.g., abstract, default, form, minOccurs, maxOccurs, nillable
1619 if ($aName != 'name' && $aName != 'type') {
1620 $contentStr .= " $aName=\"$aValue\"";
1621 }
1622 }
1623 $contentStr .= "/>\n";
1624 }
1625 }
1626 // compositor wraps elements
1627 if (isset($attrs['compositor']) && ($attrs['compositor'] != '')) {
1628 $contentStr = " <$schemaPrefix:$attrs[compositor]>\n" . $contentStr . " </$schemaPrefix:$attrs[compositor]>\n";
1629 }
1630 }
1631 // attributes
1632 if (isset($attrs['attrs']) && (count($attrs['attrs']) >= 1)) {
1633 foreach ($attrs['attrs'] as $attr => $aParts) {
1634 $contentStr .= " <$schemaPrefix:attribute";
1635 foreach ($aParts as $a => $v) {
1636 if ($a == 'ref' || $a == 'type') {
1637 $contentStr .= " $a=\"" . $this->contractQName($v) . '"';
1638 } elseif ($a == 'http://schemas.xmlsoap.org/wsdl/:arrayType') {
1639 $this->usedNamespaces['wsdl'] = $this->namespaces['wsdl'];
1640 $contentStr .= ' wsdl:arrayType="' . $this->contractQName($v) . '"';
1641 } else {
1642 $contentStr .= " $a=\"$v\"";
1643 }
1644 }
1645 $contentStr .= "/>\n";
1646 }
1647 }
1648 // if restriction
1649 if (isset($attrs['restrictionBase']) && $attrs['restrictionBase'] != '') {
1650 $contentStr = " <$schemaPrefix:restriction base=\"" . $this->contractQName($attrs['restrictionBase']) . "\">\n" . $contentStr . " </$schemaPrefix:restriction>\n";
1651 // complex or simple content
1652 if ((isset($attrs['elements']) && count($attrs['elements']) > 0) || (isset($attrs['attrs']) && count($attrs['attrs']) > 0)) {
1653 $contentStr = " <$schemaPrefix:complexContent>\n" . $contentStr . " </$schemaPrefix:complexContent>\n";
1654 }
1655 }
1656 // finalize complex type
1657 if ($contentStr != '') {
1658 $contentStr = " <$schemaPrefix:complexType name=\"$typeName\">\n" . $contentStr . " </$schemaPrefix:complexType>\n";
1659 } else {
1660 $contentStr = " <$schemaPrefix:complexType name=\"$typeName\"/>\n";
1661 }
1662 $xml .= $contentStr;
1663 }
1664 // simple types
1665 if (isset($this->simpleTypes) && count($this->simpleTypes) > 0) {
1666 foreach ($this->simpleTypes as $typeName => $eParts) {
1667 $xml .= " <$schemaPrefix:simpleType name=\"$typeName\">\n <$schemaPrefix:restriction base=\"" . $this->contractQName($eParts['type']) . "\">\n";
1668 if (isset($eParts['enumeration'])) {
1669 foreach ($eParts['enumeration'] as $e) {
1670 $xml .= " <$schemaPrefix:enumeration value=\"$e\"/>\n";
1671 }
1672 }
1673 $xml .= " </$schemaPrefix:restriction>\n </$schemaPrefix:simpleType>";
1674 }
1675 }
1676 // elements
1677 if (isset($this->elements) && count($this->elements) > 0) {
1678 foreach ($this->elements as $element => $eParts) {
1679 $xml .= " <$schemaPrefix:element name=\"$element\" type=\"" . $this->contractQName($eParts['type']) . "\"/>\n";
1680 }
1681 }
1682 // attributes
1683 if (isset($this->attributes) && count($this->attributes) > 0) {
1684 foreach ($this->attributes as $attr => $aParts) {
1685 $xml .= " <$schemaPrefix:attribute name=\"$attr\" type=\"" . $this->contractQName($aParts['type']) . "\"\n/>";
1686 }
1687 }
1688 // finish 'er up
1689 $attr = '';
1690 foreach ($this->schemaInfo as $k => $v) {
1691 if ($k == 'elementFormDefault' || $k == 'attributeFormDefault') {
1692 $attr .= " $k=\"$v\"";
1693 }
1694 }
1695 $el = "<$schemaPrefix:schema$attr targetNamespace=\"$this->schemaTargetNamespace\"\n";
1696 foreach (array_diff($this->usedNamespaces, $this->enclosingNamespaces) as $nsp => $ns) {
1697 $el .= " xmlns:$nsp=\"$ns\"";
1698 }
1699 $xml = $el . ">\n" . $xml . "</$schemaPrefix:schema>\n";
1700 return $xml;
1701 }
1702
1709 public function xdebug($string)
1710 {
1711 $this->debug('<' . $this->schemaTargetNamespace . '> ' . $string);
1712 }
1713
1726 public function getPHPType($type, $ns)
1727 {
1728 if (isset($this->typemap[$ns][$type])) {
1729 //print "found type '$type' and ns $ns in typemap<br>";
1730 return $this->typemap[$ns][$type];
1731 } elseif (isset($this->complexTypes[$type])) {
1732 //print "getting type '$type' and ns $ns from complexTypes array<br>";
1733 return $this->complexTypes[$type]['phpType'];
1734 }
1735 return false;
1736 }
1737
1760 public function getTypeDef($type)
1761 {
1762 //$this->debug("in getTypeDef for type $type");
1763 if (substr($type, -1) == '^') {
1764 $is_element = 1;
1765 $type = substr($type, 0, -1);
1766 } else {
1767 $is_element = 0;
1768 }
1769
1770 if ((! $is_element) && isset($this->complexTypes[$type])) {
1771 $this->xdebug("in getTypeDef, found complexType $type");
1772 return $this->complexTypes[$type];
1773 } elseif ((! $is_element) && isset($this->simpleTypes[$type])) {
1774 $this->xdebug("in getTypeDef, found simpleType $type");
1775 if (!isset($this->simpleTypes[$type]['phpType'])) {
1776 // get info for type to tack onto the simple type
1777 // TODO: can this ever really apply (i.e. what is a simpleType really?)
1778 $uqType = substr($this->simpleTypes[$type]['type'], strrpos($this->simpleTypes[$type]['type'], ':') + 1);
1779 $ns = substr($this->simpleTypes[$type]['type'], 0, strrpos($this->simpleTypes[$type]['type'], ':'));
1780 $etype = $this->getTypeDef($uqType);
1781 if ($etype) {
1782 $this->xdebug("in getTypeDef, found type for simpleType $type:");
1783 $this->xdebug($this->varDump($etype));
1784 if (isset($etype['phpType'])) {
1785 $this->simpleTypes[$type]['phpType'] = $etype['phpType'];
1786 }
1787 if (isset($etype['elements'])) {
1788 $this->simpleTypes[$type]['elements'] = $etype['elements'];
1789 }
1790 }
1791 }
1792 return $this->simpleTypes[$type];
1793 } elseif (isset($this->elements[$type])) {
1794 $this->xdebug("in getTypeDef, found element $type");
1795 if (!isset($this->elements[$type]['phpType'])) {
1796 // get info for type to tack onto the element
1797 $uqType = substr($this->elements[$type]['type'], strrpos($this->elements[$type]['type'], ':') + 1);
1798 $ns = substr($this->elements[$type]['type'], 0, strrpos($this->elements[$type]['type'], ':'));
1799 $etype = $this->getTypeDef($uqType);
1800 if ($etype) {
1801 $this->xdebug("in getTypeDef, found type for element $type:");
1802 $this->xdebug($this->varDump($etype));
1803 if (isset($etype['phpType'])) {
1804 $this->elements[$type]['phpType'] = $etype['phpType'];
1805 }
1806 if (isset($etype['elements'])) {
1807 $this->elements[$type]['elements'] = $etype['elements'];
1808 }
1809 } elseif ($ns == 'http://www.w3.org/2001/XMLSchema') {
1810 $this->xdebug("in getTypeDef, element $type is an XSD type");
1811 $this->elements[$type]['phpType'] = 'scalar';
1812 }
1813 }
1814 return $this->elements[$type];
1815 } elseif (isset($this->attributes[$type])) {
1816 $this->xdebug("in getTypeDef, found attribute $type");
1817 return $this->attributes[$type];
1818 } elseif (preg_match('/_ContainedType$/', $type)) {
1819 $this->xdebug("in getTypeDef, have an untyped element $type");
1820 $typeDef['typeClass'] = 'simpleType';
1821 $typeDef['phpType'] = 'scalar';
1822 $typeDef['type'] = 'http://www.w3.org/2001/XMLSchema:string';
1823 return $typeDef;
1824 }
1825 $this->xdebug("in getTypeDef, did not find $type");
1826 return false;
1827 }
1828
1837 public function serializeTypeDef($type)
1838 {
1839 //print "in sTD() for type $type<br>";
1840 if ($typeDef = $this->getTypeDef($type)) {
1841 $str .= '<' . $type;
1842 if (is_array($typeDef['attrs'])) {
1843 foreach ($typeDef['attrs'] as $attName => $data) {
1844 $str .= " $attName=\"{type = " . $data['type'] . "}\"";
1845 }
1846 }
1847 $str .= " xmlns=\"" . $this->schema['targetNamespace'] . "\"";
1848 if (count($typeDef['elements']) > 0) {
1849 $str .= ">";
1850 foreach ($typeDef['elements'] as $element => $eData) {
1851 $str .= $this->serializeTypeDef($element);
1852 }
1853 $str .= "</$type>";
1854 } elseif ($typeDef['typeClass'] == 'element') {
1855 $str .= "></$type>";
1856 } else {
1857 $str .= "/>";
1858 }
1859 return $str;
1860 }
1861 return false;
1862 }
1863
1874 public function typeToForm($name, $type)
1875 {
1876 // get typedef
1877 if ($typeDef = $this->getTypeDef($type)) {
1878 // if struct
1879 if ($typeDef['phpType'] == 'struct') {
1880 $buffer .= '<table>';
1881 foreach ($typeDef['elements'] as $child => $childDef) {
1882 $buffer .= "
1883 <tr><td align='right'>$childDef[name] (type: " . $this->getLocalPart($childDef['type']) . "):</td>
1884 <td><input type='text' name='parameters[" . $name . "][$childDef[name]]'></td></tr>";
1885 }
1886 $buffer .= '</table>';
1887 // if array
1888 } elseif ($typeDef['phpType'] == 'array') {
1889 $buffer .= '<table>';
1890 for ($i = 0;$i < 3; $i++) {
1891 $buffer .= "
1892 <tr><td align='right'>array item (type: $typeDef[arrayType]):</td>
1893 <td><input type='text' name='parameters[" . $name . "][]'></td></tr>";
1894 }
1895 $buffer .= '</table>';
1896 // if scalar
1897 } else {
1898 $buffer .= "<input type='text' name='parameters[$name]'>";
1899 }
1900 } else {
1901 $buffer .= "<input type='text' name='parameters[$name]'>";
1902 }
1903 return $buffer;
1904 }
1905
1947 public function addComplexType($name, $typeClass = 'complexType', $phpType = 'array', $compositor = '', $restrictionBase = '', $elements = array(), $attrs = array(), $arrayType = '')
1948 {
1949 $this->complexTypes[$name] = array(
1950 'name' => $name,
1951 'typeClass' => $typeClass,
1952 'phpType' => $phpType,
1953 'compositor' => $compositor,
1954 'restrictionBase' => $restrictionBase,
1955 'elements' => $elements,
1956 'attrs' => $attrs,
1957 'arrayType' => $arrayType
1958 );
1959
1960 $this->xdebug("addComplexType $name:");
1961 $this->appendDebug($this->varDump($this->complexTypes[$name]));
1962 }
1963
1976 public function addSimpleType($name, $restrictionBase = '', $typeClass = 'simpleType', $phpType = 'scalar', $enumeration = array())
1977 {
1978 $this->simpleTypes[$name] = array(
1979 'name' => $name,
1980 'typeClass' => $typeClass,
1981 'phpType' => $phpType,
1982 'type' => $restrictionBase,
1983 'enumeration' => $enumeration
1984 );
1985
1986 $this->xdebug("addSimpleType $name:");
1987 $this->appendDebug($this->varDump($this->simpleTypes[$name]));
1988 }
1989
1997 public function addElement($attrs)
1998 {
1999 if (! $this->getPrefix($attrs['type'])) {
2000 $attrs['type'] = $this->schemaTargetNamespace . ':' . $attrs['type'];
2001 }
2002 $this->elements[ $attrs['name'] ] = $attrs;
2003 $this->elements[ $attrs['name'] ]['typeClass'] = 'element';
2004
2005 $this->xdebug("addElement " . $attrs['name']);
2006 $this->appendDebug($this->varDump($this->elements[ $attrs['name'] ]));
2007 }
2008}
2009
2014{
2015}
2016
2017?><?php
2018
2019
2020
2033{
2040 public $name;
2047 public $type;
2054 public $value;
2068 public $type_ns;
2076
2088 public function __construct($name = 'soapval', $type = false, $value = -1, $element_ns = false, $type_ns = false, $attributes = false)
2089 {
2091 $this->name = $name;
2092 $this->type = $type;
2093 $this->value = $value;
2094 $this->element_ns = $element_ns;
2095 $this->type_ns = $type_ns;
2096 $this->attributes = $attributes;
2097 }
2098
2106 public function serialize($use = 'encoded')
2107 {
2108 return $this->serialize_val($this->value, $this->name, $this->type, $this->element_ns, $this->type_ns, $this->attributes, $use, true);
2109 }
2110
2117 public function decode()
2118 {
2119 return $this->value;
2120 }
2121}
2122
2123
2124
2125?><?php
2126
2127
2128
2139{
2140 public $fp;
2142 public $url = '';
2143 public $uri = '';
2144 public $digest_uri = '';
2145 public $scheme = '';
2146 public $host = '';
2147 public $port = '';
2148 public $path = '';
2149 public $request_method = 'POST';
2150 public $protocol_version = '1.0';
2151 public $encoding = '';
2152 public $outgoing_headers = array();
2153 public $incoming_headers = array();
2154 public $incoming_cookies = array();
2157 public $response_status_line; // HTTP response status line
2158 public $useSOAPAction = true;
2160 public $ch = false; // cURL handle
2161 public $ch_options = array(); // cURL custom options
2162 public $use_curl = false; // force cURL use
2163 public $proxy = null; // proxy information (associative array)
2164 public $username = '';
2165 public $password = '';
2166 public $authtype = '';
2167 public $digestRequest = array();
2168 public $certRequest = array(); // keys must be cainfofile (optional), sslcertfile, sslkeyfile, passphrase, certpassword (optional), verifypeer (optional), verifyhost (optional)
2169 // cainfofile: certificate authority file, e.g. '$pathToPemFiles/rootca.pem'
2170 // sslcertfile: SSL certificate file, e.g. '$pathToPemFiles/mycert.pem'
2171 // sslkeyfile: SSL key file, e.g. '$pathToPemFiles/mykey.pem'
2172 // passphrase: SSL key password/passphrase
2173 // certpassword: SSL certificate password
2174 // verifypeer: default is 1
2175 // verifyhost: default is 1
2176
2185 public function __construct($url, $curl_options = null, $use_curl = false)
2186 {
2188 $this->debug("ctor url=$url use_curl=$use_curl curl_options:");
2189 $this->appendDebug($this->varDump($curl_options));
2190 $this->setURL($url);
2191 if (is_array($curl_options)) {
2192 $this->ch_options = $curl_options;
2193 }
2194 $this->use_curl = $use_curl;
2195 preg_match('/\$Revisio' . 'n: ([^ ]+)/', $this->revision, $rev);
2196 // begin-patch php8
2197 $this->setHeader('User-Agent', $this->title . '/' . $this->version . ' (' . ($rev[1] ?? '1.1') . ')');
2198 }
2199
2207 public function setCurlOption($option, $value)
2208 {
2209 $this->debug("setCurlOption option=$option, value=");
2210 $this->appendDebug($this->varDump($value));
2211 curl_setopt($this->ch, $option, $value);
2212 }
2213
2221 public function setHeader($name, $value)
2222 {
2223 $this->outgoing_headers[$name] = $value;
2224 $this->debug("set header $name: $value");
2225 }
2226
2233 public function unsetHeader($name)
2234 {
2235 if (isset($this->outgoing_headers[$name])) {
2236 $this->debug("unset header $name");
2237 unset($this->outgoing_headers[$name]);
2238 }
2239 }
2240
2247 public function setURL($url)
2248 {
2249 $this->url = $url;
2250
2251 $u = parse_url($url);
2252 foreach ($u as $k => $v) {
2253 $this->debug("parsed URL $k = $v");
2254 $this->$k = $v;
2255 }
2256
2257 // add any GET params to path
2258 if (isset($u['query']) && $u['query'] != '') {
2259 $this->path .= '?' . $u['query'];
2260 }
2261
2262 // set default port
2263 if (!isset($u['port'])) {
2264 if ($u['scheme'] == 'https') {
2265 $this->port = 443;
2266 } else {
2267 $this->port = 80;
2268 }
2269 }
2270
2271 $this->uri = $this->path;
2272 $this->digest_uri = $this->uri;
2273
2274 // build headers
2275 if (!isset($u['port'])) {
2276 $this->setHeader('Host', $this->host);
2277 } else {
2278 $this->setHeader('Host', $this->host . ':' . $this->port);
2279 }
2280
2281 if (isset($u['user']) && $u['user'] != '') {
2282 $this->setCredentials(urldecode($u['user']), isset($u['pass']) ? urldecode($u['pass']) : '');
2283 }
2284 }
2285
2292 public function io_method()
2293 {
2294 if ($this->use_curl || ($this->scheme == 'https') || ($this->scheme == 'http' && $this->authtype == 'ntlm') || ($this->scheme == 'http' && is_array($this->proxy) && $this->proxy['authtype'] == 'ntlm')) {
2295 return 'curl';
2296 }
2297 if (($this->scheme == 'http' || $this->scheme == 'ssl') && $this->authtype != 'ntlm' && (!is_array($this->proxy) || $this->proxy['authtype'] != 'ntlm')) {
2298 return 'socket';
2299 }
2300 return 'unknown';
2301 }
2302
2311 public function connect($connection_timeout = 0, $response_timeout = 30)
2312 {
2313 // For PHP 4.3 with OpenSSL, change https scheme to ssl, then treat like
2314 // "regular" socket.
2315 // TODO: disabled for now because OpenSSL must be *compiled* in (not just
2316 // loaded), and until PHP5 stream_get_wrappers is not available.
2317 // if ($this->scheme == 'https') {
2318 // if (version_compare(phpversion(), '4.3.0') >= 0) {
2319 // if (extension_loaded('openssl')) {
2320 // $this->scheme = 'ssl';
2321 // $this->debug('Using SSL over OpenSSL');
2322 // }
2323 // }
2324 // }
2325 $this->debug("connect connection_timeout $connection_timeout, response_timeout $response_timeout, scheme $this->scheme, host $this->host, port $this->port");
2326 if ($this->io_method() == 'socket') {
2327 if (!is_array($this->proxy)) {
2330 } else {
2331 $host = $this->proxy['host'];
2332 $port = $this->proxy['port'];
2333 }
2334
2335 // use persistent connection
2336 if ($this->persistentConnection && isset($this->fp) && is_resource($this->fp)) {
2337 if (!feof($this->fp)) {
2338 $this->debug('Re-use persistent connection');
2339 return true;
2340 }
2341 fclose($this->fp);
2342 $this->debug('Closed persistent connection at EOF');
2343 }
2344
2345 // munge host if using OpenSSL
2346 if ($this->scheme == 'ssl') {
2347 $host = 'ssl://' . $host;
2348 }
2349 $this->debug('calling fsockopen with host ' . $host . ' connection_timeout ' . $connection_timeout);
2350
2351 // open socket
2352 if ($connection_timeout > 0) {
2353 $this->fp = @fsockopen($host, $this->port, $this->errno, $this->error_str, $connection_timeout);
2354 } else {
2355 $this->fp = @fsockopen($host, $this->port, $this->errno, $this->error_str);
2356 }
2357
2358 // test pointer
2359 if (!$this->fp) {
2360 $msg = 'Couldn\'t open socket connection to server ' . $this->url;
2361 if ($this->errno) {
2362 $msg .= ', Error (' . $this->errno . '): ' . $this->error_str;
2363 } else {
2364 $msg .= ' prior to connect(). This is often a problem looking up the host name.';
2365 }
2366 $this->debug($msg);
2367 $this->setError($msg);
2368 return false;
2369 }
2370
2371 // set response timeout
2372 $this->debug('set response timeout to ' . $response_timeout);
2373 socket_set_timeout($this->fp, $response_timeout);
2374
2375 $this->debug('socket connected');
2376 return true;
2377 } elseif ($this->io_method() == 'curl') {
2378 if (!extension_loaded('curl')) {
2379 // $this->setError('cURL Extension, or OpenSSL extension w/ PHP version >= 4.3 is required for HTTPS');
2380 $this->setError('The PHP cURL Extension is required for HTTPS or NLTM. You will need to re-build or update your PHP to included cURL.');
2381 return false;
2382 }
2383 // Avoid warnings when PHP does not have these options
2384 if (defined('CURLOPT_CONNECTIONTIMEOUT')) {
2385 $CURLOPT_CONNECTIONTIMEOUT = CURLOPT_CONNECTIONTIMEOUT;
2386 } else {
2387 $CURLOPT_CONNECTIONTIMEOUT = 78;
2388 }
2389 if (defined('CURLOPT_HTTPAUTH')) {
2390 $CURLOPT_HTTPAUTH = CURLOPT_HTTPAUTH;
2391 } else {
2392 $CURLOPT_HTTPAUTH = 107;
2393 }
2394 if (defined('CURLOPT_PROXYAUTH')) {
2395 $CURLOPT_PROXYAUTH = CURLOPT_PROXYAUTH;
2396 } else {
2397 $CURLOPT_PROXYAUTH = 111;
2398 }
2399 if (defined('CURLAUTH_BASIC')) {
2400 $CURLAUTH_BASIC = CURLAUTH_BASIC;
2401 } else {
2402 $CURLAUTH_BASIC = 1;
2403 }
2404 if (defined('CURLAUTH_DIGEST')) {
2405 $CURLAUTH_DIGEST = CURLAUTH_DIGEST;
2406 } else {
2407 $CURLAUTH_DIGEST = 2;
2408 }
2409 if (defined('CURLAUTH_NTLM')) {
2410 $CURLAUTH_NTLM = CURLAUTH_NTLM;
2411 } else {
2412 $CURLAUTH_NTLM = 8;
2413 }
2414
2415 $this->debug('connect using cURL');
2416 // init CURL
2417 $this->ch = curl_init();
2418 // set url
2419 $hostURL = ($this->port != '') ? "$this->scheme://$this->host:$this->port" : "$this->scheme://$this->host";
2420 // add path
2421 $hostURL .= $this->path;
2422 $this->setCurlOption(CURLOPT_URL, $hostURL);
2423 // follow location headers (re-directs)
2424 if (ini_get('safe_mode') || ini_get('open_basedir')) {
2425 $this->debug('safe_mode or open_basedir set, so do not set CURLOPT_FOLLOWLOCATION');
2426 $this->debug('safe_mode = ');
2427 $this->appendDebug($this->varDump(ini_get('safe_mode')));
2428 $this->debug('open_basedir = ');
2429 $this->appendDebug($this->varDump(ini_get('open_basedir')));
2430 } else {
2431 $this->setCurlOption(CURLOPT_FOLLOWLOCATION, 1);
2432 }
2433 // ask for headers in the response output
2434 $this->setCurlOption(CURLOPT_HEADER, 1);
2435 // ask for the response output as the return value
2436 $this->setCurlOption(CURLOPT_RETURNTRANSFER, 1);
2437 // encode
2438 // We manage this ourselves through headers and encoding
2439 // if(function_exists('gzuncompress')){
2440 // $this->setCurlOption(CURLOPT_ENCODING, 'deflate');
2441 // }
2442 // persistent connection
2443 if ($this->persistentConnection) {
2444 // I believe the following comment is now bogus, having applied to
2445 // the code when it used CURLOPT_CUSTOMREQUEST to send the request.
2446 // The way we send data, we cannot use persistent connections, since
2447 // there will be some "junk" at the end of our request.
2448 //$this->setCurlOption(CURL_HTTP_VERSION_1_1, true);
2449 $this->persistentConnection = false;
2450 $this->setHeader('Connection', 'close');
2451 }
2452 // set timeouts
2453 if ($connection_timeout != 0) {
2454 $this->setCurlOption($CURLOPT_CONNECTIONTIMEOUT, $connection_timeout);
2455 }
2456 if ($response_timeout != 0) {
2457 $this->setCurlOption(CURLOPT_TIMEOUT, $response_timeout);
2458 }
2459
2460 if ($this->scheme == 'https') {
2461 $this->debug('set cURL SSL verify options');
2462 // recent versions of cURL turn on peer/host checking by default,
2463 // while PHP binaries are not compiled with a default location for the
2464 // CA cert bundle, so disable peer/host checking.
2465 //$this->setCurlOption(CURLOPT_CAINFO, 'f:\php-4.3.2-win32\extensions\curl-ca-bundle.crt');
2466 $this->setCurlOption(CURLOPT_SSL_VERIFYPEER, 0);
2467 $this->setCurlOption(CURLOPT_SSL_VERIFYHOST, 0);
2468
2469 // support client certificates (thanks Tobias Boes, Doug Anarino, Eryan Ariobowo)
2470 if ($this->authtype == 'certificate') {
2471 $this->debug('set cURL certificate options');
2472 if (isset($this->certRequest['cainfofile'])) {
2473 $this->setCurlOption(CURLOPT_CAINFO, $this->certRequest['cainfofile']);
2474 }
2475 if (isset($this->certRequest['verifypeer'])) {
2476 $this->setCurlOption(CURLOPT_SSL_VERIFYPEER, $this->certRequest['verifypeer']);
2477 } else {
2478 $this->setCurlOption(CURLOPT_SSL_VERIFYPEER, 1);
2479 }
2480 if (isset($this->certRequest['verifyhost'])) {
2481 $this->setCurlOption(CURLOPT_SSL_VERIFYHOST, $this->certRequest['verifyhost']);
2482 } else {
2483 $this->setCurlOption(CURLOPT_SSL_VERIFYHOST, 1);
2484 }
2485 if (isset($this->certRequest['sslcertfile'])) {
2486 $this->setCurlOption(CURLOPT_SSLCERT, $this->certRequest['sslcertfile']);
2487 }
2488 if (isset($this->certRequest['sslkeyfile'])) {
2489 $this->setCurlOption(CURLOPT_SSLKEY, $this->certRequest['sslkeyfile']);
2490 }
2491 if (isset($this->certRequest['passphrase'])) {
2492 $this->setCurlOption(CURLOPT_SSLKEYPASSWD, $this->certRequest['passphrase']);
2493 }
2494 if (isset($this->certRequest['certpassword'])) {
2495 $this->setCurlOption(CURLOPT_SSLCERTPASSWD, $this->certRequest['certpassword']);
2496 }
2497 }
2498 }
2499 if ($this->authtype && ($this->authtype != 'certificate')) {
2500 if ($this->username) {
2501 $this->debug('set cURL username/password');
2502 $this->setCurlOption(CURLOPT_USERPWD, "$this->username:$this->password");
2503 }
2504 if ($this->authtype == 'basic') {
2505 $this->debug('set cURL for Basic authentication');
2506 $this->setCurlOption($CURLOPT_HTTPAUTH, $CURLAUTH_BASIC);
2507 }
2508 if ($this->authtype == 'digest') {
2509 $this->debug('set cURL for digest authentication');
2510 $this->setCurlOption($CURLOPT_HTTPAUTH, $CURLAUTH_DIGEST);
2511 }
2512 if ($this->authtype == 'ntlm') {
2513 $this->debug('set cURL for NTLM authentication');
2514 $this->setCurlOption($CURLOPT_HTTPAUTH, $CURLAUTH_NTLM);
2515 }
2516 }
2517 if (is_array($this->proxy)) {
2518 $this->debug('set cURL proxy options');
2519 if ($this->proxy['port'] != '') {
2520 $this->setCurlOption(CURLOPT_PROXY, $this->proxy['host'] . ':' . $this->proxy['port']);
2521 } else {
2522 $this->setCurlOption(CURLOPT_PROXY, $this->proxy['host']);
2523 }
2524 if ($this->proxy['username'] || $this->proxy['password']) {
2525 $this->debug('set cURL proxy authentication options');
2526 $this->setCurlOption(CURLOPT_PROXYUSERPWD, $this->proxy['username'] . ':' . $this->proxy['password']);
2527 if ($this->proxy['authtype'] == 'basic') {
2528 $this->setCurlOption($CURLOPT_PROXYAUTH, $CURLAUTH_BASIC);
2529 }
2530 if ($this->proxy['authtype'] == 'ntlm') {
2531 $this->setCurlOption($CURLOPT_PROXYAUTH, $CURLAUTH_NTLM);
2532 }
2533 }
2534 }
2535 $this->debug('cURL connection set up');
2536 return true;
2537 } else {
2538 $this->setError('Unknown scheme ' . $this->scheme);
2539 $this->debug('Unknown scheme ' . $this->scheme);
2540 return false;
2541 }
2542 }
2543
2554 public function send($data, $timeout = 0, $response_timeout = 30, $cookies = null)
2555 {
2556 $this->debug('entered send() with data of length: ' . strlen($data));
2557
2558 $this->tryagain = true;
2559 $tries = 0;
2560 while ($this->tryagain) {
2561 $this->tryagain = false;
2562 if ($tries++ < 2) {
2563 // make connnection
2564 if (!$this->connect($timeout, $response_timeout)) {
2565 return false;
2566 }
2567
2568 // send request
2569 if (!$this->sendRequest($data, $cookies)) {
2570 return false;
2571 }
2572
2573 // get response
2574 $respdata = $this->getResponse();
2575 } else {
2576 $this->setError("Too many tries to get an OK response ($this->response_status_line)");
2577 }
2578 }
2579 $this->debug('end of send()');
2580 return $respdata;
2581 }
2582
2583
2595 public function sendHTTPS($data, $timeout = 0, $response_timeout = 30, $cookies = null)
2596 {
2597 return $this->send($data, $timeout, $response_timeout, $cookies);
2598 }
2599
2610 public function setCredentials($username, $password, $authtype = 'basic', $digestRequest = array(), $certRequest = array())
2611 {
2612 $this->debug("setCredentials username=$username authtype=$authtype digestRequest=");
2613 $this->appendDebug($this->varDump($digestRequest));
2614 $this->debug("certRequest=");
2615 $this->appendDebug($this->varDump($certRequest));
2616 // cf. RFC 2617
2617 if ($authtype == 'basic') {
2618 $this->setHeader('Authorization', 'Basic ' . base64_encode(str_replace(':', '', $username) . ':' . $password));
2619 } elseif ($authtype == 'digest') {
2620 if (isset($digestRequest['nonce'])) {
2621 $digestRequest['nc'] = isset($digestRequest['nc']) ? $digestRequest['nc']++ : 1;
2622
2623 // calculate the Digest hashes (calculate code based on digest implementation found at: http://www.rassoc.com/gregr/weblog/stories/2002/07/09/webServicesSecurityHttpDigestAuthenticationWithoutActiveDirectory.html)
2624
2625 // A1 = unq(username-value) ":" unq(realm-value) ":" passwd
2626 $A1 = $username . ':' . (isset($digestRequest['realm']) ? $digestRequest['realm'] : '') . ':' . $password;
2627
2628 // H(A1) = MD5(A1)
2629 $HA1 = md5($A1);
2630
2631 // A2 = Method ":" digest-uri-value
2632 $A2 = $this->request_method . ':' . $this->digest_uri;
2633
2634 // H(A2)
2635 $HA2 = md5($A2);
2636
2637 // KD(secret, data) = H(concat(secret, ":", data))
2638 // if qop == auth:
2639 // request-digest = <"> < KD ( H(A1), unq(nonce-value)
2640 // ":" nc-value
2641 // ":" unq(cnonce-value)
2642 // ":" unq(qop-value)
2643 // ":" H(A2)
2644 // ) <">
2645 // if qop is missing,
2646 // request-digest = <"> < KD ( H(A1), unq(nonce-value) ":" H(A2) ) > <">
2647
2648 $unhashedDigest = '';
2649 $nonce = isset($digestRequest['nonce']) ? $digestRequest['nonce'] : '';
2650 $cnonce = $nonce;
2651 if ($digestRequest['qop'] != '') {
2652 $unhashedDigest = $HA1 . ':' . $nonce . ':' . sprintf("%08d", $digestRequest['nc']) . ':' . $cnonce . ':' . $digestRequest['qop'] . ':' . $HA2;
2653 } else {
2654 $unhashedDigest = $HA1 . ':' . $nonce . ':' . $HA2;
2655 }
2656
2657 $hashedDigest = md5($unhashedDigest);
2658
2659 $opaque = '';
2660 if (isset($digestRequest['opaque'])) {
2661 $opaque = ', opaque="' . $digestRequest['opaque'] . '"';
2662 }
2663
2664 $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 . '"');
2665 }
2666 } elseif ($authtype == 'certificate') {
2667 $this->certRequest = $certRequest;
2668 $this->debug('Authorization header not set for certificate');
2669 } elseif ($authtype == 'ntlm') {
2670 // do nothing
2671 $this->debug('Authorization header not set for ntlm');
2672 }
2673 $this->username = $username;
2674 $this->password = $password;
2675 $this->authtype = $authtype;
2676 $this->digestRequest = $digestRequest;
2677 }
2678
2685 public function setSOAPAction($soapaction)
2686 {
2687 $this->setHeader('SOAPAction', '"' . $soapaction . '"');
2688 }
2689
2696 public function setEncoding($enc = 'gzip, deflate')
2697 {
2698 if (function_exists('gzdeflate')) {
2699 $this->protocol_version = '1.1';
2700 $this->setHeader('Accept-Encoding', $enc);
2701 if (!isset($this->outgoing_headers['Connection'])) {
2702 $this->setHeader('Connection', 'close');
2703 $this->persistentConnection = false;
2704 }
2705 #set_magic_quotes_runtime(0);
2706 // deprecated
2707 $this->encoding = $enc;
2708 }
2709 }
2710
2721 public function setProxy($proxyhost, $proxyport, $proxyusername = '', $proxypassword = '', $proxyauthtype = 'basic')
2722 {
2723 if ($proxyhost) {
2724 $this->proxy = array(
2725 'host' => $proxyhost,
2726 'port' => $proxyport,
2727 'username' => $proxyusername,
2728 'password' => $proxypassword,
2729 'authtype' => $proxyauthtype
2730 );
2731 if ($proxyusername != '' && $proxypassword != '' && $proxyauthtype = 'basic') {
2732 $this->setHeader('Proxy-Authorization', ' Basic ' . base64_encode($proxyusername . ':' . $proxypassword));
2733 }
2734 } else {
2735 $this->debug('remove proxy');
2736 $proxy = null;
2737 unsetHeader('Proxy-Authorization');
2738 }
2739 }
2740
2741
2751 {
2752 $skipHeaders = array( 'HTTP/1.1 100',
2753 'HTTP/1.0 301',
2754 'HTTP/1.1 301',
2755 'HTTP/1.0 302',
2756 'HTTP/1.1 302',
2757 'HTTP/1.0 401',
2758 'HTTP/1.1 401',
2759 'HTTP/1.0 200 Connection established');
2760 foreach ($skipHeaders as $hd) {
2761 $prefix = substr($data, 0, strlen($hd));
2762 if ($prefix == $hd) {
2763 return true;
2764 }
2765 }
2766
2767 return false;
2768 }
2769
2780 public function decodeChunked($buffer, $lb)
2781 {
2782 // length := 0
2783 $length = 0;
2784 $new = '';
2785
2786 // read chunk-size, chunk-extension (if any) and CRLF
2787 // get the position of the linebreak
2788 $chunkend = strpos($buffer, $lb);
2789 if ($chunkend == false) {
2790 $this->debug('no linebreak found in decodeChunked');
2791 return $new;
2792 }
2793 $temp = substr($buffer, 0, $chunkend);
2794 $chunk_size = hexdec(trim($temp));
2795 $chunkstart = $chunkend + strlen($lb);
2796 // while (chunk-size > 0) {
2797 while ($chunk_size > 0) {
2798 $this->debug("chunkstart: $chunkstart chunk_size: $chunk_size");
2799 $chunkend = strpos($buffer, $lb, $chunkstart + $chunk_size);
2800
2801 // Just in case we got a broken connection
2802 if ($chunkend == false) {
2803 $chunk = substr($buffer, $chunkstart);
2804 // append chunk-data to entity-body
2805 $new .= $chunk;
2806 $length += strlen($chunk);
2807 break;
2808 }
2809
2810 // read chunk-data and CRLF
2811 $chunk = substr($buffer, $chunkstart, $chunkend - $chunkstart);
2812 // append chunk-data to entity-body
2813 $new .= $chunk;
2814 // length := length + chunk-size
2815 $length += strlen($chunk);
2816 // read chunk-size and CRLF
2817 $chunkstart = $chunkend + strlen($lb);
2818
2819 $chunkend = strpos($buffer, $lb, $chunkstart) + strlen($lb);
2820 if ($chunkend == false) {
2821 break; //Just in case we got a broken connection
2822 }
2823 $temp = substr($buffer, $chunkstart, $chunkend - $chunkstart);
2824 $chunk_size = hexdec(trim($temp));
2825 $chunkstart = $chunkend;
2826 }
2827 return $new;
2828 }
2829
2838 public function buildPayload($data, $cookie_str = '')
2839 {
2840 // Note: for cURL connections, $this->outgoing_payload is ignored,
2841 // as is the Content-Length header, but these are still created as
2842 // debugging guides.
2843
2844 // add content-length header
2845 $this->setHeader('Content-Length', strlen($data));
2846
2847 // start building outgoing payload:
2848 if ($this->proxy) {
2849 $uri = $this->url;
2850 } else {
2851 $uri = $this->uri;
2852 }
2853 $req = "$this->request_method $uri HTTP/$this->protocol_version";
2854 $this->debug("HTTP request: $req");
2855 $this->outgoing_payload = "$req\r\n";
2856
2857 // loop thru headers, serializing
2858 foreach ($this->outgoing_headers as $k => $v) {
2859 $hdr = $k . ': ' . $v;
2860 $this->debug("HTTP header: $hdr");
2861 $this->outgoing_payload .= "$hdr\r\n";
2862 }
2863
2864 // add any cookies
2865 if ($cookie_str != '') {
2866 $hdr = 'Cookie: ' . $cookie_str;
2867 $this->debug("HTTP header: $hdr");
2868 $this->outgoing_payload .= "$hdr\r\n";
2869 }
2870
2871 // header/body separator
2872 $this->outgoing_payload .= "\r\n";
2873
2874 // add data
2875 $this->outgoing_payload .= $data;
2876 }
2877
2886 public function sendRequest($data, $cookies = null)
2887 {
2888 // build cookie string
2889 $cookie_str = $this->getCookiesForRequest($cookies, (($this->scheme == 'ssl') || ($this->scheme == 'https')));
2890
2891 // build payload
2892 $this->buildPayload($data, $cookie_str);
2893
2894 if ($this->io_method() == 'socket') {
2895 // send payload
2896 if (!fputs($this->fp, $this->outgoing_payload, strlen($this->outgoing_payload))) {
2897 $this->setError('couldn\'t write message data to socket');
2898 $this->debug('couldn\'t write message data to socket');
2899 return false;
2900 }
2901 $this->debug('wrote data to socket, length = ' . strlen($this->outgoing_payload));
2902 return true;
2903 } elseif ($this->io_method() == 'curl') {
2904 // set payload
2905 // cURL does say this should only be the verb, and in fact it
2906 // turns out that the URI and HTTP version are appended to this, which
2907 // some servers refuse to work with (so we no longer use this method!)
2908 //$this->setCurlOption(CURLOPT_CUSTOMREQUEST, $this->outgoing_payload);
2909 $curl_headers = array();
2910 foreach ($this->outgoing_headers as $k => $v) {
2911 if ($k == 'Connection' || $k == 'Content-Length' || $k == 'Host' || $k == 'Authorization' || $k == 'Proxy-Authorization') {
2912 $this->debug("Skip cURL header $k: $v");
2913 } else {
2914 $curl_headers[] = "$k: $v";
2915 }
2916 }
2917 if ($cookie_str != '') {
2918 $curl_headers[] = 'Cookie: ' . $cookie_str;
2919 }
2920 $this->setCurlOption(CURLOPT_HTTPHEADER, $curl_headers);
2921 $this->debug('set cURL HTTP headers');
2922 if ($this->request_method == "POST") {
2923 $this->setCurlOption(CURLOPT_POST, 1);
2924 $this->setCurlOption(CURLOPT_POSTFIELDS, $data);
2925 $this->debug('set cURL POST data');
2926 } else {
2927 }
2928 // insert custom user-set cURL options
2929 foreach ($this->ch_options as $key => $val) {
2930 $this->setCurlOption($key, $val);
2931 }
2932
2933 $this->debug('set cURL payload');
2934 return true;
2935 }
2936 }
2937
2944 public function getResponse()
2945 {
2946 $this->incoming_payload = '';
2947
2948 if ($this->io_method() == 'socket') {
2949 // loop until headers have been retrieved
2950 $data = '';
2951 while (!isset($lb)) {
2952 // We might EOF during header read.
2953 if (feof($this->fp)) {
2954 $this->incoming_payload = $data;
2955 $this->debug('found no headers before EOF after length ' . strlen($data));
2956 $this->debug("received before EOF:\n" . $data);
2957 $this->setError('server failed to send headers');
2958 return false;
2959 }
2960
2961 $tmp = fgets($this->fp, 256);
2962 $tmplen = strlen($tmp);
2963 $this->debug("read line of $tmplen bytes: " . trim($tmp));
2964
2965 if ($tmplen == 0) {
2966 $this->incoming_payload = $data;
2967 $this->debug('socket read of headers timed out after length ' . strlen($data));
2968 $this->debug("read before timeout: " . $data);
2969 $this->setError('socket read of headers timed out');
2970 return false;
2971 }
2972
2973 $data .= $tmp;
2974 $pos = strpos($data, "\r\n\r\n");
2975 if ($pos > 1) {
2976 $lb = "\r\n";
2977 } else {
2978 $pos = strpos($data, "\n\n");
2979 if ($pos > 1) {
2980 $lb = "\n";
2981 }
2982 }
2983 // remove 100 headers
2984 if (isset($lb) && preg_match('/^HTTP\/1.1 100/', $data)) {
2985 unset($lb);
2986 $data = '';
2987 }//
2988 }
2989 // store header data
2990 $this->incoming_payload .= $data;
2991 $this->debug('found end of headers after length ' . strlen($data));
2992 // process headers
2993 $header_data = trim(substr($data, 0, $pos));
2994 $header_array = explode($lb, $header_data);
2995 $this->incoming_headers = array();
2996 $this->incoming_cookies = array();
2997 foreach ($header_array as $header_line) {
2998 $arr = explode(':', $header_line, 2);
2999 if (count($arr) > 1) {
3000 $header_name = strtolower(trim($arr[0]));
3001 $this->incoming_headers[$header_name] = trim($arr[1]);
3002 if ($header_name == 'set-cookie') {
3003 // TODO: allow multiple cookies from parseCookie
3004 $cookie = $this->parseCookie(trim($arr[1]));
3005 if ($cookie) {
3006 $this->incoming_cookies[] = $cookie;
3007 $this->debug('found cookie: ' . $cookie['name'] . ' = ' . $cookie['value']);
3008 } else {
3009 $this->debug('did not find cookie in ' . trim($arr[1]));
3010 }
3011 }
3012 } elseif (isset($header_name)) {
3013 // append continuation line to previous header
3014 $this->incoming_headers[$header_name] .= $lb . ' ' . $header_line;
3015 }
3016 }
3017
3018 // loop until msg has been received
3019 if (isset($this->incoming_headers['transfer-encoding']) && strtolower($this->incoming_headers['transfer-encoding']) == 'chunked') {
3020 $content_length = 2147483647; // ignore any content-length header
3021 $chunked = true;
3022 $this->debug("want to read chunked content");
3023 } elseif (isset($this->incoming_headers['content-length'])) {
3024 $content_length = $this->incoming_headers['content-length'];
3025 $chunked = false;
3026 $this->debug("want to read content of length $content_length");
3027 } else {
3028 $content_length = 2147483647;
3029 $chunked = false;
3030 $this->debug("want to read content to EOF");
3031 }
3032 $data = '';
3033 do {
3034 if ($chunked) {
3035 $tmp = fgets($this->fp, 256);
3036 $tmplen = strlen($tmp);
3037 $this->debug("read chunk line of $tmplen bytes");
3038 if ($tmplen == 0) {
3039 $this->incoming_payload = $data;
3040 $this->debug('socket read of chunk length timed out after length ' . strlen($data));
3041 $this->debug("read before timeout:\n" . $data);
3042 $this->setError('socket read of chunk length timed out');
3043 return false;
3044 }
3045 $content_length = hexdec(trim($tmp));
3046 $this->debug("chunk length $content_length");
3047 }
3048 $strlen = 0;
3049 while (($strlen < $content_length) && (!feof($this->fp))) {
3050 $readlen = min(8192, $content_length - $strlen);
3051 $tmp = fread($this->fp, $readlen);
3052 $tmplen = strlen($tmp);
3053 $this->debug("read buffer of $tmplen bytes");
3054 if (($tmplen == 0) && (!feof($this->fp))) {
3055 $this->incoming_payload = $data;
3056 $this->debug('socket read of body timed out after length ' . strlen($data));
3057 $this->debug("read before timeout:\n" . $data);
3058 $this->setError('socket read of body timed out');
3059 return false;
3060 }
3061 $strlen += $tmplen;
3062 $data .= $tmp;
3063 }
3064 if ($chunked && ($content_length > 0)) {
3065 $tmp = fgets($this->fp, 256);
3066 $tmplen = strlen($tmp);
3067 $this->debug("read chunk terminator of $tmplen bytes");
3068 if ($tmplen == 0) {
3069 $this->incoming_payload = $data;
3070 $this->debug('socket read of chunk terminator timed out after length ' . strlen($data));
3071 $this->debug("read before timeout:\n" . $data);
3072 $this->setError('socket read of chunk terminator timed out');
3073 return false;
3074 }
3075 }
3076 } while ($chunked && ($content_length > 0) && (!feof($this->fp)));
3077 if (feof($this->fp)) {
3078 $this->debug('read to EOF');
3079 }
3080 $this->debug('read body of length ' . strlen($data));
3081 $this->incoming_payload .= $data;
3082 $this->debug('received a total of ' . strlen($this->incoming_payload) . ' bytes of data from server');
3083
3084 // close filepointer
3085 if (
3086 (isset($this->incoming_headers['connection']) && strtolower($this->incoming_headers['connection']) == 'close') ||
3087 (! $this->persistentConnection) || feof($this->fp)) {
3088 fclose($this->fp);
3089 $this->fp = false;
3090 $this->debug('closed socket');
3091 }
3092
3093 // connection was closed unexpectedly
3094 if ($this->incoming_payload == '') {
3095 $this->setError('no response from server');
3096 return false;
3097 }
3098
3099 // decode transfer-encoding
3100 // if(isset($this->incoming_headers['transfer-encoding']) && strtolower($this->incoming_headers['transfer-encoding']) == 'chunked'){
3101 // if(!$data = $this->decodeChunked($data, $lb)){
3102 // $this->setError('Decoding of chunked data failed');
3103 // return false;
3104 // }
3105 //print "<pre>\nde-chunked:\n---------------\n$data\n\n---------------\n</pre>";
3106 // set decoded payload
3107 // $this->incoming_payload = $header_data.$lb.$lb.$data;
3108 // }
3109 } elseif ($this->io_method() == 'curl') {
3110 // send and receive
3111 $this->debug('send and receive with cURL');
3112 $this->incoming_payload = curl_exec($this->ch);
3114
3115 $cErr = curl_error($this->ch);
3116 if ($cErr != '') {
3117 $err = 'cURL ERROR: ' . curl_errno($this->ch) . ': ' . $cErr . '<br>';
3118 // TODO: there is a PHP bug that can cause this to SEGV for CURLINFO_CONTENT_TYPE
3119 foreach (curl_getinfo($this->ch) as $k => $v) {
3120 $err .= "$k: $v<br>";
3121 }
3122 $this->debug($err);
3123 $this->setError($err);
3124 $this->ch = null;
3125 return false;
3126 } else {
3127 //echo '<pre>';
3128 //var_dump(curl_getinfo($this->ch));
3129 //echo '</pre>';
3130 }
3131 // close curl
3132 $this->debug('No cURL error, closing cURL');
3133 $this->ch = null;
3134
3135 // try removing skippable headers
3136 $savedata = $data;
3137 while ($this->isSkippableCurlHeader($data)) {
3138 $this->debug("Found HTTP header to skip");
3139 if ($pos = strpos($data, "\r\n\r\n")) {
3140 $data = ltrim(substr($data, $pos));
3141 } elseif ($pos = strpos($data, "\n\n")) {
3142 $data = ltrim(substr($data, $pos));
3143 }
3144 }
3145
3146 if ($data == '') {
3147 // have nothing left; just remove 100 header(s)
3148 $data = $savedata;
3149 while (preg_match('/^HTTP\/1.1 100/', $data)) {
3150 if ($pos = strpos($data, "\r\n\r\n")) {
3151 $data = ltrim(substr($data, $pos));
3152 } elseif ($pos = strpos($data, "\n\n")) {
3153 $data = ltrim(substr($data, $pos));
3154 }
3155 }
3156 }
3157
3158 // separate content from HTTP headers
3159 if ($pos = strpos($data, "\r\n\r\n")) {
3160 $lb = "\r\n";
3161 } elseif ($pos = strpos($data, "\n\n")) {
3162 $lb = "\n";
3163 } else {
3164 $this->debug('no proper separation of headers and document');
3165 $this->setError('no proper separation of headers and document');
3166 return false;
3167 }
3168 $header_data = trim(substr($data, 0, $pos));
3169 $header_array = explode($lb, $header_data);
3170 $data = ltrim(substr($data, $pos));
3171 $this->debug('found proper separation of headers and document');
3172 $this->debug('cleaned data, stringlen: ' . strlen($data));
3173 // clean headers
3174 foreach ($header_array as $header_line) {
3175 $arr = explode(':', $header_line, 2);
3176 if (count($arr) > 1) {
3177 $header_name = strtolower(trim($arr[0]));
3178 $this->incoming_headers[$header_name] = trim($arr[1]);
3179 if ($header_name == 'set-cookie') {
3180 // TODO: allow multiple cookies from parseCookie
3181 $cookie = $this->parseCookie(trim($arr[1]));
3182 if ($cookie) {
3183 $this->incoming_cookies[] = $cookie;
3184 $this->debug('found cookie: ' . $cookie['name'] . ' = ' . $cookie['value']);
3185 } else {
3186 $this->debug('did not find cookie in ' . trim($arr[1]));
3187 }
3188 }
3189 } elseif (isset($header_name)) {
3190 // append continuation line to previous header
3191 $this->incoming_headers[$header_name] .= $lb . ' ' . $header_line;
3192 }
3193 }
3194 }
3195
3196 $this->response_status_line = $header_array[0];
3197 $arr = explode(' ', $this->response_status_line, 3);
3198 $http_version = $arr[0];
3199 $http_status = intval($arr[1]);
3200 $http_reason = count($arr) > 2 ? $arr[2] : '';
3201
3202 // see if we need to resend the request with http digest authentication
3203 if (isset($this->incoming_headers['location']) && ($http_status == 301 || $http_status == 302)) {
3204 $this->debug("Got $http_status $http_reason with Location: " . $this->incoming_headers['location']);
3205 $this->setURL($this->incoming_headers['location']);
3206 $this->tryagain = true;
3207 return false;
3208 }
3209
3210 // see if we need to resend the request with http digest authentication
3211 if (isset($this->incoming_headers['www-authenticate']) && $http_status == 401) {
3212 $this->debug("Got 401 $http_reason with WWW-Authenticate: " . $this->incoming_headers['www-authenticate']);
3213 if (strstr($this->incoming_headers['www-authenticate'], "Digest ")) {
3214 $this->debug('Server wants digest authentication');
3215 // remove "Digest " from our elements
3216 $digestString = str_replace('Digest ', '', $this->incoming_headers['www-authenticate']);
3217
3218 // parse elements into array
3219 $digestElements = explode(',', $digestString);
3220 foreach ($digestElements as $val) {
3221 $tempElement = explode('=', trim($val), 2);
3222 $digestRequest[$tempElement[0]] = str_replace("\"", '', $tempElement[1]);
3223 }
3224
3225 // should have (at least) qop, realm, nonce
3226 if (isset($digestRequest['nonce'])) {
3227 $this->setCredentials($this->username, $this->password, 'digest', $digestRequest);
3228 $this->tryagain = true;
3229 return false;
3230 }
3231 }
3232 $this->debug('HTTP authentication failed');
3233 $this->setError('HTTP authentication failed');
3234 return false;
3235 }
3236
3237 if (
3238 ($http_status >= 300 && $http_status <= 307) ||
3239 ($http_status >= 400 && $http_status <= 417) ||
3240 ($http_status >= 501 && $http_status <= 505)
3241 ) {
3242 $this->setError("Unsupported HTTP response status $http_status $http_reason (soapclient->response has contents of the response)");
3243 return false;
3244 }
3245
3246 // decode content-encoding
3247 if (isset($this->incoming_headers['content-encoding']) && $this->incoming_headers['content-encoding'] != '') {
3248 if (strtolower($this->incoming_headers['content-encoding']) == 'deflate' || strtolower($this->incoming_headers['content-encoding']) == 'gzip') {
3249 // if decoding works, use it. else assume data wasn't gzencoded
3250 if (function_exists('gzinflate')) {
3251 //$timer->setMarker('starting decoding of gzip/deflated content');
3252 // IIS 5 requires gzinflate instead of gzuncompress (similar to IE 5 and gzdeflate v. gzcompress)
3253 // this means there are no Zlib headers, although there should be
3254 $this->debug('The gzinflate function exists');
3255 $datalen = strlen($data);
3256 if ($this->incoming_headers['content-encoding'] == 'deflate') {
3257 if ($degzdata = @gzinflate($data)) {
3258 $data = $degzdata;
3259 $this->debug('The payload has been inflated to ' . strlen($data) . ' bytes');
3260 if (strlen($data) < $datalen) {
3261 // test for the case that the payload has been compressed twice
3262 $this->debug('The inflated payload is smaller than the gzipped one; try again');
3263 if ($degzdata = @gzinflate($data)) {
3264 $data = $degzdata;
3265 $this->debug('The payload has been inflated again to ' . strlen($data) . ' bytes');
3266 }
3267 }
3268 } else {
3269 $this->debug('Error using gzinflate to inflate the payload');
3270 $this->setError('Error using gzinflate to inflate the payload');
3271 }
3272 } elseif ($this->incoming_headers['content-encoding'] == 'gzip') {
3273 if ($degzdata = @gzinflate(substr($data, 10))) { // do our best
3274 $data = $degzdata;
3275 $this->debug('The payload has been un-gzipped to ' . strlen($data) . ' bytes');
3276 if (strlen($data) < $datalen) {
3277 // test for the case that the payload has been compressed twice
3278 $this->debug('The un-gzipped payload is smaller than the gzipped one; try again');
3279 if ($degzdata = @gzinflate(substr($data, 10))) {
3280 $data = $degzdata;
3281 $this->debug('The payload has been un-gzipped again to ' . strlen($data) . ' bytes');
3282 }
3283 }
3284 } else {
3285 $this->debug('Error using gzinflate to un-gzip the payload');
3286 $this->setError('Error using gzinflate to un-gzip the payload');
3287 }
3288 }
3289 //$timer->setMarker('finished decoding of gzip/deflated content');
3290 //print "<xmp>\nde-inflated:\n---------------\n$data\n-------------\n</xmp>";
3291 // set decoded payload
3292 $this->incoming_payload = $header_data . $lb . $lb . $data;
3293 } else {
3294 $this->debug('The server sent compressed data. Your php install must have the Zlib extension compiled in to support this.');
3295 $this->setError('The server sent compressed data. Your php install must have the Zlib extension compiled in to support this.');
3296 }
3297 } else {
3298 $this->debug('Unsupported Content-Encoding ' . $this->incoming_headers['content-encoding']);
3299 $this->setError('Unsupported Content-Encoding ' . $this->incoming_headers['content-encoding']);
3300 }
3301 } else {
3302 $this->debug('No Content-Encoding header');
3303 }
3304
3305 if (strlen($data) == 0) {
3306 $this->debug('no data after headers!');
3307 $this->setError('no data present after HTTP headers');
3308 return false;
3309 }
3310
3311 return $data;
3312 }
3313
3321 public function setContentType($type, $charset = false)
3322 {
3323 $this->setHeader('Content-Type', $type . ($charset ? '; charset=' . $charset : ''));
3324 }
3325
3332 public function usePersistentConnection()
3333 {
3334 if (isset($this->outgoing_headers['Accept-Encoding'])) {
3335 return false;
3336 }
3337 $this->protocol_version = '1.1';
3338 $this->persistentConnection = true;
3339 $this->setHeader('Connection', 'Keep-Alive');
3340 return true;
3341 }
3342
3350 /*
3351 * TODO: allow a Set-Cookie string to be parsed into multiple cookies
3352 */
3353 public function parseCookie($cookie_str)
3354 {
3355 $cookie_str = str_replace('; ', ';', $cookie_str) . ';';
3356 // begin-patch php8
3357 //$data = split(';', $cookie_str);
3358 $data = explode(';', $cookie_str);
3359 $value_str = $data[0];
3360
3361 $cookie_param = 'domain=';
3362 $start = strpos($cookie_str, $cookie_param);
3363 if ($start > 0) {
3364 $domain = substr($cookie_str, $start + strlen($cookie_param));
3365 $domain = substr($domain, 0, strpos($domain, ';'));
3366 } else {
3367 $domain = '';
3368 }
3369
3370 $cookie_param = 'expires=';
3371 $start = strpos($cookie_str, $cookie_param);
3372 if ($start > 0) {
3373 $expires = substr($cookie_str, $start + strlen($cookie_param));
3374 $expires = substr($expires, 0, strpos($expires, ';'));
3375 } else {
3376 $expires = '';
3377 }
3378
3379 $cookie_param = 'path=';
3380 $start = strpos($cookie_str, $cookie_param);
3381 if ($start > 0) {
3382 $path = substr($cookie_str, $start + strlen($cookie_param));
3383 $path = substr($path, 0, strpos($path, ';'));
3384 } else {
3385 $path = '/';
3386 }
3387
3388 $cookie_param = ';secure;';
3389 if (strpos($cookie_str, $cookie_param) !== false) {
3390 $secure = true;
3391 } else {
3392 $secure = false;
3393 }
3394
3395 $sep_pos = strpos($value_str, '=');
3396
3397 if ($sep_pos) {
3398 $name = substr($value_str, 0, $sep_pos);
3399 $value = substr($value_str, $sep_pos + 1);
3400 $cookie = array( 'name' => $name,
3401 'value' => $value,
3402 'domain' => $domain,
3403 'path' => $path,
3404 'expires' => $expires,
3405 'secure' => $secure
3406 );
3407 return $cookie;
3408 }
3409 return false;
3410 }
3411
3420 public function getCookiesForRequest($cookies, $secure = false)
3421 {
3422 $cookie_str = '';
3423 if ((! is_null($cookies)) && (is_array($cookies))) {
3424 foreach ($cookies as $cookie) {
3425 if (! is_array($cookie)) {
3426 continue;
3427 }
3428 $this->debug("check cookie for validity: " . $cookie['name'] . '=' . $cookie['value']);
3429 if ((isset($cookie['expires'])) && (! empty($cookie['expires']))) {
3430 if (strtotime($cookie['expires']) <= time()) {
3431 $this->debug('cookie has expired');
3432 continue;
3433 }
3434 }
3435 if ((isset($cookie['domain'])) && (! empty($cookie['domain']))) {
3436 $domain = preg_quote($cookie['domain']);
3437 if (! preg_match("'.*$domain$'i", $this->host)) {
3438 $this->debug('cookie has different domain');
3439 continue;
3440 }
3441 }
3442 if ((isset($cookie['path'])) && (! empty($cookie['path']))) {
3443 $path = preg_quote($cookie['path']);
3444 if (! preg_match("'^$path.*'i", $this->path)) {
3445 $this->debug('cookie is for a different path');
3446 continue;
3447 }
3448 }
3449 if ((! $secure) && (isset($cookie['secure'])) && ($cookie['secure'])) {
3450 $this->debug('cookie is secure, transport is not');
3451 continue;
3452 }
3453 $cookie_str .= $cookie['name'] . '=' . $cookie['value'] . '; ';
3454 $this->debug('add cookie to Cookie-String: ' . $cookie['name'] . '=' . $cookie['value']);
3455 }
3456 }
3457 return $cookie_str;
3458 }
3459}
3460
3461?><?php
3462
3463
3464
3476{
3477 public $opData;
3483 public $headers = array();
3489 public $request = '';
3495 public $requestHeaders = '';
3501 public $requestHeader = null;
3507 public $document = '';
3513 public $requestSOAP = '';
3519 public $methodURI = '';
3525 public $methodname = '';
3531 public $methodparams = array();
3537 public $SOAPAction = '';
3543 public $xml_encoding = '';
3549 public $decode_utf8 = true;
3550 public $class;
3551
3557 public $outgoing_headers = array();
3563 public $response = '';
3569 public $responseHeaders = '';
3575 public $responseSOAP = '';
3581 public $methodreturn = false;
3593 public $fault = false;
3599 public $result = 'successful';
3600
3607 public $operations = array();
3613 public $wsdl = false;
3619 public $externalWSDLURL = false;
3625 public $debug_flag = false;
3626
3627
3635 public function __construct($wsdl = false)
3636 {
3638 // turn on debugging?
3639 global $debug;
3640 global $HTTP_SERVER_VARS;
3641
3642 if (isset($_SERVER)) {
3643 $this->debug("_SERVER is defined:");
3644 $this->appendDebug($this->varDump($_SERVER));
3645 } elseif (isset($HTTP_SERVER_VARS)) {
3646 $this->debug("HTTP_SERVER_VARS is defined:");
3647 $this->appendDebug($this->varDump($HTTP_SERVER_VARS));
3648 } else {
3649 $this->debug("Neither _SERVER nor HTTP_SERVER_VARS is defined.");
3650 }
3651
3652 if (isset($debug)) {
3653 $this->debug("In nusoap_server, set debug_flag=$debug based on global flag");
3654 $this->debug_flag = $debug;
3655 } elseif (isset($_SERVER['QUERY_STRING'])) {
3656 $qs = explode('&', $_SERVER['QUERY_STRING']);
3657 foreach ($qs as $v) {
3658 if (substr($v, 0, 6) == 'debug=') {
3659 $this->debug("In nusoap_server, set debug_flag=" . substr($v, 6) . " based on query string #1");
3660 $this->debug_flag = substr($v, 6);
3661 }
3662 }
3663 } elseif (isset($HTTP_SERVER_VARS['QUERY_STRING'])) {
3664 $qs = explode('&', $HTTP_SERVER_VARS['QUERY_STRING']);
3665 foreach ($qs as $v) {
3666 if (substr($v, 0, 6) == 'debug=') {
3667 $this->debug("In nusoap_server, set debug_flag=" . substr($v, 6) . " based on query string #2");
3668 $this->debug_flag = substr($v, 6);
3669 }
3670 }
3671 }
3672
3673 // wsdl
3674 if ($wsdl) {
3675 $this->debug("In nusoap_server, WSDL is specified");
3676 if (is_object($wsdl) && (get_class($wsdl) == 'wsdl')) {
3677 $this->wsdl = $wsdl;
3678 $this->externalWSDLURL = $this->wsdl->wsdl;
3679 $this->debug('Use existing wsdl instance from ' . $this->externalWSDLURL);
3680 } else {
3681 $this->debug('Create wsdl from ' . $wsdl);
3682 $this->wsdl = new wsdl($wsdl);
3683 $this->externalWSDLURL = $wsdl;
3684 }
3685 $this->appendDebug($this->wsdl->getDebug());
3686 $this->wsdl->clearDebug();
3687 if ($err = $this->wsdl->getError()) {
3688 die('WSDL ERROR: ' . $err);
3689 }
3690 }
3691 }
3692
3699 public function service($data)
3700 {
3701 global $HTTP_SERVER_VARS;
3702
3703 if (isset($_SERVER['QUERY_STRING'])) {
3704 $qs = $_SERVER['QUERY_STRING'];
3705 } elseif (isset($HTTP_SERVER_VARS['QUERY_STRING'])) {
3706 $qs = $HTTP_SERVER_VARS['QUERY_STRING'];
3707 } else {
3708 $qs = '';
3709 }
3710 $this->debug("In service, query string=$qs");
3711
3712 if (preg_match('/wsdl/', $qs)) {
3713 $this->debug("In service, this is a request for WSDL");
3714 if ($this->externalWSDLURL) {
3715 if (strpos($this->externalWSDLURL, "://") !== false) { // assume URL
3716 header('Location: ' . $this->externalWSDLURL);
3717 } else { // assume file
3718 header("Content-Type: text/xml\r\n");
3719 $fp = fopen($this->externalWSDLURL, 'r');
3720 fpassthru($fp);
3721 }
3722 } elseif ($this->wsdl) {
3723 header("Content-Type: text/xml; charset=ISO-8859-1\r\n");
3724 print $this->wsdl->serialize($this->debug_flag);
3725 if ($this->debug_flag) {
3726 $this->debug('wsdl:');
3727 $this->appendDebug($this->varDump($this->wsdl));
3728 print $this->getDebugAsXMLComment();
3729 }
3730 } else {
3731 header("Content-Type: text/html; charset=ISO-8859-1\r\n");
3732 print "This service does not provide WSDL";
3733 }
3734 } elseif ($data == '' && $this->wsdl) {
3735 $this->debug("In service, there is no data, so return Web description");
3736 print $this->wsdl->webDescription();
3737 } else {
3738 $this->debug("In service, invoke the request");
3739 $this->parse_request($data);
3740 if (! $this->fault) {
3741 $this->invoke_method();
3742 }
3743 if (! $this->fault) {
3744 $this->serialize_return();
3745 }
3746 $this->send_response();
3747 }
3748 }
3749
3762 public function parse_http_headers()
3763 {
3764 global $HTTP_SERVER_VARS;
3765
3766 $this->request = '';
3767 $this->SOAPAction = '';
3768 if (function_exists('getallheaders')) {
3769 $this->debug("In parse_http_headers, use getallheaders");
3770 $headers = getallheaders();
3771 foreach ($headers as $k => $v) {
3772 $k = strtolower($k);
3773 $this->headers[$k] = $v;
3774 $this->request .= "$k: $v\r\n";
3775 $this->debug("$k: $v");
3776 }
3777 // get SOAPAction header
3778 if (isset($this->headers['soapaction'])) {
3779 $this->SOAPAction = str_replace('"', '', $this->headers['soapaction']);
3780 }
3781 // get the character encoding of the incoming request
3782 if (isset($this->headers['content-type']) && strpos($this->headers['content-type'], '=')) {
3783 $enc = str_replace('"', '', substr(strstr($this->headers["content-type"], '='), 1));
3784 if (preg_match('/^(ISO-8859-1|US-ASCII|UTF-8)$/i', $enc)) {
3785 $this->xml_encoding = strtoupper($enc);
3786 } else {
3787 $this->xml_encoding = 'US-ASCII';
3788 }
3789 } else {
3790 // should be US-ASCII for HTTP 1.0 or ISO-8859-1 for HTTP 1.1
3791 $this->xml_encoding = 'ISO-8859-1';
3792 }
3793 } elseif (isset($_SERVER) && is_array($_SERVER)) {
3794 $this->debug("In parse_http_headers, use _SERVER");
3795 foreach ($_SERVER as $k => $v) {
3796 if (substr($k, 0, 5) == 'HTTP_') {
3797 $k = str_replace(' ', '-', strtolower(str_replace('_', ' ', substr($k, 5))));
3798 } else {
3799 $k = str_replace(' ', '-', strtolower(str_replace('_', ' ', $k)));
3800 }
3801 if ($k == 'soapaction') {
3802 // get SOAPAction header
3803 $k = 'SOAPAction';
3804 $v = str_replace('"', '', $v);
3805 $v = str_replace('\\', '', $v);
3806 $this->SOAPAction = $v;
3807 } elseif ($k == 'content-type') {
3808 // get the character encoding of the incoming request
3809 if (strpos($v, '=')) {
3810 $enc = substr(strstr($v, '='), 1);
3811 $enc = str_replace('"', '', $enc);
3812 $enc = str_replace('\\', '', $enc);
3813 if (preg_match('/^(ISO-8859-1|US-ASCII|UTF-8)$/i', $enc)) {
3814 $this->xml_encoding = strtoupper($enc);
3815 } else {
3816 $this->xml_encoding = 'US-ASCII';
3817 }
3818 } else {
3819 // should be US-ASCII for HTTP 1.0 or ISO-8859-1 for HTTP 1.1
3820 $this->xml_encoding = 'ISO-8859-1';
3821 }
3822 }
3823 $this->headers[$k] = $v;
3824 $this->request .= "$k: $v\r\n";
3825 $this->debug("$k: $v");
3826 }
3827 } elseif (is_array($HTTP_SERVER_VARS)) {
3828 $this->debug("In parse_http_headers, use HTTP_SERVER_VARS");
3829 foreach ($HTTP_SERVER_VARS as $k => $v) {
3830 if (substr($k, 0, 5) == 'HTTP_') {
3831 $k = str_replace(' ', '-', strtolower(str_replace('_', ' ', substr($k, 5))));
3832 $k = strtolower(substr($k, 5));
3833 } else {
3834 $k = str_replace(' ', '-', strtolower(str_replace('_', ' ', $k)));
3835 $k = strtolower($k);
3836 }
3837 if ($k == 'soapaction') {
3838 // get SOAPAction header
3839 $k = 'SOAPAction';
3840 $v = str_replace('"', '', $v);
3841 $v = str_replace('\\', '', $v);
3842 $this->SOAPAction = $v;
3843 } elseif ($k == 'content-type') {
3844 // get the character encoding of the incoming request
3845 if (strpos($v, '=')) {
3846 $enc = substr(strstr($v, '='), 1);
3847 $enc = str_replace('"', '', $enc);
3848 $enc = str_replace('\\', '', $enc);
3849 if (preg_match('/^(ISO-8859-1|US-ASCII|UTF-8)$/i', $enc)) {
3850 $this->xml_encoding = strtoupper($enc);
3851 } else {
3852 $this->xml_encoding = 'US-ASCII';
3853 }
3854 } else {
3855 // should be US-ASCII for HTTP 1.0 or ISO-8859-1 for HTTP 1.1
3856 $this->xml_encoding = 'ISO-8859-1';
3857 }
3858 }
3859 $this->headers[$k] = $v;
3860 $this->request .= "$k: $v\r\n";
3861 $this->debug("$k: $v");
3862 }
3863 } else {
3864 $this->debug("In parse_http_headers, HTTP headers not accessible");
3865 $this->setError("HTTP headers not accessible");
3866 }
3867 }
3868
3891 public function parse_request($data = '')
3892 {
3893 $this->debug('entering parse_request()');
3894 $this->parse_http_headers();
3895 $this->debug('got character encoding: ' . $this->xml_encoding);
3896 // uncompress if necessary
3897 if (isset($this->headers['content-encoding']) && $this->headers['content-encoding'] != '') {
3898 $this->debug('got content encoding: ' . $this->headers['content-encoding']);
3899 if ($this->headers['content-encoding'] == 'deflate' || $this->headers['content-encoding'] == 'gzip') {
3900 // if decoding works, use it. else assume data wasn't gzencoded
3901 if (function_exists('gzuncompress')) {
3902 if ($this->headers['content-encoding'] == 'deflate' && $degzdata = @gzuncompress($data)) {
3903 $data = $degzdata;
3904 } elseif ($this->headers['content-encoding'] == 'gzip' && $degzdata = gzinflate(substr($data, 10))) {
3905 $data = $degzdata;
3906 } else {
3907 $this->fault('SOAP-ENV:Client', 'Errors occurred when trying to decode the data');
3908 return;
3909 }
3910 } else {
3911 $this->fault('SOAP-ENV:Client', 'This Server does not support compressed data');
3912 return;
3913 }
3914 }
3915 }
3916 $this->request .= "\r\n" . $data;
3917 $data = $this->parseRequest($this->headers, $data);
3918 $this->requestSOAP = $data;
3919 $this->debug('leaving parse_request');
3920 }
3921
3939 public function invoke_method()
3940 {
3941 $this->debug('in invoke_method, methodname=' . $this->methodname . ' methodURI=' . $this->methodURI . ' SOAPAction=' . $this->SOAPAction);
3942
3943 if ($this->wsdl) {
3944 if ($this->opData = $this->wsdl->getOperationData($this->methodname)) {
3945 $this->debug('in invoke_method, found WSDL operation=' . $this->methodname);
3946 $this->appendDebug('opData=' . $this->varDump($this->opData));
3947 } elseif ($this->opData = $this->wsdl->getOperationDataForSoapAction($this->SOAPAction)) {
3948 // Note: hopefully this case will only be used for doc/lit, since rpc services should have wrapper element
3949 $this->debug('in invoke_method, found WSDL soapAction=' . $this->SOAPAction . ' for operation=' . $this->opData['name']);
3950 $this->appendDebug('opData=' . $this->varDump($this->opData));
3951 $this->methodname = $this->opData['name'];
3952 } else {
3953 $this->debug('in invoke_method, no WSDL for operation=' . $this->methodname);
3954 $this->fault('SOAP-ENV:Client', "Operation '" . $this->methodname . "' is not defined in the WSDL for this service");
3955 return;
3956 }
3957 } else {
3958 $this->debug('in invoke_method, no WSDL to validate method');
3959 }
3960
3961 // if a . is present in $this->methodname, we see if there is a class in scope,
3962 // which could be referred to. We will also distinguish between two deliminators,
3963 // to allow methods to be called a the class or an instance
3964 $class = '';
3965 $method = '';
3966 if (strpos($this->methodname, '..') > 0) {
3967 $delim = '..';
3968 } elseif (strpos($this->methodname, '.') > 0) {
3969 $delim = '.';
3970 } else {
3971 $delim = '';
3972 }
3973
3974 if (strlen($delim) > 0 && substr_count($this->methodname, $delim) == 1 &&
3975 class_exists(substr($this->methodname, 0, strpos($this->methodname, $delim)))) {
3976 // get the class and method name
3977 $class = substr($this->methodname, 0, strpos($this->methodname, $delim));
3978 $method = substr($this->methodname, strpos($this->methodname, $delim) + strlen($delim));
3979 $this->debug("in invoke_method, class=$class method=$method delim=$delim");
3980 }
3981 // set class handler
3982 // added to support single operations
3983 if ($class == '' && $this->class != '') {
3985 $delim = "..";
3986 $method = $this->methodname;
3987 }
3988
3989 // does method exist?
3990 if ($class == '') {
3991 if (!function_exists($this->methodname)) {
3992 $this->debug("in invoke_method, function '$this->methodname' not found!");
3993 $this->result = 'fault: method not found';
3994 $this->fault('SOAP-ENV:Client', "method '$this->methodname' not defined in service");
3995 return;
3996 }
3997 } else {
3998 $method_to_compare = (substr(phpversion(), 0, 2) == '4.') ? strtolower($method) : $method;
3999 if (!in_array($method_to_compare, get_class_methods($class))) {
4000 $this->debug("in invoke_method, method '$this->methodname' not found in class '$class'!");
4001 $this->result = 'fault: method not found';
4002 $this->fault('SOAP-ENV:Client', "method '$this->methodname' not defined in service");
4003 return;
4004 }
4005 }
4006
4007 // evaluate message, getting back parameters
4008 // verify that request parameters match the method's signature
4009 if (! $this->verify_method($this->methodname, $this->methodparams)) {
4010 // debug
4011 $this->debug('ERROR: request not verified against method signature');
4012 $this->result = 'fault: request failed validation against method signature';
4013 // return fault
4014 $this->fault('SOAP-ENV:Client', "Operation '$this->methodname' not defined in service.");
4015 return;
4016 }
4017
4018 // if there are parameters to pass
4019 $this->debug('in invoke_method, params:');
4020 $this->appendDebug($this->varDump($this->methodparams));
4021 $this->debug("in invoke_method, calling '$this->methodname'");
4022 if (!function_exists('call_user_func_array')) {
4023 if ($class == '') {
4024 $this->debug('in invoke_method, calling function using eval()');
4025 $funcCall = "\$this->methodreturn = $this->methodname(";
4026 } else {
4027 if ($delim == '..') {
4028 $this->debug('in invoke_method, calling class method using eval()');
4029 $funcCall = "\$this->methodreturn = " . $class . "::" . $method . "(";
4030 } else {
4031 $this->debug('in invoke_method, calling instance method using eval()');
4032 // generate unique instance name
4033 $instname = "\$inst_" . time();
4034 $funcCall = $instname . " = new " . $class . "(); ";
4035 $funcCall .= "\$this->methodreturn = " . $instname . "->" . $method . "(";
4036 }
4037 }
4038 if ($this->methodparams) {
4039 foreach ($this->methodparams as $param) {
4040 if (is_array($param) || is_object($param)) {
4041 $this->fault('SOAP-ENV:Client', 'NuSOAP does not handle complexType parameters correctly when using eval; call_user_func_array must be available');
4042 return;
4043 }
4044 $funcCall .= "\"$param\",";
4045 }
4046 $funcCall = substr($funcCall, 0, -1);
4047 }
4048 $funcCall .= ');';
4049 $this->debug('in invoke_method, function call: ' . $funcCall);
4050 @eval($funcCall);
4051 } else {
4052 if ($class == '') {
4053 $this->debug('in invoke_method, calling function using call_user_func_array()');
4054 $call_arg = "$this->methodname"; // straight assignment changes $this->methodname to lower case after call_user_func_array()
4055 } elseif ($delim == '..') {
4056 $this->debug('in invoke_method, calling class method using call_user_func_array()');
4057 $call_arg = array($class, $method);
4058 } else {
4059 $this->debug('in invoke_method, calling instance method using call_user_func_array()');
4060 $instance = new $class();
4061 $call_arg = array(&$instance, $method);
4062 }
4063 if (is_array($this->methodparams)) {
4064 $this->methodreturn = call_user_func_array($call_arg, array_values($this->methodparams));
4065 } else {
4066 $this->methodreturn = call_user_func_array($call_arg, array());
4067 }
4068 }
4069 $this->debug('in invoke_method, methodreturn:');
4070 $this->appendDebug($this->varDump($this->methodreturn));
4071 $this->debug("in invoke_method, called method $this->methodname, received data of type " . gettype($this->methodreturn));
4072 }
4073
4085 public function serialize_return()
4086 {
4087 $this->debug('Entering serialize_return methodname: ' . $this->methodname . ' methodURI: ' . $this->methodURI);
4088 // if fault
4089 if (isset($this->methodreturn) && ((get_class((object) $this->methodreturn) == 'soap_fault') || (get_class((object) $this->methodreturn) == 'nusoap_fault'))) {
4090 $this->debug('got a fault object from method');
4091 $this->fault = $this->methodreturn;
4092 return;
4093 } elseif ($this->methodreturnisliteralxml) {
4094 $return_val = $this->methodreturn;
4095 // returned value(s)
4096 } else {
4097 $this->debug('got a(n) ' . gettype($this->methodreturn) . ' from method');
4098 $this->debug('serializing return value');
4099 if ($this->wsdl) {
4100 if (sizeof($this->opData['output']['parts']) > 1) {
4101 $this->debug('more than one output part, so use the method return unchanged');
4102 $opParams = $this->methodreturn;
4103 } elseif (sizeof($this->opData['output']['parts']) == 1) {
4104 $this->debug('exactly one output part, so wrap the method return in a simple array');
4105 // TODO: verify that it is not already wrapped!
4106 //foreach ($this->opData['output']['parts'] as $name => $type) {
4107 // $this->debug('wrap in element named ' . $name);
4108 //}
4109 $opParams = array($this->methodreturn);
4110 }
4111 $return_val = $this->wsdl->serializeRPCParameters($this->methodname, 'output', $opParams);
4112 $this->appendDebug($this->wsdl->getDebug());
4113 $this->wsdl->clearDebug();
4114 if ($errstr = $this->wsdl->getError()) {
4115 $this->debug('got wsdl error: ' . $errstr);
4116 $this->fault('SOAP-ENV:Server', 'unable to serialize result');
4117 return;
4118 }
4119 } else {
4120 if (isset($this->methodreturn)) {
4121 $return_val = $this->serialize_val($this->methodreturn, 'return');
4122 } else {
4123 $return_val = '';
4124 $this->debug('in absence of WSDL, assume void return for backward compatibility');
4125 }
4126 }
4127 }
4128 $this->debug('return value:');
4129 $this->appendDebug($this->varDump($return_val));
4130
4131 $this->debug('serializing response');
4132 if ($this->wsdl) {
4133 $this->debug('have WSDL for serialization: style is ' . $this->opData['style']);
4134 if ($this->opData['style'] == 'rpc') {
4135 $this->debug('style is rpc for serialization: use is ' . $this->opData['output']['use']);
4136 if ($this->opData['output']['use'] == 'literal') {
4137 // http://www.ws-i.org/Profiles/BasicProfile-1.1-2004-08-24.html R2735 says rpc/literal accessor elements should not be in a namespace
4138 $payload = '<ns1:' . $this->methodname . 'Response xmlns:ns1="' . $this->methodURI . '">' . $return_val . '</ns1:' . $this->methodname . "Response>";
4139 } else {
4140 $payload = '<ns1:' . $this->methodname . 'Response xmlns:ns1="' . $this->methodURI . '">' . $return_val . '</ns1:' . $this->methodname . "Response>";
4141 }
4142 } else {
4143 $this->debug('style is not rpc for serialization: assume document');
4144 $payload = $return_val;
4145 }
4146 } else {
4147 $this->debug('do not have WSDL for serialization: assume rpc/encoded');
4148 $payload = '<ns1:' . $this->methodname . 'Response xmlns:ns1="' . $this->methodURI . '">' . $return_val . '</ns1:' . $this->methodname . "Response>";
4149 }
4150 $this->result = 'successful';
4151 if ($this->wsdl) {
4152 //if($this->debug_flag){
4153 $this->appendDebug($this->wsdl->getDebug());
4154 // }
4155 if (isset($opData['output']['encodingStyle'])) {
4156 $encodingStyle = $opData['output']['encodingStyle'];
4157 } else {
4158 $encodingStyle = '';
4159 }
4160 // Added: In case we use a WSDL, return a serialized env. WITH the usedNamespaces.
4161 $this->responseSOAP = $this->serializeEnvelope($payload, $this->responseHeaders, $this->wsdl->usedNamespaces, $this->opData['style'], $this->opData['output']['use'], $encodingStyle);
4162 } else {
4163 $this->responseSOAP = $this->serializeEnvelope($payload, $this->responseHeaders);
4164 }
4165 $this->debug("Leaving serialize_return");
4166 }
4167
4178 public function send_response()
4179 {
4180 $this->debug('Enter send_response');
4181 if ($this->fault) {
4182 $payload = $this->fault->serialize();
4183 $this->outgoing_headers[] = "HTTP/1.0 500 Internal Server Error";
4184 $this->outgoing_headers[] = "Status: 500 Internal Server Error";
4185 } else {
4187 // Some combinations of PHP+Web server allow the Status
4188 // to come through as a header. Since OK is the default
4189 // just do nothing.
4190 // $this->outgoing_headers[] = "HTTP/1.0 200 OK";
4191 // $this->outgoing_headers[] = "Status: 200 OK";
4192 }
4193 // add debug data if in debug mode
4194 if (isset($this->debug_flag) && $this->debug_flag) {
4195 $payload .= $this->getDebugAsXMLComment();
4196 }
4197 $this->outgoing_headers[] = "Server: $this->title Server v$this->version";
4198 preg_match('/\$Revisio' . 'n: ([^ ]+)/', $this->revision, $rev);
4199 $this->outgoing_headers[] = "X-SOAP-Server: $this->title/$this->version (" . $rev[1] . ")";
4200 // Let the Web server decide about this
4201 //$this->outgoing_headers[] = "Connection: Close\r\n";
4202 $payload = $this->getHTTPBody($payload);
4203 $type = $this->getHTTPContentType();
4204 $charset = $this->getHTTPContentTypeCharset();
4205 $this->outgoing_headers[] = "Content-Type: $type" . ($charset ? '; charset=' . $charset : '');
4206 //begin code to compress payload - by John
4207 // NOTE: there is no way to know whether the Web server will also compress
4208 // this data.
4209 if (strlen($payload) > 1024 && isset($this->headers) && isset($this->headers['accept-encoding'])) {
4210 if (strstr($this->headers['accept-encoding'], 'gzip')) {
4211 if (function_exists('gzencode')) {
4212 if (isset($this->debug_flag) && $this->debug_flag) {
4213 $payload .= "<!-- Content being gzipped -->";
4214 }
4215 $this->outgoing_headers[] = "Content-Encoding: gzip";
4216 $payload = gzencode($payload);
4217 } else {
4218 if (isset($this->debug_flag) && $this->debug_flag) {
4219 $payload .= "<!-- Content will not be gzipped: no gzencode -->";
4220 }
4221 }
4222 } elseif (strstr($this->headers['accept-encoding'], 'deflate')) {
4223 // Note: MSIE requires gzdeflate output (no Zlib header and checksum),
4224 // instead of gzcompress output,
4225 // which conflicts with HTTP 1.1 spec (http://www.w3.org/Protocols/rfc2616/rfc2616-sec3.html#sec3.5)
4226 if (function_exists('gzdeflate')) {
4227 if (isset($this->debug_flag) && $this->debug_flag) {
4228 $payload .= "<!-- Content being deflated -->";
4229 }
4230 $this->outgoing_headers[] = "Content-Encoding: deflate";
4231 $payload = gzdeflate($payload);
4232 } else {
4233 if (isset($this->debug_flag) && $this->debug_flag) {
4234 $payload .= "<!-- Content will not be deflated: no gzcompress -->";
4235 }
4236 }
4237 }
4238 }
4239 //end code
4240 $this->outgoing_headers[] = "Content-Length: " . strlen($payload);
4241 reset($this->outgoing_headers);
4242 foreach ($this->outgoing_headers as $hdr) {
4243 header($hdr, false);
4244 }
4245 print $payload;
4246 $this->response = join("\r\n", $this->outgoing_headers) . "\r\n\r\n" . $payload;
4247 }
4248
4258 public function verify_method($operation, $request)
4259 {
4260 if (isset($this->wsdl) && is_object($this->wsdl)) {
4261 if ($this->wsdl->getOperationData($operation)) {
4262 return true;
4263 }
4264 } elseif (isset($this->operations[$operation])) {
4265 return true;
4266 }
4267 return false;
4268 }
4269
4278 public function parseRequest($headers, $data)
4279 {
4280 $this->debug('Entering parseRequest() for data of length ' . strlen($data) . ' and type ' . $headers['content-type']);
4281 if (!strstr($headers['content-type'], 'text/xml')) {
4282 $this->setError('Request not of type text/xml');
4283 return false;
4284 }
4285 if (strpos($headers['content-type'], '=')) {
4286 $enc = str_replace('"', '', substr(strstr($headers["content-type"], '='), 1));
4287 $this->debug('Got response encoding: ' . $enc);
4288 if (preg_match('/^(ISO-8859-1|US-ASCII|UTF-8)$/i', $enc)) {
4289 $this->xml_encoding = strtoupper($enc);
4290 } else {
4291 $this->xml_encoding = 'US-ASCII';
4292 }
4293 } else {
4294 // should be US-ASCII for HTTP 1.0 or ISO-8859-1 for HTTP 1.1
4295 $this->xml_encoding = 'ISO-8859-1';
4296 }
4297 $this->debug('Use encoding: ' . $this->xml_encoding . ' when creating nusoap_parser');
4298 // parse response, get soap parser obj
4299 $parser = new nusoap_parser($data, $this->xml_encoding, '', $this->decode_utf8);
4300 // parser debug
4301 $this->debug("parser debug: \n" . $parser->getDebug());
4302 // if fault occurred during message parsing
4303 if ($err = $parser->getError()) {
4304 $this->result = 'fault: error in msg parsing: ' . $err;
4305 $this->fault('SOAP-ENV:Client', "error in msg parsing:\n" . $err);
4306 // else successfully parsed request into soapval object
4307 } else {
4308 // get/set methodname
4309 $this->methodURI = $parser->root_struct_namespace;
4310 $this->methodname = $parser->root_struct_name;
4311 $this->debug('methodname: ' . $this->methodname . ' methodURI: ' . $this->methodURI);
4312 $this->debug('calling parser->get_soapbody()');
4313 $this->methodparams = $parser->get_soapbody();
4314 // get SOAP headers
4315 $this->requestHeaders = $parser->getHeaders();
4316 // get SOAP Header
4317 $this->requestHeader = $parser->get_soapheader();
4318 // add document for doclit support
4319 $this->document = $parser->document;
4320 }
4321 }
4322
4330 public function getHTTPBody($soapmsg)
4331 {
4332 return $soapmsg;
4333 }
4334
4343 public function getHTTPContentType()
4344 {
4345 return 'text/xml';
4346 }
4347
4358 {
4360 }
4361
4371 public function add_to_map($methodname, $in, $out)
4372 {
4373 $this->operations[$methodname] = array('name' => $methodname,'in' => $in,'out' => $out);
4374 }
4375
4390 public function register($name, $in = array(), $out = array(), $namespace = false, $soapaction = false, $style = false, $use = false, $documentation = '', $encodingStyle = '')
4391 {
4392 global $HTTP_SERVER_VARS;
4393
4394 if ($this->externalWSDLURL) {
4395 die('You cannot bind to an external WSDL file, and register methods outside of it! Please choose either WSDL or no WSDL.');
4396 }
4397 if (! $name) {
4398 die('You must specify a name when you register an operation');
4399 }
4400 if (!is_array($in)) {
4401 die('You must provide an array for operation inputs');
4402 }
4403 if (!is_array($out)) {
4404 die('You must provide an array for operation outputs');
4405 }
4406 if (false == $namespace) {
4407 }
4408 if (false == $soapaction) {
4409 if (isset($_SERVER)) {
4410 $SERVER_NAME = $_SERVER['SERVER_NAME'];
4411 $SCRIPT_NAME = isset($_SERVER['PHP_SELF']) ? $_SERVER['PHP_SELF'] : $_SERVER['SCRIPT_NAME'];
4412 $HTTPS = isset($_SERVER['HTTPS']) ? $_SERVER['HTTPS'] : (isset($HTTP_SERVER_VARS['HTTPS']) ? $HTTP_SERVER_VARS['HTTPS'] : 'off');
4413 } elseif (isset($HTTP_SERVER_VARS)) {
4414 $SERVER_NAME = $HTTP_SERVER_VARS['SERVER_NAME'];
4415 $SCRIPT_NAME = isset($HTTP_SERVER_VARS['PHP_SELF']) ? $HTTP_SERVER_VARS['PHP_SELF'] : $HTTP_SERVER_VARS['SCRIPT_NAME'];
4416 $HTTPS = isset($HTTP_SERVER_VARS['HTTPS']) ? $HTTP_SERVER_VARS['HTTPS'] : 'off';
4417 } else {
4418 $this->setError("Neither _SERVER nor HTTP_SERVER_VARS is available");
4419 }
4420 if ($HTTPS == '1' || $HTTPS == 'on') {
4421 $SCHEME = 'https';
4422 } else {
4423 $SCHEME = 'http';
4424 }
4425 $soapaction = "$SCHEME://$SERVER_NAME$SCRIPT_NAME/$name";
4426 }
4427 if (false == $style) {
4428 $style = "rpc";
4429 }
4430 if (false == $use) {
4431 $use = "encoded";
4432 }
4433 if ($use == 'encoded' && $encodingStyle = '') {
4434 $encodingStyle = 'http://schemas.xmlsoap.org/soap/encoding/';
4435 }
4436
4437 $this->operations[$name] = array(
4438 'name' => $name,
4439 'in' => $in,
4440 'out' => $out,
4441 'namespace' => $namespace,
4442 'soapaction' => $soapaction,
4443 'style' => $style);
4444 if ($this->wsdl) {
4445 $this->wsdl->addOperation($name, $in, $out, $namespace, $soapaction, $style, $use, $documentation, $encodingStyle);
4446 }
4447 return true;
4448 }
4449
4460 public function fault($faultcode, $faultstring, $faultactor = '', $faultdetail = '')
4461 {
4462 if ($faultdetail == '' && $this->debug_flag) {
4463 $faultdetail = $this->getDebug();
4464 }
4465 $this->fault = new nusoap_fault($faultcode, $faultactor, $faultstring, $faultdetail);
4466 $this->fault->soap_defencoding = $this->soap_defencoding;
4467 }
4468
4480 public function configureWSDL($serviceName, $namespace = false, $endpoint = false, $style = 'rpc', $transport = 'http://schemas.xmlsoap.org/soap/http', $schemaTargetNamespace = false)
4481 {
4482 global $HTTP_SERVER_VARS;
4483
4484 if (isset($_SERVER)) {
4485 $SERVER_NAME = $_SERVER['SERVER_NAME'];
4486 $SERVER_PORT = $_SERVER['SERVER_PORT'];
4487 $SCRIPT_NAME = isset($_SERVER['PHP_SELF']) ? $_SERVER['PHP_SELF'] : $_SERVER['SCRIPT_NAME'];
4488 $HTTPS = isset($_SERVER['HTTPS']) ? $_SERVER['HTTPS'] : (isset($HTTP_SERVER_VARS['HTTPS']) ? $HTTP_SERVER_VARS['HTTPS'] : 'off');
4489 } elseif (isset($HTTP_SERVER_VARS)) {
4490 $SERVER_NAME = $HTTP_SERVER_VARS['SERVER_NAME'];
4491 $SERVER_PORT = $HTTP_SERVER_VARS['SERVER_PORT'];
4492 $SCRIPT_NAME = isset($HTTP_SERVER_VARS['PHP_SELF']) ? $HTTP_SERVER_VARS['PHP_SELF'] : $HTTP_SERVER_VARS['SCRIPT_NAME'];
4493 $HTTPS = isset($HTTP_SERVER_VARS['HTTPS']) ? $HTTP_SERVER_VARS['HTTPS'] : 'off';
4494 } else {
4495 $this->setError("Neither _SERVER nor HTTP_SERVER_VARS is available");
4496 }
4497 // If server name has port number attached then strip it (else port number gets duplicated in WSDL output) (occurred using lighttpd and FastCGI)
4498 $colon = strpos($SERVER_NAME, ":");
4499 if ($colon) {
4500 $SERVER_NAME = substr($SERVER_NAME, 0, $colon);
4501 }
4502 if ($SERVER_PORT == 80) {
4503 $SERVER_PORT = '';
4504 } else {
4505 $SERVER_PORT = ':' . $SERVER_PORT;
4506 }
4507 if (false == $namespace) {
4508 $namespace = "http://$SERVER_NAME/soap/$serviceName";
4509 }
4510
4511 if (false == $endpoint) {
4512 if ($HTTPS == '1' || $HTTPS == 'on') {
4513 $SCHEME = 'https';
4514 } else {
4515 $SCHEME = 'http';
4516 }
4517 $endpoint = "$SCHEME://$SERVER_NAME$SERVER_PORT$SCRIPT_NAME";
4518 }
4519
4520 if (false == $schemaTargetNamespace) {
4521 $schemaTargetNamespace = $namespace;
4522 }
4523
4524 $this->wsdl = new wsdl();
4525 $this->wsdl->serviceName = $serviceName;
4526 $this->wsdl->endpoint = $endpoint;
4527 $this->wsdl->namespaces['tns'] = $namespace;
4528 $this->wsdl->namespaces['soap'] = 'http://schemas.xmlsoap.org/wsdl/soap/';
4529 $this->wsdl->namespaces['wsdl'] = 'http://schemas.xmlsoap.org/wsdl/';
4530 if ($schemaTargetNamespace != $namespace) {
4531 $this->wsdl->namespaces['types'] = $schemaTargetNamespace;
4532 }
4533 $this->wsdl->schemas[$schemaTargetNamespace][0] = new nusoap_xmlschema('', '', $this->wsdl->namespaces);
4534 if ($style == 'document') {
4535 $this->wsdl->schemas[$schemaTargetNamespace][0]->schemaInfo['elementFormDefault'] = 'qualified';
4536 }
4537 $this->wsdl->schemas[$schemaTargetNamespace][0]->schemaTargetNamespace = $schemaTargetNamespace;
4538 $this->wsdl->schemas[$schemaTargetNamespace][0]->imports['http://schemas.xmlsoap.org/soap/encoding/'][0] = array('location' => '', 'loaded' => true);
4539 $this->wsdl->schemas[$schemaTargetNamespace][0]->imports['http://schemas.xmlsoap.org/wsdl/'][0] = array('location' => '', 'loaded' => true);
4540 $this->wsdl->bindings[$serviceName . 'Binding'] = array(
4541 'name' => $serviceName . 'Binding',
4542 'style' => $style,
4543 'transport' => $transport,
4544 'portType' => $serviceName . 'PortType');
4545 $this->wsdl->ports[$serviceName . 'Port'] = array(
4546 'binding' => $serviceName . 'Binding',
4547 'location' => $endpoint,
4548 'bindingType' => 'http://schemas.xmlsoap.org/wsdl/soap/');
4549 }
4550
4551 public function addInternalPort(string $serviceName, string $url): void
4552 {
4553 $this->wsdl->ports['Internal' . $serviceName . 'Port'] = [
4554 'binding' => $serviceName . 'Binding',
4555 'location' => (string) (new \ILIAS\Data\URI($url))->withQuery(),
4556 'bindingType' => 'http://schemas.xmlsoap.org/wsdl/soap/'
4557 ];
4558 }
4559}
4560
4565{
4566}
4567
4568?><?php
4569
4570
4571
4581class wsdl extends nusoap_base
4582{
4583 // URL or filename of the root of this WSDL
4587 public $wsdl;
4588 // define internal arrays of bindings, ports, operations, messages, etc.
4589 public $schemas = array();
4591 public $message = array();
4592 public $complexTypes = array();
4593 public $messages = array();
4596 public $portTypes = array();
4598 public $bindings = array();
4600 public $ports = array();
4602 public $opData = array();
4603 public $status = '';
4604 public $documentation = false;
4605 public $endpoint = '';
4606 // array of wsdl docs to import
4607 public $import = array();
4608 // parser vars
4609 public $parser;
4610 public $position = 0;
4611 public $depth = 0;
4612 public $depth_array = array();
4613 // for getting wsdl
4614 public $proxyhost = '';
4615 public $proxyport = '';
4616 public $proxyusername = '';
4617 public $proxypassword = '';
4618 public $timeout = 0;
4620 public $curl_options = array(); // User-specified cURL options
4621 public $use_curl = false; // whether to always try to use cURL
4622 // for HTTP authentication
4623 public $username = ''; // Username for HTTP authentication
4624 public $password = ''; // Password for HTTP authentication
4625 public $authtype = ''; // Type of HTTP authentication
4626 public $certRequest = array(); // Certificate for HTTP SSL authentication
4627
4642 public function __construct($wsdl = '', $proxyhost = false, $proxyport = false, $proxyusername = false, $proxypassword = false, $timeout = 0, $response_timeout = 30, $curl_options = null, $use_curl = false)
4643 {
4645 $this->debug("ctor wsdl=$wsdl timeout=$timeout response_timeout=$response_timeout");
4646 $this->proxyhost = $proxyhost;
4647 $this->proxyport = $proxyport;
4648 $this->proxyusername = $proxyusername;
4649 $this->proxypassword = $proxypassword;
4650 $this->timeout = $timeout;
4651 $this->response_timeout = $response_timeout;
4652 if (is_array($curl_options)) {
4653 $this->curl_options = $curl_options;
4654 }
4655 $this->use_curl = $use_curl;
4656 $this->fetchWSDL($wsdl);
4657 }
4658
4664 public function fetchWSDL($wsdl)
4665 {
4666 $this->debug("parse and process WSDL path=$wsdl");
4667 $this->wsdl = $wsdl;
4668 // parse wsdl file
4669 if ($this->wsdl != "") {
4670 $this->parseWSDL($this->wsdl);
4671 }
4672 // imports
4673 // TODO: handle imports more properly, grabbing them in-line and nesting them
4674 $imported_urls = array();
4675 $imported = 1;
4676 while ($imported > 0) {
4677 $imported = 0;
4678 // Schema imports
4679 foreach ($this->schemas as $ns => $list) {
4680 foreach ($list as $xs) {
4681 $wsdlparts = parse_url($this->wsdl); // this is bogusly simple!
4682 foreach ($xs->imports as $ns2 => $list2) {
4683 for ($ii = 0; $ii < count($list2); $ii++) {
4684 if (! $list2[$ii]['loaded']) {
4685 $this->schemas[$ns]->imports[$ns2][$ii]['loaded'] = true;
4686 $url = $list2[$ii]['location'];
4687 if ($url != '') {
4688 $urlparts = parse_url($url);
4689 if (!isset($urlparts['host'])) {
4690 $url = $wsdlparts['scheme'] . '://' . $wsdlparts['host'] . (isset($wsdlparts['port']) ? ':' . $wsdlparts['port'] : '') .
4691 substr($wsdlparts['path'], 0, strrpos($wsdlparts['path'], '/') + 1) . $urlparts['path'];
4692 }
4693 if (! in_array($url, $imported_urls)) {
4694 $this->parseWSDL($url);
4695 $imported++;
4696 $imported_urls[] = $url;
4697 }
4698 } else {
4699 $this->debug("Unexpected scenario: empty URL for unloaded import");
4700 }
4701 }
4702 }
4703 }
4704 }
4705 }
4706 // WSDL imports
4707 $wsdlparts = parse_url($this->wsdl); // this is bogusly simple!
4708 foreach ($this->import as $ns => $list) {
4709 for ($ii = 0; $ii < count($list); $ii++) {
4710 if (! $list[$ii]['loaded']) {
4711 $this->import[$ns][$ii]['loaded'] = true;
4712 $url = $list[$ii]['location'];
4713 if ($url != '') {
4714 $urlparts = parse_url($url);
4715 if (!isset($urlparts['host'])) {
4716 $url = $wsdlparts['scheme'] . '://' . $wsdlparts['host'] . (isset($wsdlparts['port']) ? ':' . $wsdlparts['port'] : '') .
4717 substr($wsdlparts['path'], 0, strrpos($wsdlparts['path'], '/') + 1) . $urlparts['path'];
4718 }
4719 if (! in_array($url, $imported_urls)) {
4720 $this->parseWSDL($url);
4721 $imported++;
4722 $imported_urls[] = $url;
4723 }
4724 } else {
4725 $this->debug("Unexpected scenario: empty URL for unloaded import");
4726 }
4727 }
4728 }
4729 }
4730 }
4731 // add new data to operation data
4732 foreach ($this->bindings as $binding => $bindingData) {
4733 if (isset($bindingData['operations']) && is_array($bindingData['operations'])) {
4734 foreach ($bindingData['operations'] as $operation => $data) {
4735 $this->debug('post-parse data gathering for ' . $operation);
4736 $this->bindings[$binding]['operations'][$operation]['input'] =
4737 isset($this->bindings[$binding]['operations'][$operation]['input']) ?
4738 array_merge($this->bindings[$binding]['operations'][$operation]['input'], $this->portTypes[ $bindingData['portType'] ][$operation]['input']) :
4739 $this->portTypes[ $bindingData['portType'] ][$operation]['input'];
4740 $this->bindings[$binding]['operations'][$operation]['output'] =
4741 isset($this->bindings[$binding]['operations'][$operation]['output']) ?
4742 array_merge($this->bindings[$binding]['operations'][$operation]['output'], $this->portTypes[ $bindingData['portType'] ][$operation]['output']) :
4743 $this->portTypes[ $bindingData['portType'] ][$operation]['output'];
4744 if (isset($this->messages[ $this->bindings[$binding]['operations'][$operation]['input']['message'] ])) {
4745 $this->bindings[$binding]['operations'][$operation]['input']['parts'] = $this->messages[ $this->bindings[$binding]['operations'][$operation]['input']['message'] ];
4746 }
4747 if (isset($this->messages[ $this->bindings[$binding]['operations'][$operation]['output']['message'] ])) {
4748 $this->bindings[$binding]['operations'][$operation]['output']['parts'] = $this->messages[ $this->bindings[$binding]['operations'][$operation]['output']['message'] ];
4749 }
4750 // Set operation style if necessary, but do not override one already provided
4751 if (isset($bindingData['style']) && !isset($this->bindings[$binding]['operations'][$operation]['style'])) {
4752 $this->bindings[$binding]['operations'][$operation]['style'] = $bindingData['style'];
4753 }
4754 $this->bindings[$binding]['operations'][$operation]['transport'] = isset($bindingData['transport']) ? $bindingData['transport'] : '';
4755 $this->bindings[$binding]['operations'][$operation]['documentation'] = isset($this->portTypes[ $bindingData['portType'] ][$operation]['documentation']) ? $this->portTypes[ $bindingData['portType'] ][$operation]['documentation'] : '';
4756 $this->bindings[$binding]['operations'][$operation]['endpoint'] = isset($bindingData['endpoint']) ? $bindingData['endpoint'] : '';
4757 }
4758 }
4759 }
4760 }
4761
4768 public function parseWSDL($wsdl = '')
4769 {
4770 $this->debug("parse WSDL at path=$wsdl");
4771
4772 if ($wsdl == '') {
4773 $this->debug('no wsdl passed to parseWSDL()!!');
4774 $this->setError('no wsdl passed to parseWSDL()!!');
4775 return false;
4776 }
4777
4778 // parse $wsdl for url format
4779 $wsdl_props = parse_url($wsdl);
4780
4781 if (isset($wsdl_props['scheme']) && ($wsdl_props['scheme'] == 'http' || $wsdl_props['scheme'] == 'https')) {
4782 $this->debug('getting WSDL http(s) URL ' . $wsdl);
4783 // get wsdl
4784 $tr = new soap_transport_http($wsdl, $this->curl_options, $this->use_curl);
4785 $tr->request_method = 'GET';
4786 $tr->useSOAPAction = false;
4787 if ($this->proxyhost && $this->proxyport) {
4788 $tr->setProxy($this->proxyhost, $this->proxyport, $this->proxyusername, $this->proxypassword);
4789 }
4790 if ($this->authtype != '') {
4791 $tr->setCredentials($this->username, $this->password, $this->authtype, array(), $this->certRequest);
4792 }
4793 $tr->setEncoding('gzip, deflate');
4794 $wsdl_string = $tr->send('', $this->timeout, $this->response_timeout);
4795 //$this->debug("WSDL request\n" . $tr->outgoing_payload);
4796 //$this->debug("WSDL response\n" . $tr->incoming_payload);
4797 $this->appendDebug($tr->getDebug());
4798 // catch errors
4799 if ($err = $tr->getError()) {
4800 $errstr = 'HTTP ERROR: ' . $err;
4801 $this->debug($errstr);
4802 $this->setError($errstr);
4803 unset($tr);
4804 return false;
4805 }
4806 unset($tr);
4807 $this->debug("got WSDL URL");
4808 } else {
4809 // $wsdl is not http(s), so treat it as a file URL or plain file path
4810 if (isset($wsdl_props['scheme']) && ($wsdl_props['scheme'] == 'file') && isset($wsdl_props['path'])) {
4811 $path = isset($wsdl_props['host']) ? ($wsdl_props['host'] . ':' . $wsdl_props['path']) : $wsdl_props['path'];
4812 } else {
4813 $path = $wsdl;
4814 }
4815 $this->debug('getting WSDL file ' . $path);
4816 if ($fp = @fopen($path, 'r')) {
4817 $wsdl_string = '';
4818 while ($data = fread($fp, 32768)) {
4819 $wsdl_string .= $data;
4820 }
4821 fclose($fp);
4822 } else {
4823 $errstr = "Bad path to WSDL file $path";
4824 $this->debug($errstr);
4825 $this->setError($errstr);
4826 return false;
4827 }
4828 }
4829 $this->debug('Parse WSDL');
4830 // end new code added
4831 // Create an XML parser.
4832 $this->parser = xml_parser_create();
4833 // Set the options for parsing the XML data.
4834 // xml_parser_set_option($parser, XML_OPTION_SKIP_WHITE, 1);
4835 xml_parser_set_option($this->parser, XML_OPTION_CASE_FOLDING, 0);
4836 // Set the object for the parser.
4837 // Set the element handlers for the parser.
4838 xml_set_element_handler($this->parser, $this->start_element(...), $this->end_element(...));
4839 xml_set_character_data_handler($this->parser, $this->character_data(...));
4840 // Parse the XML file.
4841 if (!xml_parse($this->parser, $wsdl_string, true)) {
4842 // Display an error message.
4843 $errstr = sprintf(
4844 'XML error parsing WSDL from %s on line %d: %s',
4845 $wsdl,
4846 xml_get_current_line_number($this->parser),
4847 xml_error_string(xml_get_error_code($this->parser))
4848 );
4849 $this->debug($errstr);
4850 $this->debug("XML payload:\n" . $wsdl_string);
4851 $this->setError($errstr);
4852 return false;
4853 }
4854 $this->debug('Parsing WSDL done');
4855 // catch wsdl parse errors
4856 if ($this->getError()) {
4857 return false;
4858 }
4859 return true;
4860 }
4861
4870 public function start_element($parser, $name, $attrs)
4871 {
4872 if ($this->status == 'schema') {
4873 $this->currentSchema->schemaStartElement($parser, $name, $attrs);
4874 $this->appendDebug($this->currentSchema->getDebug());
4875 $this->currentSchema->clearDebug();
4876 } elseif (preg_match('/schema$/', $name)) {
4877 $this->debug('Parsing WSDL schema');
4878 // $this->debug("startElement for $name ($attrs[name]). status = $this->status (".$this->getLocalPart($name).")");
4879 $this->status = 'schema';
4880 $this->currentSchema = new nusoap_xmlschema('', '', $this->namespaces);
4881 $this->currentSchema->schemaStartElement($parser, $name, $attrs);
4882 $this->appendDebug($this->currentSchema->getDebug());
4883 $this->currentSchema->clearDebug();
4884 } else {
4885 // position in the total number of elements, starting from 0
4886 $pos = $this->position++;
4887 $depth = $this->depth++;
4888 // set self as current value for this depth
4889 $this->depth_array[$depth] = $pos;
4890 $this->message[$pos] = array('cdata' => '');
4891 // process attributes
4892 if (count($attrs) > 0) {
4893 // register namespace declarations
4894 foreach ($attrs as $k => $v) {
4895 if (preg_match('/^xmlns/', $k)) {
4896 if ($ns_prefix = substr(strrchr($k, ':'), 1)) {
4897 $this->namespaces[$ns_prefix] = $v;
4898 } else {
4899 $this->namespaces['ns' . (count($this->namespaces) + 1)] = $v;
4900 }
4901 if ($v == 'http://www.w3.org/2001/XMLSchema' || $v == 'http://www.w3.org/1999/XMLSchema' || $v == 'http://www.w3.org/2000/10/XMLSchema') {
4902 $this->XMLSchemaVersion = $v;
4903 $this->namespaces['xsi'] = $v . '-instance';
4904 }
4905 }
4906 }
4907 // expand each attribute prefix to its namespace
4908 foreach ($attrs as $k => $v) {
4909 $k = strpos($k, ':') ? $this->expandQname($k) : $k;
4910 if ($k != 'location' && $k != 'soapAction' && $k != 'namespace') {
4911 $v = strpos($v, ':') ? $this->expandQname($v) : $v;
4912 }
4913 $eAttrs[$k] = $v;
4914 }
4915 $attrs = $eAttrs;
4916 } else {
4917 $attrs = array();
4918 }
4919 // get element prefix, namespace and name
4920 if (preg_match('/:/', $name)) {
4921 // get ns prefix
4922 $prefix = substr($name, 0, strpos($name, ':'));
4923 // get ns
4924 $namespace = isset($this->namespaces[$prefix]) ? $this->namespaces[$prefix] : '';
4925 // get unqualified name
4926 $name = substr(strstr($name, ':'), 1);
4927 }
4928 // process attributes, expanding any prefixes to namespaces
4929 // find status, register data
4930 switch ($this->status) {
4931 case 'message':
4932 if ($name == 'part') {
4933 if (isset($attrs['type'])) {
4934 $this->debug("msg " . $this->currentMessage . ": found part (with type) $attrs[name]: " . implode(',', $attrs));
4935 $this->messages[$this->currentMessage][$attrs['name']] = $attrs['type'];
4936 }
4937 if (isset($attrs['element'])) {
4938 $this->debug("msg " . $this->currentMessage . ": found part (with element) $attrs[name]: " . implode(',', $attrs));
4939 $this->messages[$this->currentMessage][$attrs['name']] = $attrs['element'] . '^';
4940 }
4941 }
4942 break;
4943 case 'portType':
4944 switch ($name) {
4945 case 'operation':
4946 $this->currentPortOperation = $attrs['name'];
4947 $this->debug("portType $this->currentPortType operation: $this->currentPortOperation");
4948 if (isset($attrs['parameterOrder'])) {
4949 $this->portTypes[$this->currentPortType][$attrs['name']]['parameterOrder'] = $attrs['parameterOrder'];
4950 }
4951 break;
4952 case 'documentation':
4953 $this->documentation = true;
4954 break;
4955 // merge input/output data
4956 default:
4957 $m = isset($attrs['message']) ? $this->getLocalPart($attrs['message']) : '';
4958 $this->portTypes[$this->currentPortType][$this->currentPortOperation][$name]['message'] = $m;
4959 break;
4960 }
4961 break;
4962 case 'binding':
4963 switch ($name) {
4964 case 'binding':
4965 // get ns prefix
4966 if (isset($attrs['style'])) {
4967 $this->bindings[$this->currentBinding]['prefix'] = $prefix;
4968 }
4969 $this->bindings[$this->currentBinding] = array_merge($this->bindings[$this->currentBinding], $attrs);
4970 break;
4971 case 'header':
4972 $this->bindings[$this->currentBinding]['operations'][$this->currentOperation][$this->opStatus]['headers'][] = $attrs;
4973 break;
4974 case 'operation':
4975 if (isset($attrs['soapAction'])) {
4976 $this->bindings[$this->currentBinding]['operations'][$this->currentOperation]['soapAction'] = $attrs['soapAction'];
4977 }
4978 if (isset($attrs['style'])) {
4979 $this->bindings[$this->currentBinding]['operations'][$this->currentOperation]['style'] = $attrs['style'];
4980 }
4981 if (isset($attrs['name'])) {
4982 $this->currentOperation = $attrs['name'];
4983 $this->debug("current binding operation: $this->currentOperation");
4984 $this->bindings[$this->currentBinding]['operations'][$this->currentOperation]['name'] = $attrs['name'];
4985 $this->bindings[$this->currentBinding]['operations'][$this->currentOperation]['binding'] = $this->currentBinding;
4986 $this->bindings[$this->currentBinding]['operations'][$this->currentOperation]['endpoint'] = isset($this->bindings[$this->currentBinding]['endpoint']) ? $this->bindings[$this->currentBinding]['endpoint'] : '';
4987 }
4988 break;
4989 case 'input':
4990 $this->opStatus = 'input';
4991 break;
4992 case 'output':
4993 $this->opStatus = 'output';
4994 break;
4995 case 'body':
4996 if (isset($this->bindings[$this->currentBinding]['operations'][$this->currentOperation][$this->opStatus])) {
4997 $this->bindings[$this->currentBinding]['operations'][$this->currentOperation][$this->opStatus] = array_merge($this->bindings[$this->currentBinding]['operations'][$this->currentOperation][$this->opStatus], $attrs);
4998 } else {
4999 $this->bindings[$this->currentBinding]['operations'][$this->currentOperation][$this->opStatus] = $attrs;
5000 }
5001 break;
5002 }
5003 break;
5004 case 'service':
5005 switch ($name) {
5006 case 'port':
5007 $this->currentPort = $attrs['name'];
5008 $this->debug('current port: ' . $this->currentPort);
5009 $this->ports[$this->currentPort]['binding'] = $this->getLocalPart($attrs['binding']);
5010
5011 break;
5012 case 'address':
5013 $this->ports[$this->currentPort]['location'] = $attrs['location'];
5014 $this->ports[$this->currentPort]['bindingType'] = $namespace;
5015 $this->bindings[ $this->ports[$this->currentPort]['binding'] ]['bindingType'] = $namespace;
5016 $this->bindings[ $this->ports[$this->currentPort]['binding'] ]['endpoint'] = $attrs['location'];
5017 break;
5018 }
5019 break;
5020 }
5021 // set status
5022 switch ($name) {
5023 case 'import':
5024 if (isset($attrs['location'])) {
5025 $this->import[$attrs['namespace']][] = array('location' => $attrs['location'], 'loaded' => false);
5026 $this->debug('parsing import ' . $attrs['namespace'] . ' - ' . $attrs['location'] . ' (' . count($this->import[$attrs['namespace']]) . ')');
5027 } else {
5028 $this->import[$attrs['namespace']][] = array('location' => '', 'loaded' => true);
5029 if (! $this->getPrefixFromNamespace($attrs['namespace'])) {
5030 $this->namespaces['ns' . (count($this->namespaces) + 1)] = $attrs['namespace'];
5031 }
5032 $this->debug('parsing import ' . $attrs['namespace'] . ' - [no location] (' . count($this->import[$attrs['namespace']]) . ')');
5033 }
5034 break;
5035 //wait for schema
5036 //case 'types':
5037 // $this->status = 'schema';
5038 // break;
5039 case 'message':
5040 $this->status = 'message';
5041 $this->messages[$attrs['name']] = array();
5042 $this->currentMessage = $attrs['name'];
5043 break;
5044 case 'portType':
5045 $this->status = 'portType';
5046 $this->portTypes[$attrs['name']] = array();
5047 $this->currentPortType = $attrs['name'];
5048 break;
5049 case "binding":
5050 if (isset($attrs['name'])) {
5051 // get binding name
5052 if (strpos($attrs['name'], ':')) {
5053 $this->currentBinding = $this->getLocalPart($attrs['name']);
5054 } else {
5055 $this->currentBinding = $attrs['name'];
5056 }
5057 $this->status = 'binding';
5058 $this->bindings[$this->currentBinding]['portType'] = $this->getLocalPart($attrs['type']);
5059 $this->debug("current binding: $this->currentBinding of portType: " . $attrs['type']);
5060 }
5061 break;
5062 case 'service':
5063 $this->serviceName = $attrs['name'];
5064 $this->status = 'service';
5065 $this->debug('current service: ' . $this->serviceName);
5066 break;
5067 case 'definitions':
5068 foreach ($attrs as $name => $value) {
5069 $this->wsdl_info[$name] = $value;
5070 }
5071 break;
5072 }
5073 }
5074 }
5075
5083 public function end_element($parser, $name)
5084 {
5085 // unset schema status
5086 if (/*preg_match('/types$/', $name) ||*/ preg_match('/schema$/', $name)) {
5087 $this->status = "";
5088 $this->appendDebug($this->currentSchema->getDebug());
5089 $this->currentSchema->clearDebug();
5090 $this->schemas[$this->currentSchema->schemaTargetNamespace][] = $this->currentSchema;
5091 $this->debug('Parsing WSDL schema done');
5092 }
5093 if ($this->status == 'schema') {
5094 $this->currentSchema->schemaEndElement($parser, $name);
5095 } else {
5096 // bring depth down a notch
5097 $this->depth--;
5098 }
5099 // end documentation
5100 if ($this->documentation) {
5101 //TODO: track the node to which documentation should be assigned; it can be a part, message, etc.
5102 //$this->portTypes[$this->currentPortType][$this->currentPortOperation]['documentation'] = $this->documentation;
5103 $this->documentation = false;
5104 }
5105 }
5106
5114 public function character_data($parser, $data)
5115 {
5116 $pos = isset($this->depth_array[$this->depth]) ? $this->depth_array[$this->depth] : 0;
5117 if (isset($this->message[$pos]['cdata'])) {
5118 $this->message[$pos]['cdata'] .= $data;
5119 }
5120 if ($this->documentation) {
5121 $this->documentation .= $data;
5122 }
5123 }
5124
5134 public function setCredentials($username, $password, $authtype = 'basic', $certRequest = array())
5135 {
5136 $this->debug("setCredentials username=$username authtype=$authtype certRequest=");
5137 $this->appendDebug($this->varDump($certRequest));
5138 $this->username = $username;
5139 $this->password = $password;
5140 $this->authtype = $authtype;
5141 $this->certRequest = $certRequest;
5142 }
5143
5144 public function getBindingData($binding)
5145 {
5146 if (is_array($this->bindings[$binding])) {
5147 return $this->bindings[$binding];
5148 }
5149 }
5150
5158 public function getOperations($bindingType = 'soap')
5159 {
5160 $ops = array();
5161 if ($bindingType == 'soap') {
5162 $bindingType = 'http://schemas.xmlsoap.org/wsdl/soap/';
5163 } elseif ($bindingType == 'soap12') {
5164 $bindingType = 'http://schemas.xmlsoap.org/wsdl/soap12/';
5165 }
5166 // loop thru ports
5167 foreach ($this->ports as $port => $portData) {
5168 // binding type of port matches parameter
5169 if ($portData['bindingType'] == $bindingType) {
5170 //$this->debug("getOperations for port $port");
5171 //$this->debug("port data: " . $this->varDump($portData));
5172 //$this->debug("bindings: " . $this->varDump($this->bindings[ $portData['binding'] ]));
5173 // merge bindings
5174 if (isset($this->bindings[ $portData['binding'] ]['operations'])) {
5175 $ops = array_merge($ops, $this->bindings[ $portData['binding'] ]['operations']);
5176 }
5177 }
5178 }
5179 return $ops;
5180 }
5181
5190 public function getOperationData($operation, $bindingType = 'soap')
5191 {
5192 if ($bindingType == 'soap') {
5193 $bindingType = 'http://schemas.xmlsoap.org/wsdl/soap/';
5194 } elseif ($bindingType == 'soap12') {
5195 $bindingType = 'http://schemas.xmlsoap.org/wsdl/soap12/';
5196 }
5197 // loop thru ports
5198 foreach ($this->ports as $port => $portData) {
5199 // binding type of port matches parameter
5200 if ($portData['bindingType'] == $bindingType) {
5201 // get binding
5202 //foreach($this->bindings[ $portData['binding'] ]['operations'] as $bOperation => $opData) {
5203 foreach (array_keys($this->bindings[ $portData['binding'] ]['operations']) as $bOperation) {
5204 // note that we could/should also check the namespace here
5205 if ($operation == $bOperation) {
5206 $opData = $this->bindings[ $portData['binding'] ]['operations'][$operation];
5207 return $opData;
5208 }
5209 }
5210 }
5211 }
5212 }
5213
5222 public function getOperationDataForSoapAction($soapAction, $bindingType = 'soap')
5223 {
5224 if ($bindingType == 'soap') {
5225 $bindingType = 'http://schemas.xmlsoap.org/wsdl/soap/';
5226 } elseif ($bindingType == 'soap12') {
5227 $bindingType = 'http://schemas.xmlsoap.org/wsdl/soap12/';
5228 }
5229 // loop thru ports
5230 foreach ($this->ports as $port => $portData) {
5231 // binding type of port matches parameter
5232 if ($portData['bindingType'] == $bindingType) {
5233 // loop through operations for the binding
5234 foreach ($this->bindings[ $portData['binding'] ]['operations'] as $bOperation => $opData) {
5235 if ($opData['soapAction'] == $soapAction) {
5236 return $opData;
5237 }
5238 }
5239 }
5240 }
5241 }
5242
5261 public function getTypeDef($type, $ns)
5262 {
5263 $this->debug("in getTypeDef: type=$type, ns=$ns");
5264 if ((! $ns) && isset($this->namespaces['tns'])) {
5265 $ns = $this->namespaces['tns'];
5266 $this->debug("in getTypeDef: type namespace forced to $ns");
5267 }
5268 if (!isset($this->schemas[$ns])) {
5269 foreach ($this->schemas as $ns0 => $schema0) {
5270 if (strcasecmp($ns, $ns0) == 0) {
5271 $this->debug("in getTypeDef: replacing schema namespace $ns with $ns0");
5272 $ns = $ns0;
5273 break;
5274 }
5275 }
5276 }
5277 if (isset($this->schemas[$ns])) {
5278 $this->debug("in getTypeDef: have schema for namespace $ns");
5279 for ($i = 0; $i < count($this->schemas[$ns]); $i++) {
5280 $xs = &$this->schemas[$ns][$i];
5281 $t = $xs->getTypeDef($type);
5282 //$this->appendDebug($xs->getDebug());
5283 //$xs->clearDebug();
5284 if ($t) {
5285 if (!isset($t['phpType'])) {
5286 // get info for type to tack onto the element
5287 $uqType = substr($t['type'], strrpos($t['type'], ':') + 1);
5288 $ns = substr($t['type'], 0, strrpos($t['type'], ':'));
5289 $etype = $this->getTypeDef($uqType, $ns);
5290 if ($etype) {
5291 $this->debug("found type for [element] $type:");
5292 $this->debug($this->varDump($etype));
5293 if (isset($etype['phpType'])) {
5294 $t['phpType'] = $etype['phpType'];
5295 }
5296 if (isset($etype['elements'])) {
5297 $t['elements'] = $etype['elements'];
5298 }
5299 if (isset($etype['attrs'])) {
5300 $t['attrs'] = $etype['attrs'];
5301 }
5302 }
5303 }
5304 return $t;
5305 }
5306 }
5307 } else {
5308 $this->debug("in getTypeDef: do not have schema for namespace $ns");
5309 }
5310 return false;
5311 }
5312
5318 public function webDescription()
5319 {
5320 global $HTTP_SERVER_VARS;
5321
5322 if (isset($_SERVER)) {
5323 $PHP_SELF = $_SERVER['PHP_SELF'];
5324 } elseif (isset($HTTP_SERVER_VARS)) {
5325 $PHP_SELF = $HTTP_SERVER_VARS['PHP_SELF'];
5326 } else {
5327 $this->setError("Neither _SERVER nor HTTP_SERVER_VARS is available");
5328 }
5329 // begin-patch: https://mantis.ilias.de/view.php?id=28866
5330 $PHP_SELF = htmlspecialchars($PHP_SELF, ENT_QUOTES | ENT_HTML5, 'UTF-8');
5331 // end-patch
5332
5333 $b = '
5334 <html><head><title>NuSOAP: ' . $this->serviceName . '</title>
5335 <style type="text/css">
5336 body { font-family: arial; color: #000000; background-color: #ffffff; margin: 0px 0px 0px 0px; }
5337 p { font-family: arial; color: #000000; margin-top: 0px; margin-bottom: 12px; }
5338 pre { background-color: silver; padding: 5px; font-family: Courier New; font-size: x-small; color: #000000;}
5339 ul { margin-top: 10px; margin-left: 20px; }
5340 li { list-style-type: none; margin-top: 10px; color: #000000; }
5341 .content{
5342 margin-left: 0px; padding-bottom: 2em; }
5343 .nav {
5344 padding-top: 10px; padding-bottom: 10px; padding-left: 15px; font-size: .70em;
5345 margin-top: 10px; margin-left: 0px; color: #000000;
5346 background-color: #ccccff; width: 20%; margin-left: 20px; margin-top: 20px; }
5347 .title {
5348 font-family: arial; font-size: 26px; color: #ffffff;
5349 background-color: #999999; width: 105%; margin-left: 0px;
5350 padding-top: 10px; padding-bottom: 10px; padding-left: 15px;}
5351 .hidden {
5352 position: absolute; visibility: hidden; z-index: 200; left: 250px; top: 100px;
5353 font-family: arial; overflow: hidden; width: 600;
5354 padding: 20px; font-size: 10px; background-color: #999999;
5355 layer-background-color:#FFFFFF; }
5356 a,a:active { color: charcoal; font-weight: bold; }
5357 a:visited { color: #666666; font-weight: bold; }
5358 a:hover { color: cc3300; font-weight: bold; }
5359 </style>
5360 <script language="JavaScript" type="text/javascript">
5361 <!--
5362 // POP-UP CAPTIONS...
5363 function lib_bwcheck(){ //Browsercheck (needed)
5364 this.ver=navigator.appVersion
5365 this.agent=navigator.userAgent
5366 this.dom=document.getElementById?1:0
5367 this.opera5=this.agent.indexOf("Opera 5")>-1
5368 this.ie5=(this.ver.indexOf("MSIE 5")>-1 && this.dom && !this.opera5)?1:0;
5369 this.ie6=(this.ver.indexOf("MSIE 6")>-1 && this.dom && !this.opera5)?1:0;
5370 this.ie4=(document.all && !this.dom && !this.opera5)?1:0;
5371 this.ie=this.ie4||this.ie5||this.ie6
5372 this.mac=this.agent.indexOf("Mac")>-1
5373 this.ns6=(this.dom && parseInt(this.ver) >= 5) ?1:0;
5374 this.ns4=(document.layers && !this.dom)?1:0;
5375 this.bw=(this.ie6 || this.ie5 || this.ie4 || this.ns4 || this.ns6 || this.opera5)
5376 return this
5377 }
5378 var bw = new lib_bwcheck()
5379 //Makes crossbrowser object.
5380 function makeObj(obj){
5381 this.evnt=bw.dom? document.getElementById(obj):bw.ie4?document.all[obj]:bw.ns4?document.layers[obj]:0;
5382 if(!this.evnt) return false
5383 this.css=bw.dom||bw.ie4?this.evnt.style:bw.ns4?this.evnt:0;
5384 this.wref=bw.dom||bw.ie4?this.evnt:bw.ns4?this.css.document:0;
5385 this.writeIt=b_writeIt;
5386 return this
5387 }
5388 // A unit of measure that will be added when setting the position of a layer.
5389 //var px = bw.ns4||window.opera?"":"px";
5390 function b_writeIt(text){
5391 if (bw.ns4){this.wref.write(text);this.wref.close()}
5392 else this.wref.innerHTML = text
5393 }
5394 //Shows the messages
5395 var oDesc;
5396 function popup(divid){
5397 if(oDesc = new makeObj(divid)){
5398 oDesc.css.visibility = "visible"
5399 }
5400 }
5401 function popout(){ // Hides message
5402 if(oDesc) oDesc.css.visibility = "hidden"
5403 }
5404 //-->
5405 </script>
5406 </head>
5407 <body>
5408 <div class=content>
5409 <br><br>
5410 <div class=title>' . $this->serviceName . '</div>
5411 <div class=nav>
5412 <p>View the <a href="' . $PHP_SELF . '?wsdl">WSDL</a> for the service.
5413 Click on an operation name to view it&apos;s details.</p>
5414 <ul>';
5415 foreach ($this->getOperations() as $op => $data) {
5416 // begin-patch: https://mantis.ilias.de/view.php?id=28866
5417 if (isset($data['endpoint'])) {
5418 $data['endpoint'] = htmlspecialchars($data['endpoint'], ENT_QUOTES | ENT_HTML5, 'UTF-8');
5419 }
5420 // end-patch
5421 $b .= "<li><a href='#' onclick=\"popout();popup('$op')\">$op</a></li>";
5422 // create hidden div
5423 $b .= "<div id='$op' class='hidden'>
5424 <a href='#' onclick='popout()'><font color='#ffffff'>Close</font></a><br><br>";
5425 foreach ($data as $donnie => $marie) { // loop through opdata
5426 if ($donnie == 'input' || $donnie == 'output') { // show input/output data
5427 $b .= "<font color='white'>" . ucfirst($donnie) . ':</font><br>';
5428 foreach ($marie as $captain => $tenille) { // loop through data
5429 if ($captain == 'parts') { // loop thru parts
5430 $b .= "&nbsp;&nbsp;$captain:<br>";
5431 //if(is_array($tenille)){
5432 foreach ($tenille as $joanie => $chachi) {
5433 $b .= "&nbsp;&nbsp;&nbsp;&nbsp;$joanie: $chachi<br>";
5434 }
5435 //}
5436 } else {
5437 $b .= "&nbsp;&nbsp;$captain: $tenille<br>";
5438 }
5439 }
5440 } else {
5441 $b .= "<font color='white'>" . ucfirst($donnie) . ":</font> $marie<br>";
5442 }
5443 }
5444 $b .= '</div>';
5445 }
5446 $b .= '
5447 <ul>
5448 </div>
5449 </div></body></html>';
5450 return $b;
5451 }
5452
5460 public function serialize($debug = 0)
5461 {
5462 $xml = '<?xml version="1.0" encoding="ISO-8859-1"?>';
5463 $xml .= "\n<definitions";
5464 foreach ($this->namespaces as $k => $v) {
5465 $xml .= " xmlns:$k=\"$v\"";
5466 }
5467 // 10.9.02 - add poulter fix for wsdl and tns declarations
5468 if (isset($this->namespaces['wsdl'])) {
5469 $xml .= " xmlns=\"" . $this->namespaces['wsdl'] . "\"";
5470 }
5471 if (isset($this->namespaces['tns'])) {
5472 $xml .= " targetNamespace=\"" . $this->namespaces['tns'] . "\"";
5473 }
5474 $xml .= '>';
5475 // imports
5476 if (sizeof($this->import) > 0) {
5477 foreach ($this->import as $ns => $list) {
5478 foreach ($list as $ii) {
5479 if ($ii['location'] != '') {
5480 $xml .= '<import location="' . $ii['location'] . '" namespace="' . $ns . '" />';
5481 } else {
5482 $xml .= '<import namespace="' . $ns . '" />';
5483 }
5484 }
5485 }
5486 }
5487 // types
5488 if (count($this->schemas) >= 1) {
5489 $xml .= "\n<types>\n";
5490 foreach ($this->schemas as $ns => $list) {
5491 foreach ($list as $xs) {
5492 $xml .= $xs->serializeSchema();
5493 }
5494 }
5495 $xml .= '</types>';
5496 }
5497 // messages
5498 if (count($this->messages) >= 1) {
5499 foreach ($this->messages as $msgName => $msgParts) {
5500 $xml .= "\n<message name=\"" . $msgName . '">';
5501 if (is_array($msgParts)) {
5502 foreach ($msgParts as $partName => $partType) {
5503 // print 'serializing '.$partType.', sv: '.$this->XMLSchemaVersion.'<br>';
5504 if (strpos($partType, ':')) {
5505 $typePrefix = $this->getPrefixFromNamespace($this->getPrefix($partType));
5506 } elseif (isset($this->typemap[$this->namespaces['xsd']][$partType])) {
5507 // print 'checking typemap: '.$this->XMLSchemaVersion.'<br>';
5508 $typePrefix = 'xsd';
5509 } else {
5510 foreach ($this->typemap as $ns => $types) {
5511 if (isset($types[$partType])) {
5512 $typePrefix = $this->getPrefixFromNamespace($ns);
5513 }
5514 }
5515 if (!isset($typePrefix)) {
5516 die("$partType has no namespace!");
5517 }
5518 }
5519 $ns = $this->getNamespaceFromPrefix($typePrefix);
5520 $localPart = $this->getLocalPart($partType);
5521 $typeDef = $this->getTypeDef($localPart, $ns);
5522 if (($typeDef['typeClass'] ?? '') == 'element') {
5523 $elementortype = 'element';
5524 if (substr($localPart, -1) == '^') {
5525 $localPart = substr($localPart, 0, -1);
5526 }
5527 } else {
5528 $elementortype = 'type';
5529 }
5530 $xml .= "\n" . ' <part name="' . $partName . '" ' . $elementortype . '="' . $typePrefix . ':' . $localPart . '" />';
5531 }
5532 }
5533 $xml .= '</message>';
5534 }
5535 }
5536 // bindings & porttypes
5537 if (count($this->bindings) >= 1) {
5538 $binding_xml = '';
5539 $portType_xml = '';
5540 foreach ($this->bindings as $bindingName => $attrs) {
5541 $binding_xml .= "\n<binding name=\"" . $bindingName . '" type="tns:' . $attrs['portType'] . '">';
5542 $binding_xml .= "\n" . ' <soap:binding style="' . $attrs['style'] . '" transport="' . $attrs['transport'] . '"/>';
5543 $portType_xml .= "\n<portType name=\"" . $attrs['portType'] . '">';
5544 foreach ($attrs['operations'] as $opName => $opParts) {
5545 $binding_xml .= "\n" . ' <operation name="' . $opName . '">';
5546 $binding_xml .= "\n" . ' <soap:operation soapAction="' . $opParts['soapAction'] . '" style="' . $opParts['style'] . '"/>';
5547 if (isset($opParts['input']['encodingStyle']) && $opParts['input']['encodingStyle'] != '') {
5548 $enc_style = ' encodingStyle="' . $opParts['input']['encodingStyle'] . '"';
5549 } else {
5550 $enc_style = '';
5551 }
5552 $binding_xml .= "\n" . ' <input><soap:body use="' . $opParts['input']['use'] . '" namespace="' . $opParts['input']['namespace'] . '"' . $enc_style . '/></input>';
5553 if (isset($opParts['output']['encodingStyle']) && $opParts['output']['encodingStyle'] != '') {
5554 $enc_style = ' encodingStyle="' . $opParts['output']['encodingStyle'] . '"';
5555 } else {
5556 $enc_style = '';
5557 }
5558 $binding_xml .= "\n" . ' <output><soap:body use="' . $opParts['output']['use'] . '" namespace="' . $opParts['output']['namespace'] . '"' . $enc_style . '/></output>';
5559 $binding_xml .= "\n" . ' </operation>';
5560 $portType_xml .= "\n" . ' <operation name="' . $opParts['name'] . '"';
5561 if (isset($opParts['parameterOrder'])) {
5562 $portType_xml .= ' parameterOrder="' . $opParts['parameterOrder'] . '"';
5563 }
5564 $portType_xml .= '>';
5565 if (isset($opParts['documentation']) && $opParts['documentation'] != '') {
5566 $portType_xml .= "\n" . ' <documentation>' . htmlspecialchars($opParts['documentation']) . '</documentation>';
5567 }
5568 $portType_xml .= "\n" . ' <input message="tns:' . $opParts['input']['message'] . '"/>';
5569 $portType_xml .= "\n" . ' <output message="tns:' . $opParts['output']['message'] . '"/>';
5570 $portType_xml .= "\n" . ' </operation>';
5571 }
5572 $portType_xml .= "\n" . '</portType>';
5573 $binding_xml .= "\n" . '</binding>';
5574 }
5575 $xml .= $portType_xml . $binding_xml;
5576 }
5577 // services
5578 $xml .= "\n<service name=\"" . $this->serviceName . '">';
5579 $has_client = isset($_GET['client_id']);
5580 if (count($this->ports) >= 1) {
5581 foreach ($this->ports as $pName => $attrs) {
5582 $xml .= "\n" . ' <port name="' . $pName . '" binding="tns:' . $attrs['binding'] . '">';
5583 $locations = $attrs['location'];
5584 $locations = is_array($locations) ? $locations : [$locations];
5585 foreach ($locations as $location) {
5586 $address = $location . ($debug || $has_client ? "?" : "")
5587 . ($debug ? 'debug=1' : '') . ($debug && $has_client ? "&amp;" : "")
5588 . ($has_client ? 'client_id=' . $_GET['client_id'] : '');
5589 $xml .= "\n" . ' <soap:address location="' . $address . '"/>';
5590 }
5591 $xml .= "\n" . ' </port>';
5592 }
5593 }
5594
5595 $xml .= "\n" . '</service>';
5596 return $xml . "\n</definitions>";
5597 }
5598
5608 public function parametersMatchWrapped($type, &$parameters)
5609 {
5610 $this->debug("in parametersMatchWrapped type=$type, parameters=");
5611 $this->appendDebug($this->varDump($parameters));
5612
5613 // split type into namespace:unqualified-type
5614 if (strpos($type, ':')) {
5615 $uqType = substr($type, strrpos($type, ':') + 1);
5616 $ns = substr($type, 0, strrpos($type, ':'));
5617 $this->debug("in parametersMatchWrapped: got a prefixed type: $uqType, $ns");
5618 if ($this->getNamespaceFromPrefix($ns)) {
5619 $ns = $this->getNamespaceFromPrefix($ns);
5620 $this->debug("in parametersMatchWrapped: expanded prefixed type: $uqType, $ns");
5621 }
5622 } else {
5623 // TODO: should the type be compared to types in XSD, and the namespace
5624 // set to XSD if the type matches?
5625 $this->debug("in parametersMatchWrapped: No namespace for type $type");
5626 $ns = '';
5627 $uqType = $type;
5628 }
5629
5630 // get the type information
5631 if (!$typeDef = $this->getTypeDef($uqType, $ns)) {
5632 $this->debug("in parametersMatchWrapped: $type ($uqType) is not a supported type.");
5633 return false;
5634 }
5635 $this->debug("in parametersMatchWrapped: found typeDef=");
5636 $this->appendDebug($this->varDump($typeDef));
5637 if (substr($uqType, -1) == '^') {
5638 $uqType = substr($uqType, 0, -1);
5639 }
5640 $phpType = $typeDef['phpType'];
5641 $arrayType = (isset($typeDef['arrayType']) ? $typeDef['arrayType'] : '');
5642 $this->debug("in parametersMatchWrapped: uqType: $uqType, ns: $ns, phptype: $phpType, arrayType: $arrayType");
5643
5644 // we expect a complexType or element of complexType
5645 if ($phpType != 'struct') {
5646 $this->debug("in parametersMatchWrapped: not a struct");
5647 return false;
5648 }
5649
5650 // see whether the parameter names match the elements
5651 if (isset($typeDef['elements']) && is_array($typeDef['elements'])) {
5652 $elements = 0;
5653 $matches = 0;
5654 $change = false;
5655 if ($this->isArraySimpleOrStruct($parameters) == 'arraySimple' && count($parameters) == count($typeDef['elements'])) {
5656 $this->debug("in parametersMatchWrapped: (wrapped return value kludge) correct number of elements in simple array, so change array and wrap");
5657 $change = true;
5658 }
5659 foreach ($typeDef['elements'] as $name => $attrs) {
5660 if ($change) {
5661 $this->debug("in parametersMatchWrapped: change parameter $element to name $name");
5662 $parameters[$name] = $parameters[$elements];
5663 unset($parameters[$elements]);
5664 $matches++;
5665 } elseif (isset($parameters[$name])) {
5666 $this->debug("in parametersMatchWrapped: have parameter named $name");
5667 $matches++;
5668 } else {
5669 $this->debug("in parametersMatchWrapped: do not have parameter named $name");
5670 }
5671 $elements++;
5672 }
5673
5674 $this->debug("in parametersMatchWrapped: $matches parameter names match $elements wrapped parameter names");
5675 if ($matches == 0) {
5676 return false;
5677 }
5678 return true;
5679 }
5680
5681 // since there are no elements for the type, if the user passed no
5682 // parameters, the parameters match wrapped.
5683 $this->debug("in parametersMatchWrapped: no elements type $ns:$uqType");
5684 return count($parameters) == 0;
5685 }
5686
5702 public function serializeRPCParameters($operation, $direction, $parameters, $bindingType = 'soap')
5703 {
5704 $this->debug("in serializeRPCParameters: operation=$operation, direction=$direction, XMLSchemaVersion=$this->XMLSchemaVersion, bindingType=$bindingType");
5705 $this->appendDebug('parameters=' . $this->varDump($parameters));
5706
5707 if ($direction != 'input' && $direction != 'output') {
5708 $this->debug('The value of the \$direction argument needs to be either "input" or "output"');
5709 $this->setError('The value of the \$direction argument needs to be either "input" or "output"');
5710 return false;
5711 }
5712 if (!$opData = $this->getOperationData($operation, $bindingType)) {
5713 $this->debug('Unable to retrieve WSDL data for operation: ' . $operation . ' bindingType: ' . $bindingType);
5714 $this->setError('Unable to retrieve WSDL data for operation: ' . $operation . ' bindingType: ' . $bindingType);
5715 return false;
5716 }
5717 $this->debug('in serializeRPCParameters: opData:');
5718 $this->appendDebug($this->varDump($opData));
5719
5720 // Get encoding style for output and set to current
5721 $encodingStyle = 'http://schemas.xmlsoap.org/soap/encoding/';
5722 if (($direction == 'input') && isset($opData['output']['encodingStyle']) && ($opData['output']['encodingStyle'] != $encodingStyle)) {
5723 $encodingStyle = $opData['output']['encodingStyle'];
5724 $enc_style = $encodingStyle;
5725 }
5726
5727 // set input params
5728 $xml = '';
5729 if (isset($opData[$direction]['parts']) && sizeof($opData[$direction]['parts']) > 0) {
5730 $parts = &$opData[$direction]['parts'];
5731 $part_count = sizeof($parts);
5732 $style = $opData['style'];
5733 $use = $opData[$direction]['use'];
5734 $this->debug("have $part_count part(s) to serialize using $style/$use");
5735 if (is_array($parameters)) {
5736 $parametersArrayType = $this->isArraySimpleOrStruct($parameters);
5737 $parameter_count = count($parameters);
5738 $this->debug("have $parameter_count parameter(s) provided as $parametersArrayType to serialize");
5739 // check for Microsoft-style wrapped parameters
5740 if ($style == 'document' && $use == 'literal' && $part_count == 1 && isset($parts['parameters'])) {
5741 $this->debug('check whether the caller has wrapped the parameters');
5742 if ((($parametersArrayType == 'arrayStruct' || $parameter_count == 0) && !isset($parameters['parameters'])) || ($direction == 'output' && $parametersArrayType == 'arraySimple' && $parameter_count == 1)) {
5743 $this->debug('check whether caller\'s parameters match the wrapped ones');
5744 if ($this->parametersMatchWrapped($parts['parameters'], $parameters)) {
5745 $this->debug('wrap the parameters for the caller');
5746 $parameters = array('parameters' => $parameters);
5747 $parameter_count = 1;
5748 }
5749 }
5750 }
5751 foreach ($parts as $name => $type) {
5752 $this->debug("serializing part $name of type $type");
5753 // Track encoding style
5754 if (isset($opData[$direction]['encodingStyle']) && $encodingStyle != $opData[$direction]['encodingStyle']) {
5755 $encodingStyle = $opData[$direction]['encodingStyle'];
5756 $enc_style = $encodingStyle;
5757 } else {
5758 $enc_style = false;
5759 }
5760 // NOTE: add error handling here
5761 // if serializeType returns false, then catch global error and fault
5762 if ($parametersArrayType == 'arraySimple') {
5763 $p = array_shift($parameters);
5764 $this->debug('calling serializeType w/indexed param');
5765 $xml .= $this->serializeType($name, $type, $p, $use, $enc_style);
5766 } elseif (isset($parameters[$name])) {
5767 $this->debug('calling serializeType w/named param');
5768 $xml .= $this->serializeType($name, $type, $parameters[$name], $use, $enc_style);
5769 } else {
5770 // TODO: only send nillable
5771 $this->debug('calling serializeType w/null param');
5772 $xml .= $this->serializeType($name, $type, null, $use, $enc_style);
5773 }
5774 }
5775 } else {
5776 $this->debug('no parameters passed.');
5777 }
5778 }
5779 $this->debug("serializeRPCParameters returning: $xml");
5780 return $xml;
5781 }
5782
5797 public function serializeParameters($operation, $direction, $parameters)
5798 {
5799 $this->debug("in serializeParameters: operation=$operation, direction=$direction, XMLSchemaVersion=$this->XMLSchemaVersion");
5800 $this->appendDebug('parameters=' . $this->varDump($parameters));
5801
5802 if ($direction != 'input' && $direction != 'output') {
5803 $this->debug('The value of the \$direction argument needs to be either "input" or "output"');
5804 $this->setError('The value of the \$direction argument needs to be either "input" or "output"');
5805 return false;
5806 }
5807 if (!$opData = $this->getOperationData($operation)) {
5808 $this->debug('Unable to retrieve WSDL data for operation: ' . $operation);
5809 $this->setError('Unable to retrieve WSDL data for operation: ' . $operation);
5810 return false;
5811 }
5812 $this->debug('opData:');
5813 $this->appendDebug($this->varDump($opData));
5814
5815 // Get encoding style for output and set to current
5816 $encodingStyle = 'http://schemas.xmlsoap.org/soap/encoding/';
5817 if (($direction == 'input') && isset($opData['output']['encodingStyle']) && ($opData['output']['encodingStyle'] != $encodingStyle)) {
5818 $encodingStyle = $opData['output']['encodingStyle'];
5819 $enc_style = $encodingStyle;
5820 }
5821
5822 // set input params
5823 $xml = '';
5824 if (isset($opData[$direction]['parts']) && sizeof($opData[$direction]['parts']) > 0) {
5825 $use = $opData[$direction]['use'];
5826 $this->debug("use=$use");
5827 $this->debug('got ' . count($opData[$direction]['parts']) . ' part(s)');
5828 if (is_array($parameters)) {
5829 $parametersArrayType = $this->isArraySimpleOrStruct($parameters);
5830 $this->debug('have ' . $parametersArrayType . ' parameters');
5831 foreach ($opData[$direction]['parts'] as $name => $type) {
5832 $this->debug('serializing part "' . $name . '" of type "' . $type . '"');
5833 // Track encoding style
5834 if (isset($opData[$direction]['encodingStyle']) && $encodingStyle != $opData[$direction]['encodingStyle']) {
5835 $encodingStyle = $opData[$direction]['encodingStyle'];
5836 $enc_style = $encodingStyle;
5837 } else {
5838 $enc_style = false;
5839 }
5840 // NOTE: add error handling here
5841 // if serializeType returns false, then catch global error and fault
5842 if ($parametersArrayType == 'arraySimple') {
5843 $p = array_shift($parameters);
5844 $this->debug('calling serializeType w/indexed param');
5845 $xml .= $this->serializeType($name, $type, $p, $use, $enc_style);
5846 } elseif (isset($parameters[$name])) {
5847 $this->debug('calling serializeType w/named param');
5848 $xml .= $this->serializeType($name, $type, $parameters[$name], $use, $enc_style);
5849 } else {
5850 // TODO: only send nillable
5851 $this->debug('calling serializeType w/null param');
5852 $xml .= $this->serializeType($name, $type, null, $use, $enc_style);
5853 }
5854 }
5855 } else {
5856 $this->debug('no parameters passed.');
5857 }
5858 }
5859 $this->debug("serializeParameters returning: $xml");
5860 return $xml;
5861 }
5862
5875 public function serializeType($name, $type, $value, $use = 'encoded', $encodingStyle = false, $unqualified = false)
5876 {
5877 $this->debug("in serializeType: name=$name, type=$type, use=$use, encodingStyle=$encodingStyle, unqualified=" . ($unqualified ? "unqualified" : "qualified"));
5878 $this->appendDebug("value=" . $this->varDump($value));
5879 if ($use == 'encoded' && $encodingStyle) {
5880 $encodingStyle = ' SOAP-ENV:encodingStyle="' . $encodingStyle . '"';
5881 }
5882
5883 // if a soapval has been supplied, let its type override the WSDL
5884 if (is_object($value) && get_class($value) == 'soapval') {
5885 if ($value->type_ns) {
5886 $type = $value->type_ns . ':' . $value->type;
5887 $forceType = true;
5888 $this->debug("in serializeType: soapval overrides type to $type");
5889 } elseif ($value->type) {
5890 $type = $value->type;
5891 $forceType = true;
5892 $this->debug("in serializeType: soapval overrides type to $type");
5893 } else {
5894 $forceType = false;
5895 $this->debug("in serializeType: soapval does not override type");
5896 }
5897 $attrs = $value->attributes;
5898 $value = $value->value;
5899 $this->debug("in serializeType: soapval overrides value to $value");
5900 if ($attrs) {
5901 if (!is_array($value)) {
5902 $value['!'] = $value;
5903 }
5904 foreach ($attrs as $n => $v) {
5905 $value['!' . $n] = $v;
5906 }
5907 $this->debug("in serializeType: soapval provides attributes");
5908 }
5909 } else {
5910 $forceType = false;
5911 }
5912
5913 $xml = '';
5914 if (strpos($type, ':')) {
5915 $uqType = substr($type, strrpos($type, ':') + 1);
5916 $ns = substr($type, 0, strrpos($type, ':'));
5917 $this->debug("in serializeType: got a prefixed type: $uqType, $ns");
5918 if ($this->getNamespaceFromPrefix($ns)) {
5919 $ns = $this->getNamespaceFromPrefix($ns);
5920 $this->debug("in serializeType: expanded prefixed type: $uqType, $ns");
5921 }
5922
5923 if ($ns == $this->XMLSchemaVersion || $ns == 'http://schemas.xmlsoap.org/soap/encoding/') {
5924 $this->debug('in serializeType: type namespace indicates XML Schema or SOAP Encoding type');
5925 if ($unqualified && $use == 'literal') {
5926 $elementNS = " xmlns=\"\"";
5927 } else {
5928 $elementNS = '';
5929 }
5930 if (is_null($value)) {
5931 if ($use == 'literal') {
5932 // TODO: depends on minOccurs
5933 $xml = "<$name$elementNS/>";
5934 } else {
5935 // TODO: depends on nillable, which should be checked before calling this method
5936 $xml = "<$name$elementNS xsi:nil=\"true\" xsi:type=\"" . $this->getPrefixFromNamespace($ns) . ":$uqType\"/>";
5937 }
5938 $this->debug("in serializeType: returning: $xml");
5939 return $xml;
5940 }
5941 if ($uqType == 'Array') {
5942 // JBoss/Axis does this sometimes
5943 return $this->serialize_val($value, $name, false, false, false, false, $use);
5944 }
5945 if ($uqType == 'boolean') {
5946 if ((is_string($value) && $value == 'false') || (! $value)) {
5947 $value = 'false';
5948 } else {
5949 $value = 'true';
5950 }
5951 }
5952 if ($uqType == 'string' && gettype($value) == 'string') {
5953 $value = $this->expandEntities($value);
5954 }
5955 if (($uqType == 'long' || $uqType == 'unsignedLong') && gettype($value) == 'double') {
5956 $value = sprintf("%.0lf", $value);
5957 }
5958 // it's a scalar
5959 // TODO: what about null/nil values?
5960 // check type isn't a custom type extending xmlschema namespace
5961 if (!$this->getTypeDef($uqType, $ns)) {
5962 if ($use == 'literal') {
5963 if ($forceType) {
5964 $xml = "<$name$elementNS xsi:type=\"" . $this->getPrefixFromNamespace($ns) . ":$uqType\">$value</$name>";
5965 } else {
5966 $xml = "<$name$elementNS>$value</$name>";
5967 }
5968 } else {
5969 $xml = "<$name$elementNS xsi:type=\"" . $this->getPrefixFromNamespace($ns) . ":$uqType\"$encodingStyle>$value</$name>";
5970 }
5971 $this->debug("in serializeType: returning: $xml");
5972 return $xml;
5973 }
5974 $this->debug('custom type extends XML Schema or SOAP Encoding namespace (yuck)');
5975 } elseif ($ns == 'http://xml.apache.org/xml-soap') {
5976 $this->debug('in serializeType: appears to be Apache SOAP type');
5977 if ($uqType == 'Map') {
5978 $tt_prefix = $this->getPrefixFromNamespace('http://xml.apache.org/xml-soap');
5979 if (! $tt_prefix) {
5980 $this->debug('in serializeType: Add namespace for Apache SOAP type');
5981 $tt_prefix = 'ns' . rand(1000, 9999);
5982 $this->namespaces[$tt_prefix] = 'http://xml.apache.org/xml-soap';
5983 // force this to be added to usedNamespaces
5984 $tt_prefix = $this->getPrefixFromNamespace('http://xml.apache.org/xml-soap');
5985 }
5986 $contents = '';
5987 foreach ($value as $k => $v) {
5988 $this->debug("serializing map element: key $k, value $v");
5989 $contents .= '<item>';
5990 $contents .= $this->serialize_val($k, 'key', false, false, false, false, $use);
5991 $contents .= $this->serialize_val($v, 'value', false, false, false, false, $use);
5992 $contents .= '</item>';
5993 }
5994 if ($use == 'literal') {
5995 if ($forceType) {
5996 $xml = "<$name xsi:type=\"" . $tt_prefix . ":$uqType\">$contents</$name>";
5997 } else {
5998 $xml = "<$name>$contents</$name>";
5999 }
6000 } else {
6001 $xml = "<$name xsi:type=\"" . $tt_prefix . ":$uqType\"$encodingStyle>$contents</$name>";
6002 }
6003 $this->debug("in serializeType: returning: $xml");
6004 return $xml;
6005 }
6006 $this->debug('in serializeType: Apache SOAP type, but only support Map');
6007 }
6008 } else {
6009 // TODO: should the type be compared to types in XSD, and the namespace
6010 // set to XSD if the type matches?
6011 $this->debug("in serializeType: No namespace for type $type");
6012 $ns = '';
6013 $uqType = $type;
6014 }
6015 if (!$typeDef = $this->getTypeDef($uqType, $ns)) {
6016 $this->setError("$type ($uqType) is not a supported type.");
6017 $this->debug("in serializeType: $type ($uqType) is not a supported type.");
6018 return false;
6019 } else {
6020 $this->debug("in serializeType: found typeDef");
6021 $this->appendDebug('typeDef=' . $this->varDump($typeDef));
6022 if (substr($uqType, -1) == '^') {
6023 $uqType = substr($uqType, 0, -1);
6024 }
6025 }
6026 $phpType = $typeDef['phpType'];
6027 $this->debug("in serializeType: uqType: $uqType, ns: $ns, phptype: $phpType, arrayType: " . (isset($typeDef['arrayType']) ? $typeDef['arrayType'] : ''));
6028 // if php type == struct, map value to the <all> element names
6029 if ($phpType == 'struct') {
6030 if (isset($typeDef['typeClass']) && $typeDef['typeClass'] == 'element') {
6031 $elementName = $uqType;
6032 if (isset($typeDef['form']) && ($typeDef['form'] == 'qualified')) {
6033 $elementNS = " xmlns=\"$ns\"";
6034 } else {
6035 $elementNS = " xmlns=\"\"";
6036 }
6037 } else {
6038 $elementName = $name;
6039 if ($unqualified) {
6040 $elementNS = " xmlns=\"\"";
6041 } else {
6042 $elementNS = '';
6043 }
6044 }
6045 if (is_null($value)) {
6046 if ($use == 'literal') {
6047 // TODO: depends on minOccurs
6048 $xml = "<$elementName$elementNS/>";
6049 } else {
6050 $xml = "<$elementName$elementNS xsi:nil=\"true\" xsi:type=\"" . $this->getPrefixFromNamespace($ns) . ":$uqType\"/>";
6051 }
6052 $this->debug("in serializeType: returning: $xml");
6053 return $xml;
6054 }
6055 if (is_object($value)) {
6056 $value = get_object_vars($value);
6057 }
6058 if (is_array($value)) {
6059 $elementAttrs = $this->serializeComplexTypeAttributes($typeDef, $value, $ns, $uqType);
6060 if ($use == 'literal') {
6061 if ($forceType) {
6062 $xml = "<$elementName$elementNS$elementAttrs xsi:type=\"" . $this->getPrefixFromNamespace($ns) . ":$uqType\">";
6063 } else {
6064 $xml = "<$elementName$elementNS$elementAttrs>";
6065 }
6066 } else {
6067 $xml = "<$elementName$elementNS$elementAttrs xsi:type=\"" . $this->getPrefixFromNamespace($ns) . ":$uqType\"$encodingStyle>";
6068 }
6069
6070 $xml .= $this->serializeComplexTypeElements($typeDef, $value, $ns, $uqType, $use, $encodingStyle);
6071 $xml .= "</$elementName>";
6072 } else {
6073 $this->debug("in serializeType: phpType is struct, but value is not an array");
6074 $this->setError("phpType is struct, but value is not an array: see debug output for details");
6075 $xml = '';
6076 }
6077 } elseif ($phpType == 'array') {
6078 if (isset($typeDef['form']) && ($typeDef['form'] == 'qualified')) {
6079 $elementNS = " xmlns=\"$ns\"";
6080 } else {
6081 if ($unqualified) {
6082 $elementNS = " xmlns=\"\"";
6083 } else {
6084 $elementNS = '';
6085 }
6086 }
6087 if (is_null($value)) {
6088 if ($use == 'literal') {
6089 // TODO: depends on minOccurs
6090 $xml = "<$name$elementNS/>";
6091 } else {
6092 $xml = "<$name$elementNS xsi:nil=\"true\" xsi:type=\"" .
6093 $this->getPrefixFromNamespace('http://schemas.xmlsoap.org/soap/encoding/') .
6094 ":Array\" " .
6095 $this->getPrefixFromNamespace('http://schemas.xmlsoap.org/soap/encoding/') .
6096 ':arrayType="' .
6097 $this->getPrefixFromNamespace($this->getPrefix($typeDef['arrayType'])) .
6098 ':' .
6099 $this->getLocalPart($typeDef['arrayType']) . "[0]\"/>";
6100 }
6101 $this->debug("in serializeType: returning: $xml");
6102 return $xml;
6103 }
6104 if (isset($typeDef['multidimensional'])) {
6105 $nv = array();
6106 foreach ($value as $v) {
6107 $cols = ',' . sizeof($v);
6108 $nv = array_merge($nv, $v);
6109 }
6110 $value = $nv;
6111 } else {
6112 $cols = '';
6113 }
6114 if (is_array($value) && sizeof($value) >= 1) {
6115 $rows = sizeof($value);
6116 $contents = '';
6117 foreach ($value as $k => $v) {
6118 $this->debug("serializing array element: $k, $v of type: $typeDef[arrayType]");
6119 //if (strpos($typeDef['arrayType'], ':') ) {
6120 if (!in_array($typeDef['arrayType'], $this->typemap['http://www.w3.org/2001/XMLSchema'])) {
6121 $contents .= $this->serializeType('item', $typeDef['arrayType'], $v, $use);
6122 } else {
6123 $contents .= $this->serialize_val($v, 'item', $typeDef['arrayType'], null, $this->XMLSchemaVersion, false, $use);
6124 }
6125 }
6126 } else {
6127 $rows = 0;
6128 $contents = null;
6129 }
6130 // TODO: for now, an empty value will be serialized as a zero element
6131 // array. Revisit this when coding the handling of null/nil values.
6132 if ($use == 'literal') {
6133 $xml = "<$name$elementNS>"
6134 . $contents
6135 . "</$name>";
6136 } else {
6137 $xml = "<$name$elementNS xsi:type=\"" . $this->getPrefixFromNamespace('http://schemas.xmlsoap.org/soap/encoding/') . ':Array" ' .
6138 $this->getPrefixFromNamespace('http://schemas.xmlsoap.org/soap/encoding/')
6139 . ':arrayType="'
6140 . $this->getPrefixFromNamespace($this->getPrefix($typeDef['arrayType']))
6141 . ":" . $this->getLocalPart($typeDef['arrayType']) . "[$rows$cols]\">"
6142 . $contents
6143 . "</$name>";
6144 }
6145 } elseif ($phpType == 'scalar') {
6146 if (isset($typeDef['form']) && ($typeDef['form'] == 'qualified')) {
6147 $elementNS = " xmlns=\"$ns\"";
6148 } else {
6149 if ($unqualified) {
6150 $elementNS = " xmlns=\"\"";
6151 } else {
6152 $elementNS = '';
6153 }
6154 }
6155 if ($use == 'literal') {
6156 if ($forceType) {
6157 $xml = "<$name$elementNS xsi:type=\"" . $this->getPrefixFromNamespace($ns) . ":$uqType\">$value</$name>";
6158 } else {
6159 $xml = "<$name$elementNS>$value</$name>";
6160 }
6161 } else {
6162 $xml = "<$name$elementNS xsi:type=\"" . $this->getPrefixFromNamespace($ns) . ":$uqType\"$encodingStyle>$value</$name>";
6163 }
6164 }
6165 $this->debug("in serializeType: returning: $xml");
6166 return $xml;
6167 }
6168
6179 public function serializeComplexTypeAttributes($typeDef, $value, $ns, $uqType)
6180 {
6181 $xml = '';
6182 if (isset($typeDef['attrs']) && is_array($typeDef['attrs'])) {
6183 $this->debug("serialize attributes for XML Schema type $ns:$uqType");
6184 if (is_array($value)) {
6185 $xvalue = $value;
6186 } elseif (is_object($value)) {
6187 $xvalue = get_object_vars($value);
6188 } else {
6189 $this->debug("value is neither an array nor an object for XML Schema type $ns:$uqType");
6190 $xvalue = array();
6191 }
6192 foreach ($typeDef['attrs'] as $aName => $attrs) {
6193 if (isset($xvalue['!' . $aName])) {
6194 $xname = '!' . $aName;
6195 $this->debug("value provided for attribute $aName with key $xname");
6196 } elseif (isset($xvalue[$aName])) {
6197 $xname = $aName;
6198 $this->debug("value provided for attribute $aName with key $xname");
6199 } elseif (isset($attrs['default'])) {
6200 $xname = '!' . $aName;
6201 $xvalue[$xname] = $attrs['default'];
6202 $this->debug('use default value of ' . $xvalue[$aName] . ' for attribute ' . $aName);
6203 } else {
6204 $xname = '';
6205 $this->debug("no value provided for attribute $aName");
6206 }
6207 if ($xname) {
6208 $xml .= " $aName=\"" . $this->expandEntities($xvalue[$xname]) . "\"";
6209 }
6210 }
6211 } else {
6212 $this->debug("no attributes to serialize for XML Schema type $ns:$uqType");
6213 }
6214 if (isset($typeDef['extensionBase'])) {
6215 $ns = $this->getPrefix($typeDef['extensionBase']);
6216 $uqType = $this->getLocalPart($typeDef['extensionBase']);
6217 if ($this->getNamespaceFromPrefix($ns)) {
6218 $ns = $this->getNamespaceFromPrefix($ns);
6219 }
6220 if ($typeDef = $this->getTypeDef($uqType, $ns)) {
6221 $this->debug("serialize attributes for extension base $ns:$uqType");
6222 $xml .= $this->serializeComplexTypeAttributes($typeDef, $value, $ns, $uqType);
6223 } else {
6224 $this->debug("extension base $ns:$uqType is not a supported type");
6225 }
6226 }
6227 return $xml;
6228 }
6229
6242 public function serializeComplexTypeElements($typeDef, $value, $ns, $uqType, $use = 'encoded', $encodingStyle = false)
6243 {
6244 $xml = '';
6245 if (isset($typeDef['elements']) && is_array($typeDef['elements'])) {
6246 $this->debug("in serializeComplexTypeElements, serialize elements for XML Schema type $ns:$uqType");
6247 if (is_array($value)) {
6248 $xvalue = $value;
6249 } elseif (is_object($value)) {
6250 $xvalue = get_object_vars($value);
6251 } else {
6252 $this->debug("value is neither an array nor an object for XML Schema type $ns:$uqType");
6253 $xvalue = array();
6254 }
6255 // toggle whether all elements are present - ideally should validate against schema
6256 if (count($typeDef['elements']) != count($xvalue)) {
6257 $optionals = true;
6258 }
6259 foreach ($typeDef['elements'] as $eName => $attrs) {
6260 if (!isset($xvalue[$eName])) {
6261 if (isset($attrs['default'])) {
6262 $xvalue[$eName] = $attrs['default'];
6263 $this->debug('use default value of ' . $xvalue[$eName] . ' for element ' . $eName);
6264 }
6265 }
6266 // if user took advantage of a minOccurs=0, then only serialize named parameters
6267 if (isset($optionals)
6268 && (!isset($xvalue[$eName]))
6269 && ((!isset($attrs['nillable'])) || $attrs['nillable'] != 'true')
6270 ) {
6271 if (isset($attrs['minOccurs']) && $attrs['minOccurs'] <> '0') {
6272 $this->debug("apparent error: no value provided for element $eName with minOccurs=" . $attrs['minOccurs']);
6273 }
6274 // do nothing
6275 $this->debug("no value provided for complexType element $eName and element is not nillable, so serialize nothing");
6276 } else {
6277 // get value
6278 if (isset($xvalue[$eName])) {
6279 $v = $xvalue[$eName];
6280 } else {
6281 $v = null;
6282 }
6283 if (isset($attrs['form'])) {
6284 $unqualified = ($attrs['form'] == 'unqualified');
6285 } else {
6286 $unqualified = false;
6287 }
6288 if (isset($attrs['maxOccurs']) && ($attrs['maxOccurs'] == 'unbounded' || $attrs['maxOccurs'] > 1) && isset($v) && is_array($v) && $this->isArraySimpleOrStruct($v) == 'arraySimple') {
6289 $vv = $v;
6290 foreach ($vv as $k => $v) {
6291 if (isset($attrs['type']) || isset($attrs['ref'])) {
6292 // serialize schema-defined type
6293 $xml .= $this->serializeType($eName, isset($attrs['type']) ? $attrs['type'] : $attrs['ref'], $v, $use, $encodingStyle, $unqualified);
6294 } else {
6295 // serialize generic type (can this ever really happen?)
6296 $this->debug("calling serialize_val() for $v, $eName, false, false, false, false, $use");
6297 $xml .= $this->serialize_val($v, $eName, false, false, false, false, $use);
6298 }
6299 }
6300 } else {
6301 if (isset($attrs['type']) || isset($attrs['ref'])) {
6302 // serialize schema-defined type
6303 $xml .= $this->serializeType($eName, isset($attrs['type']) ? $attrs['type'] : $attrs['ref'], $v, $use, $encodingStyle, $unqualified);
6304 } else {
6305 // serialize generic type (can this ever really happen?)
6306 $this->debug("calling serialize_val() for $v, $eName, false, false, false, false, $use");
6307 $xml .= $this->serialize_val($v, $eName, false, false, false, false, $use);
6308 }
6309 }
6310 }
6311 }
6312 } else {
6313 $this->debug("no elements to serialize for XML Schema type $ns:$uqType");
6314 }
6315 if (isset($typeDef['extensionBase'])) {
6316 $ns = $this->getPrefix($typeDef['extensionBase']);
6317 $uqType = $this->getLocalPart($typeDef['extensionBase']);
6318 if ($this->getNamespaceFromPrefix($ns)) {
6319 $ns = $this->getNamespaceFromPrefix($ns);
6320 }
6321 if ($typeDef = $this->getTypeDef($uqType, $ns)) {
6322 $this->debug("serialize elements for extension base $ns:$uqType");
6323 $xml .= $this->serializeComplexTypeElements($typeDef, $value, $ns, $uqType, $use, $encodingStyle);
6324 } else {
6325 $this->debug("extension base $ns:$uqType is not a supported type");
6326 }
6327 }
6328 return $xml;
6329 }
6330
6345 public function addComplexType($name, $typeClass = 'complexType', $phpType = 'array', $compositor = '', $restrictionBase = '', $elements = array(), $attrs = array(), $arrayType = '')
6346 {
6347 if (count($elements) > 0) {
6348 $eElements = array();
6349 foreach ($elements as $n => $e) {
6350 // expand each element
6351 $ee = array();
6352 foreach ($e as $k => $v) {
6353 $k = strpos($k, ':') ? $this->expandQname($k) : $k;
6354 $v = strpos($v, ':') ? $this->expandQname($v) : $v;
6355 $ee[$k] = $v;
6356 }
6357 $eElements[$n] = $ee;
6358 }
6359 $elements = $eElements;
6360 }
6361
6362 if (count($attrs) > 0) {
6363 foreach ($attrs as $n => $a) {
6364 // expand each attribute
6365 foreach ($a as $k => $v) {
6366 $k = strpos($k, ':') ? $this->expandQname($k) : $k;
6367 $v = strpos($v, ':') ? $this->expandQname($v) : $v;
6368 $aa[$k] = $v;
6369 }
6370 $eAttrs[$n] = $aa;
6371 }
6372 $attrs = $eAttrs;
6373 }
6374
6375 $restrictionBase = strpos($restrictionBase, ':') ? $this->expandQname($restrictionBase) : $restrictionBase;
6376 $arrayType = strpos($arrayType, ':') ? $this->expandQname($arrayType) : $arrayType;
6377
6378 $typens = isset($this->namespaces['types']) ? $this->namespaces['types'] : $this->namespaces['tns'];
6379 $this->schemas[$typens][0]->addComplexType($name, $typeClass, $phpType, $compositor, $restrictionBase, $elements, $attrs, $arrayType);
6380 }
6381
6393 public function addSimpleType($name, $restrictionBase = '', $typeClass = 'simpleType', $phpType = 'scalar', $enumeration = array())
6394 {
6395 $restrictionBase = strpos($restrictionBase, ':') ? $this->expandQname($restrictionBase) : $restrictionBase;
6396
6397 $typens = isset($this->namespaces['types']) ? $this->namespaces['types'] : $this->namespaces['tns'];
6398 $this->schemas[$typens][0]->addSimpleType($name, $restrictionBase, $typeClass, $phpType, $enumeration);
6399 }
6400
6408 public function addElement($attrs)
6409 {
6410 $typens = isset($this->namespaces['types']) ? $this->namespaces['types'] : $this->namespaces['tns'];
6411 $this->schemas[$typens][0]->addElement($attrs);
6412 }
6413
6428 public function addOperation($name, $in = false, $out = false, $namespace = false, $soapaction = false, $style = 'rpc', $use = 'encoded', $documentation = '', $encodingStyle = '')
6429 {
6430 if ($use == 'encoded' && $encodingStyle == '') {
6431 $encodingStyle = 'http://schemas.xmlsoap.org/soap/encoding/';
6432 }
6433
6434 if ($style == 'document') {
6435 $elements = array();
6436 foreach ($in as $n => $t) {
6437 $elements[$n] = array('name' => $n, 'type' => $t);
6438 }
6439 $this->addComplexType($name . 'RequestType', 'complexType', 'struct', 'all', '', $elements);
6440 $this->addElement(array('name' => $name, 'type' => $name . 'RequestType'));
6441 $in = array('parameters' => 'tns:' . $name . '^');
6442
6443 $elements = array();
6444 foreach ($out as $n => $t) {
6445 $elements[$n] = array('name' => $n, 'type' => $t);
6446 }
6447 $this->addComplexType($name . 'ResponseType', 'complexType', 'struct', 'all', '', $elements);
6448 $this->addElement(array('name' => $name . 'Response', 'type' => $name . 'ResponseType', 'form' => 'qualified'));
6449 $out = array('parameters' => 'tns:' . $name . 'Response' . '^');
6450 }
6451
6452 // get binding
6453 $this->bindings[ $this->serviceName . 'Binding' ]['operations'][$name] =
6454 array(
6455 'name' => $name,
6456 'binding' => $this->serviceName . 'Binding',
6457 'endpoint' => $this->endpoint,
6458 'soapAction' => $soapaction,
6459 'style' => $style,
6460 'input' => array(
6461 'use' => $use,
6462 'namespace' => $namespace,
6463 'encodingStyle' => $encodingStyle,
6464 'message' => $name . 'Request',
6465 'parts' => $in),
6466 'output' => array(
6467 'use' => $use,
6468 'namespace' => $namespace,
6469 'encodingStyle' => $encodingStyle,
6470 'message' => $name . 'Response',
6471 'parts' => $out),
6472 'namespace' => $namespace,
6473 'transport' => 'http://schemas.xmlsoap.org/soap/http',
6474 'documentation' => $documentation);
6475 // add portTypes
6476 // add messages
6477 if ($in) {
6478 foreach ($in as $pName => $pType) {
6479 if (strpos($pType, ':')) {
6480 $pType = $this->getNamespaceFromPrefix($this->getPrefix($pType)) . ":" . $this->getLocalPart($pType);
6481 }
6482 $this->messages[$name . 'Request'][$pName] = $pType;
6483 }
6484 } else {
6485 $this->messages[$name . 'Request'] = '0';
6486 }
6487 if ($out) {
6488 foreach ($out as $pName => $pType) {
6489 if (strpos($pType, ':')) {
6490 $pType = $this->getNamespaceFromPrefix($this->getPrefix($pType)) . ":" . $this->getLocalPart($pType);
6491 }
6492 $this->messages[$name . 'Response'][$pName] = $pType;
6493 }
6494 } else {
6495 $this->messages[$name . 'Response'] = '0';
6496 }
6497 return true;
6498 }
6499}
6500?><?php
6501
6502
6503
6514{
6516 public $parser;
6517 public $xml = '';
6518 public $xml_encoding = '';
6519 public $method = '';
6520 public $root_struct = '';
6523 public $root_header = '';
6524 public $document = ''; // incoming SOAP body (text)
6525 // determines where in the message we are (envelope,header,body,method)
6526 public $status = '';
6527 public $position = 0;
6528 public $depth = 0;
6530 public $namespaces = array();
6531 public $message = array();
6532 public $parent = '';
6533 public $fault = false;
6534 public $fault_code = '';
6535 public $fault_str = '';
6536 public $fault_detail = '';
6537 public $depth_array = array();
6538 public $debug_flag = true;
6539 public $soapresponse = null; // parsed SOAP Body
6540 public $soapheader = null; // parsed SOAP Header
6541 public $responseHeaders = ''; // incoming SOAP headers (text)
6542 public $body_position = 0;
6543 // for multiref parsing:
6544 // array of id => pos
6545 public $ids = array();
6546 // array of id => hrefs => pos
6547 public $multirefs = array();
6548 // toggle for auto-decoding element content
6549 public $decode_utf8 = true;
6550
6560 public function __construct($xml, $encoding = 'UTF-8', $method = '', $decode_utf8 = true)
6561 {
6563 $this->xml = $xml;
6564 $this->xml_encoding = $encoding;
6565 $this->method = $method;
6566 $this->decode_utf8 = $decode_utf8;
6567
6568 // Check whether content has been read.
6569 if (!empty($xml)) {
6570 // Check XML encoding
6571 $pos_xml = strpos($xml, '<?xml');
6572 if ($pos_xml !== false) {
6573 $xml_decl = substr($xml, $pos_xml, strpos($xml, '?>', $pos_xml + 2) - $pos_xml + 1);
6574 if (preg_match("/encoding=[\"']([^\"']*)[\"']/", $xml_decl, $res)) {
6575 $xml_encoding = $res[1];
6576 if (strtoupper($xml_encoding) != $encoding) {
6577 $err = "Charset from HTTP Content-Type '" . $encoding . "' does not match encoding from XML declaration '" . $xml_encoding . "'";
6578 $this->debug($err);
6579 if ($encoding != 'ISO-8859-1' || strtoupper($xml_encoding) != 'UTF-8') {
6580 $this->setError($err);
6581 return;
6582 }
6583 // when HTTP says ISO-8859-1 (the default) and XML says UTF-8 (the typical), assume the other endpoint is just sloppy and proceed
6584 } else {
6585 $this->debug('Charset from HTTP Content-Type matches encoding from XML declaration');
6586 }
6587 } else {
6588 $this->debug('No encoding specified in XML declaration');
6589 }
6590 } else {
6591 $this->debug('No XML declaration');
6592 }
6593 $this->debug('Entering nusoap_parser(), length=' . strlen($xml) . ', encoding=' . $encoding);
6594 // Create an XML parser - why not xml_parser_create_ns?
6595 $this->parser = xml_parser_create($this->xml_encoding);
6596 // Set the options for parsing the XML data.
6597 //xml_parser_set_option($parser, XML_OPTION_SKIP_WHITE, 1);
6598 xml_parser_set_option($this->parser, XML_OPTION_CASE_FOLDING, 0);
6599 xml_parser_set_option($this->parser, XML_OPTION_TARGET_ENCODING, $this->xml_encoding);
6600 // Set the object for the parser.
6601 // Set the element handlers for the parser.
6602 xml_set_element_handler($this->parser, $this->start_element(...), $this->end_element(...));
6603 xml_set_character_data_handler($this->parser, $this->character_data(...));
6604
6605 // Parse the XML file.
6606 if (!xml_parse($this->parser, $xml, true)) {
6607 // Display an error message.
6608 $err = sprintf(
6609 'XML error parsing SOAP payload on line %d: %s',
6610 xml_get_current_line_number($this->parser),
6611 xml_error_string(xml_get_error_code($this->parser))
6612 );
6613 $this->debug($err);
6614 $this->debug("XML payload:\n" . $xml);
6615 $this->setError($err);
6616 } else {
6617 $this->debug('parsed successfully, found root struct: ' . $this->root_struct . ' of name ' . $this->root_struct_name);
6618 // get final value
6619 $this->soapresponse = $this->message[$this->root_struct]['result'];
6620 // get header value
6621 if ($this->root_header != '' && isset($this->message[$this->root_header]['result'])) {
6622 $this->soapheader = $this->message[$this->root_header]['result'];
6623 }
6624 // resolve hrefs/ids
6625 if (sizeof($this->multirefs) > 0) {
6626 foreach ($this->multirefs as $id => $hrefs) {
6627 $this->debug('resolving multirefs for id: ' . $id);
6628 $idVal = $this->buildVal($this->ids[$id]);
6629 if (is_array($idVal) && isset($idVal['!id'])) {
6630 unset($idVal['!id']);
6631 }
6632 foreach ($hrefs as $refPos => $ref) {
6633 $this->debug('resolving href at pos ' . $refPos);
6634 $this->multirefs[$id][$refPos] = $idVal;
6635 }
6636 }
6637 }
6638 }
6639 } else {
6640 $this->debug('xml was empty, didn\'t parse!');
6641 $this->setError('xml was empty, didn\'t parse!');
6642 }
6643 }
6644
6653 public function start_element($parser, $name, $attrs)
6654 {
6655 // position in a total number of elements, starting from 0
6656 // update class level pos
6657 $pos = $this->position++;
6658 // and set mine
6659 $this->message[$pos] = array('pos' => $pos,'children' => '','cdata' => '');
6660 // depth = how many levels removed from root?
6661 // set mine as current global depth and increment global depth value
6662 $this->message[$pos]['depth'] = $this->depth++;
6663
6664 // else add self as child to whoever the current parent is
6665 if ($pos != 0) {
6666 $this->message[$this->parent]['children'] .= '|' . $pos;
6667 }
6668 // set my parent
6669 $this->message[$pos]['parent'] = $this->parent;
6670 // set self as current parent
6671 $this->parent = $pos;
6672 // set self as current value for this depth
6673 $this->depth_array[$this->depth] = $pos;
6674 // get element prefix
6675 if (strpos($name, ':')) {
6676 // get ns prefix
6677 $prefix = substr($name, 0, strpos($name, ':'));
6678 // get unqualified name
6679 $name = substr(strstr($name, ':'), 1);
6680 }
6681 // set status
6682 if ($name == 'Envelope') {
6683 $this->status = 'envelope';
6684 } elseif ($name == 'Header' && $this->status = 'envelope') {
6685 $this->root_header = $pos;
6686 $this->status = 'header';
6687 } elseif ($name == 'Body' && $this->status = 'envelope') {
6688 $this->status = 'body';
6689 $this->body_position = $pos;
6690 // set method
6691 } elseif ($this->status == 'body' && $pos == ($this->body_position + 1)) {
6692 $this->status = 'method';
6693 $this->root_struct_name = $name;
6694 $this->root_struct = $pos;
6695 $this->message[$pos]['type'] = 'struct';
6696 $this->debug("found root struct $this->root_struct_name, pos $this->root_struct");
6697 }
6698 // set my status
6699 $this->message[$pos]['status'] = $this->status;
6700 // set name
6701 $this->message[$pos]['name'] = htmlspecialchars($name);
6702 // set attrs
6703 $this->message[$pos]['attrs'] = $attrs;
6704
6705 // loop through atts, logging ns and type declarations
6706 $attstr = '';
6707 foreach ($attrs as $key => $value) {
6708 $key_prefix = $this->getPrefix($key);
6709 $key_localpart = $this->getLocalPart($key);
6710 // if ns declarations, add to class level array of valid namespaces
6711 if ($key_prefix == 'xmlns') {
6712 if (preg_match('/^http:\/\/www.w3.org\/[0-9]{4}\/XMLSchema$/', $value)) {
6713 $this->XMLSchemaVersion = $value;
6714 $this->namespaces['xsd'] = $this->XMLSchemaVersion;
6715 $this->namespaces['xsi'] = $this->XMLSchemaVersion . '-instance';
6716 }
6717 $this->namespaces[$key_localpart] = $value;
6718 // set method namespace
6719 if ($name == $this->root_struct_name) {
6720 $this->methodNamespace = $value;
6721 }
6722 // if it's a type declaration, set type
6723 } elseif ($key_localpart == 'type') {
6724 if (isset($this->message[$pos]['type']) && $this->message[$pos]['type'] == 'array') {
6725 // do nothing: already processed arrayType
6726 } else {
6727 $value_prefix = $this->getPrefix($value);
6728 $value_localpart = $this->getLocalPart($value);
6729 $this->message[$pos]['type'] = $value_localpart;
6730 $this->message[$pos]['typePrefix'] = $value_prefix;
6731 if (isset($this->namespaces[$value_prefix])) {
6732 $this->message[$pos]['type_namespace'] = $this->namespaces[$value_prefix];
6733 } elseif (isset($attrs['xmlns:' . $value_prefix])) {
6734 $this->message[$pos]['type_namespace'] = $attrs['xmlns:' . $value_prefix];
6735 }
6736 // should do something here with the namespace of specified type?
6737 }
6738 } elseif ($key_localpart == 'arrayType') {
6739 $this->message[$pos]['type'] = 'array';
6740 /* do arrayType ereg here
6741 [1] arrayTypeValue ::= atype asize
6742 [2] atype ::= QName rank*
6743 [3] rank ::= '[' (',')* ']'
6744 [4] asize ::= '[' length~ ']'
6745 [5] length ::= nextDimension* Digit+
6746 [6] nextDimension ::= Digit+ ','
6747 */
6748 $expr = '/([A-Za-z0-9_]+):([A-Za-z]+[A-Za-z0-9_]+)\[([0-9]+),?([0-9]*)\]/';
6749 if (preg_match($expr, $value, $regs)) {
6750 $this->message[$pos]['typePrefix'] = $regs[1];
6751 $this->message[$pos]['arrayTypePrefix'] = $regs[1];
6752 if (isset($this->namespaces[$regs[1]])) {
6753 $this->message[$pos]['arrayTypeNamespace'] = $this->namespaces[$regs[1]];
6754 } elseif (isset($attrs['xmlns:' . $regs[1]])) {
6755 $this->message[$pos]['arrayTypeNamespace'] = $attrs['xmlns:' . $regs[1]];
6756 }
6757 $this->message[$pos]['arrayType'] = $regs[2];
6758 $this->message[$pos]['arraySize'] = $regs[3];
6759 $this->message[$pos]['arrayCols'] = $regs[4];
6760 }
6761 // specifies nil value (or not)
6762 } elseif ($key_localpart == 'nil') {
6763 $this->message[$pos]['nil'] = ($value == 'true' || $value == '1');
6764 // some other attribute
6765 } elseif ($key != 'href' && $key != 'xmlns' && $key_localpart != 'encodingStyle' && $key_localpart != 'root') {
6766 $this->message[$pos]['xattrs']['!' . $key] = $value;
6767 }
6768
6769 if ($key == 'xmlns') {
6770 $this->default_namespace = $value;
6771 }
6772 // log id
6773 if ($key == 'id') {
6774 $this->ids[$value] = $pos;
6775 }
6776 // root
6777 if ($key_localpart == 'root' && $value == 1) {
6778 $this->status = 'method';
6779 $this->root_struct_name = $name;
6780 $this->root_struct = $pos;
6781 $this->debug("found root struct $this->root_struct_name, pos $pos");
6782 }
6783 // for doclit
6784 $attstr .= " $key=\"$value\"";
6785 }
6786 // get namespace - must be done after namespace atts are processed
6787 if (isset($prefix)) {
6788 $this->message[$pos]['namespace'] = $this->namespaces[$prefix];
6789 $this->default_namespace = $this->namespaces[$prefix];
6790 } else {
6791 $this->message[$pos]['namespace'] = $this->default_namespace;
6792 }
6793 if ($this->status == 'header') {
6794 if ($this->root_header != $pos) {
6795 $this->responseHeaders .= "<" . (isset($prefix) ? $prefix . ':' : '') . "$name$attstr>";
6796 }
6797 } elseif ($this->root_struct_name != '') {
6798 $this->document .= "<" . (isset($prefix) ? $prefix . ':' : '') . "$name$attstr>";
6799 }
6800 }
6801
6809 public function end_element($parser, $name)
6810 {
6811 // position of current element is equal to the last value left in depth_array for my depth
6812 $pos = $this->depth_array[$this->depth--];
6813
6814 // get element prefix
6815 if (strpos($name, ':')) {
6816 // get ns prefix
6817 $prefix = substr($name, 0, strpos($name, ':'));
6818 // get unqualified name
6819 $name = substr(strstr($name, ':'), 1);
6820 }
6821
6822 // build to native type
6823 if (isset($this->body_position) && $pos > $this->body_position) {
6824 // deal w/ multirefs
6825 if (isset($this->message[$pos]['attrs']['href'])) {
6826 // get id
6827 $id = substr($this->message[$pos]['attrs']['href'], 1);
6828 // add placeholder to href array
6829 $this->multirefs[$id][$pos] = 'placeholder';
6830 // add set a reference to it as the result value
6831 $this->message[$pos]['result'] = & $this->multirefs[$id][$pos];
6832 // build complexType values
6833 } elseif ($this->message[$pos]['children'] != '') {
6834 // if result has already been generated (struct/array)
6835 if (!isset($this->message[$pos]['result'])) {
6836 $this->message[$pos]['result'] = $this->buildVal($pos);
6837 }
6838 // build complexType values of attributes and possibly simpleContent
6839 } elseif (isset($this->message[$pos]['xattrs'])) {
6840 if (isset($this->message[$pos]['nil']) && $this->message[$pos]['nil']) {
6841 $this->message[$pos]['xattrs']['!'] = null;
6842 } elseif (isset($this->message[$pos]['cdata']) && trim($this->message[$pos]['cdata']) != '') {
6843 if (isset($this->message[$pos]['type'])) {
6844 $this->message[$pos]['xattrs']['!'] = $this->decodeSimple($this->message[$pos]['cdata'], $this->message[$pos]['type'], isset($this->message[$pos]['type_namespace']) ? $this->message[$pos]['type_namespace'] : '');
6845 } else {
6846 $parent = $this->message[$pos]['parent'];
6847 if (isset($this->message[$parent]['type']) && ($this->message[$parent]['type'] == 'array') && isset($this->message[$parent]['arrayType'])) {
6848 $this->message[$pos]['xattrs']['!'] = $this->decodeSimple($this->message[$pos]['cdata'], $this->message[$parent]['arrayType'], isset($this->message[$parent]['arrayTypeNamespace']) ? $this->message[$parent]['arrayTypeNamespace'] : '');
6849 } else {
6850 $this->message[$pos]['xattrs']['!'] = $this->message[$pos]['cdata'];
6851 }
6852 }
6853 }
6854 $this->message[$pos]['result'] = $this->message[$pos]['xattrs'];
6855 // set value of simpleType (or nil complexType)
6856 } else {
6857 //$this->debug('adding data for scalar value '.$this->message[$pos]['name'].' of value '.$this->message[$pos]['cdata']);
6858 if (isset($this->message[$pos]['nil']) && $this->message[$pos]['nil']) {
6859 $this->message[$pos]['xattrs']['!'] = null;
6860 } elseif (isset($this->message[$pos]['type'])) {
6861 $this->message[$pos]['result'] = $this->decodeSimple($this->message[$pos]['cdata'], $this->message[$pos]['type'], isset($this->message[$pos]['type_namespace']) ? $this->message[$pos]['type_namespace'] : '');
6862 } else {
6863 $parent = $this->message[$pos]['parent'];
6864 if (isset($this->message[$parent]['type']) && ($this->message[$parent]['type'] == 'array') && isset($this->message[$parent]['arrayType'])) {
6865 $this->message[$pos]['result'] = $this->decodeSimple($this->message[$pos]['cdata'], $this->message[$parent]['arrayType'], isset($this->message[$parent]['arrayTypeNamespace']) ? $this->message[$parent]['arrayTypeNamespace'] : '');
6866 } else {
6867 $this->message[$pos]['result'] = $this->message[$pos]['cdata'];
6868 }
6869 }
6870
6871 /* add value to parent's result, if parent is struct/array
6872 $parent = $this->message[$pos]['parent'];
6873 if($this->message[$parent]['type'] != 'map'){
6874 if(strtolower($this->message[$parent]['type']) == 'array'){
6875 $this->message[$parent]['result'][] = $this->message[$pos]['result'];
6876 } else {
6877 $this->message[$parent]['result'][$this->message[$pos]['name']] = $this->message[$pos]['result'];
6878 }
6879 }
6880 */
6881 }
6882 }
6883
6884 // for doclit
6885 if ($this->status == 'header') {
6886 if ($this->root_header != $pos) {
6887 $this->responseHeaders .= "</" . (isset($prefix) ? $prefix . ':' : '') . "$name>";
6888 }
6889 } elseif ($pos >= $this->root_struct) {
6890 $this->document .= "</" . (isset($prefix) ? $prefix . ':' : '') . "$name>";
6891 }
6892 // switch status
6893 if ($pos == $this->root_struct) {
6894 $this->status = 'body';
6895 $this->root_struct_namespace = $this->message[$pos]['namespace'];
6896 } elseif ($name == 'Body') {
6897 $this->status = 'envelope';
6898 } elseif ($name == 'Header') {
6899 $this->status = 'envelope';
6900 } elseif ($name == 'Envelope') {
6901 //
6902 }
6903 // set parent back to my parent
6904 $this->parent = $this->message[$pos]['parent'];
6905 }
6906
6914 public function character_data($parser, $data)
6915 {
6916 $pos = $this->depth_array[$this->depth];
6917 if ($this->xml_encoding == 'UTF-8') {
6918 // TODO: add an option to disable this for folks who want
6919 // raw UTF-8 that, e.g., might not map to iso-8859-1
6920 // TODO: this can also be handled with xml_parser_set_option($this->parser, XML_OPTION_TARGET_ENCODING, "ISO-8859-1");
6921 if ($this->decode_utf8) {
6922 $data = utf8_decode($data);
6923 }
6924 }
6925 $this->message[$pos]['cdata'] .= $data;
6926 // for doclit
6927 if ($this->status == 'header') {
6928 $this->responseHeaders .= $data;
6929 } else {
6930 $this->document .= $data;
6931 }
6932 }
6933
6941 public function get_response()
6942 {
6943 return $this->soapresponse;
6944 }
6945
6952 public function get_soapbody()
6953 {
6954 return $this->soapresponse;
6955 }
6956
6963 public function get_soapheader()
6964 {
6965 return $this->soapheader;
6966 }
6967
6974 public function getHeaders()
6975 {
6977 }
6978
6988 public function decodeSimple($value, $type, $typens)
6989 {
6990 // TODO: use the namespace!
6991 if ((!isset($type)) || $type == 'string' || $type == 'long' || $type == 'unsignedLong') {
6992 return (string) $value;
6993 }
6994 if ($type == 'int' || $type == 'integer' || $type == 'short' || $type == 'byte') {
6995 return (int) $value;
6996 }
6997 if ($type == 'float' || $type == 'double' || $type == 'decimal') {
6998 return (float) $value;
6999 }
7000 if ($type == 'boolean') {
7001 if (strtolower($value) == 'false' || strtolower($value) == 'f') {
7002 return false;
7003 }
7004 return (bool) $value;
7005 }
7006 if ($type == 'base64' || $type == 'base64Binary') {
7007 $this->debug('Decode base64 value');
7008 return base64_decode($value);
7009 }
7010 // obscure numeric types
7011 if ($type == 'nonPositiveInteger' || $type == 'negativeInteger'
7012 || $type == 'nonNegativeInteger' || $type == 'positiveInteger'
7013 || $type == 'unsignedInt'
7014 || $type == 'unsignedShort' || $type == 'unsignedByte') {
7015 return (int) $value;
7016 }
7017 // bogus: parser treats array with no elements as a simple type
7018 if ($type == 'array') {
7019 return array();
7020 }
7021 // everything else
7022 return (string) $value;
7023 }
7024
7033 public function buildVal($pos)
7034 {
7035 if (!isset($this->message[$pos]['type'])) {
7036 $this->message[$pos]['type'] = '';
7037 }
7038 $this->debug('in buildVal() for ' . $this->message[$pos]['name'] . "(pos $pos) of type " . $this->message[$pos]['type']);
7039 // if there are children...
7040 if ($this->message[$pos]['children'] != '') {
7041 $this->debug('in buildVal, there are children');
7042 $children = explode('|', $this->message[$pos]['children']);
7043 array_shift($children); // knock off empty
7044 // md array
7045 if (isset($this->message[$pos]['arrayCols']) && $this->message[$pos]['arrayCols'] != '') {
7046 $r = 0; // rowcount
7047 $c = 0; // colcount
7048 foreach ($children as $child_pos) {
7049 $this->debug("in buildVal, got an MD array element: $r, $c");
7050 $params[$r][] = $this->message[$child_pos]['result'];
7051 $c++;
7052 if ($c == $this->message[$pos]['arrayCols']) {
7053 $c = 0;
7054 $r++;
7055 }
7056 }
7057 // array
7058 } elseif ($this->message[$pos]['type'] == 'array' || $this->message[$pos]['type'] == 'Array') {
7059 $this->debug('in buildVal, adding array ' . $this->message[$pos]['name']);
7060 foreach ($children as $child_pos) {
7061 $params[] = &$this->message[$child_pos]['result'];
7062 }
7063 // apache Map type: java hashtable
7064 } elseif ($this->message[$pos]['type'] == 'Map' && $this->message[$pos]['type_namespace'] == 'http://xml.apache.org/xml-soap') {
7065 $this->debug('in buildVal, Java Map ' . $this->message[$pos]['name']);
7066 foreach ($children as $child_pos) {
7067 $kv = explode("|", $this->message[$child_pos]['children']);
7068 $params[$this->message[$kv[1]]['result']] = &$this->message[$kv[2]]['result'];
7069 }
7070 // generic compound type
7071 //} elseif($this->message[$pos]['type'] == 'SOAPStruct' || $this->message[$pos]['type'] == 'struct') {
7072 } else {
7073 // Apache Vector type: treat as an array
7074 $this->debug('in buildVal, adding Java Vector or generic compound type ' . $this->message[$pos]['name']);
7075 if ($this->message[$pos]['type'] == 'Vector' && $this->message[$pos]['type_namespace'] == 'http://xml.apache.org/xml-soap') {
7076 $notstruct = 1;
7077 } else {
7078 $notstruct = 0;
7079 }
7080 //
7081 foreach ($children as $child_pos) {
7082 if ($notstruct) {
7083 $params[] = &$this->message[$child_pos]['result'];
7084 } else {
7085 if (isset($params[$this->message[$child_pos]['name']])) {
7086 // de-serialize repeated element name into an array
7087 if ((!is_array($params[$this->message[$child_pos]['name']])) || (!isset($params[$this->message[$child_pos]['name']][0]))) {
7088 $params[$this->message[$child_pos]['name']] = array($params[$this->message[$child_pos]['name']]);
7089 }
7090 $params[$this->message[$child_pos]['name']][] = &$this->message[$child_pos]['result'];
7091 } else {
7092 $params[$this->message[$child_pos]['name']] = &$this->message[$child_pos]['result'];
7093 }
7094 }
7095 }
7096 }
7097 if (isset($this->message[$pos]['xattrs'])) {
7098 $this->debug('in buildVal, handling attributes');
7099 foreach ($this->message[$pos]['xattrs'] as $n => $v) {
7100 $params[$n] = $v;
7101 }
7102 }
7103 // handle simpleContent
7104 if (isset($this->message[$pos]['cdata']) && trim($this->message[$pos]['cdata']) != '') {
7105 $this->debug('in buildVal, handling simpleContent');
7106 if (isset($this->message[$pos]['type'])) {
7107 $params['!'] = $this->decodeSimple($this->message[$pos]['cdata'], $this->message[$pos]['type'], isset($this->message[$pos]['type_namespace']) ? $this->message[$pos]['type_namespace'] : '');
7108 } else {
7109 $parent = $this->message[$pos]['parent'];
7110 if (isset($this->message[$parent]['type']) && ($this->message[$parent]['type'] == 'array') && isset($this->message[$parent]['arrayType'])) {
7111 $params['!'] = $this->decodeSimple($this->message[$pos]['cdata'], $this->message[$parent]['arrayType'], isset($this->message[$parent]['arrayTypeNamespace']) ? $this->message[$parent]['arrayTypeNamespace'] : '');
7112 } else {
7113 $params['!'] = $this->message[$pos]['cdata'];
7114 }
7115 }
7116 }
7117 $ret = is_array($params) ? $params : array();
7118 $this->debug('in buildVal, return:');
7119 $this->appendDebug($this->varDump($ret));
7120 return $ret;
7121 } else {
7122 $this->debug('in buildVal, no children, building scalar');
7123 $cdata = isset($this->message[$pos]['cdata']) ? $this->message[$pos]['cdata'] : '';
7124 if (isset($this->message[$pos]['type'])) {
7125 $ret = $this->decodeSimple($cdata, $this->message[$pos]['type'], isset($this->message[$pos]['type_namespace']) ? $this->message[$pos]['type_namespace'] : '');
7126 $this->debug("in buildVal, return: $ret");
7127 return $ret;
7128 }
7129 $parent = $this->message[$pos]['parent'];
7130 if (isset($this->message[$parent]['type']) && ($this->message[$parent]['type'] == 'array') && isset($this->message[$parent]['arrayType'])) {
7131 $ret = $this->decodeSimple($cdata, $this->message[$parent]['arrayType'], isset($this->message[$parent]['arrayTypeNamespace']) ? $this->message[$parent]['arrayTypeNamespace'] : '');
7132 $this->debug("in buildVal, return: $ret");
7133 return $ret;
7134 }
7135 $ret = $this->message[$pos]['cdata'];
7136 $this->debug("in buildVal, return: $ret");
7137 return $ret;
7138 }
7139 }
7140}
7141
7146{
7147}
7148
7149?><?php
7150
7151
7152
7174{
7175 public $return;
7176 public $wsdl;
7178 public $opData;
7180 public $username = ''; // Username for HTTP authentication
7181 public $password = ''; // Password for HTTP authentication
7182 public $authtype = ''; // Type of HTTP authentication
7183 public $certRequest = array(); // Certificate for HTTP SSL authentication
7184 public $requestHeaders = false; // SOAP headers in request (text)
7185 public $responseHeaders = ''; // SOAP headers from response (incomplete namespace resolution) (text)
7186 public $responseHeader = null; // SOAP Header from response (parsed)
7187 public $document = ''; // SOAP body response portion (incomplete namespace resolution) (text)
7189 public $forceEndpoint = ''; // overrides WSDL endpoint
7190 public $proxyhost = '';
7191 public $proxyport = '';
7192 public $proxyusername = '';
7193 public $proxypassword = '';
7194 public $xml_encoding = ''; // character set encoding of incoming (response) messages
7195 public $http_encoding = false;
7196 public $timeout = 0; // HTTP connection timeout
7197 public $response_timeout = 30; // HTTP response timeout
7198 public $endpointType = ''; // soap|wsdl, empty for WSDL initialization error
7200 public $defaultRpcParams = false; // This is no longer used
7201 public $request = ''; // HTTP request
7202 public $response = ''; // HTTP response
7203 public $responseData = ''; // SOAP payload of response
7204 public $cookies = array(); // Cookies from response or for request
7205 public $decode_utf8 = true; // toggles whether the parser decodes element content w/ utf8_decode()
7206 public $operations = array(); // WSDL operations, empty for WSDL initialization error
7207 public $curl_options = array(); // User-specified cURL options
7208 public $bindingType = ''; // WSDL operation binding type
7209 public $use_curl = false; // whether to always try to use cURL
7210
7211 /*
7212 * fault related variables
7213 */
7218 public $fault;
7234
7249 public function __construct($endpoint, $wsdl = false, $proxyhost = false, $proxyport = false, $proxyusername = false, $proxypassword = false, $timeout = 0, $response_timeout = 30)
7250 {
7252 $this->endpoint = $endpoint;
7253 $this->proxyhost = $proxyhost;
7254 $this->proxyport = $proxyport;
7255 $this->proxyusername = $proxyusername;
7256 $this->proxypassword = $proxypassword;
7257 $this->timeout = $timeout;
7258 $this->response_timeout = $response_timeout;
7259
7260 $this->debug("ctor wsdl=$wsdl timeout=$timeout response_timeout=$response_timeout");
7261 $this->appendDebug('endpoint=' . $this->varDump($endpoint));
7262
7263 // make values
7264 if ($wsdl) {
7265 if (is_object($endpoint) && (get_class($endpoint) == 'wsdl')) {
7266 $this->wsdl = $endpoint;
7267 $this->endpoint = $this->wsdl->wsdl;
7268 $this->wsdlFile = $this->endpoint;
7269 $this->debug('existing wsdl instance created from ' . $this->endpoint);
7270 $this->checkWSDL();
7271 } else {
7272 $this->wsdlFile = $this->endpoint;
7273 $this->wsdl = null;
7274 $this->debug('will use lazy evaluation of wsdl from ' . $this->endpoint);
7275 }
7276 $this->endpointType = 'wsdl';
7277 } else {
7278 $this->debug("instantiate SOAP with endpoint at $endpoint");
7279 $this->endpointType = 'soap';
7280 }
7281 }
7282
7308 public function call($operation, $params = array(), $namespace = 'http://tempuri.org', $soapAction = '', $headers = false, $rpcParams = null, $style = 'rpc', $use = 'encoded')
7309 {
7310 $this->operation = $operation;
7311 $this->fault = false;
7312 $this->setError('');
7313 $this->request = '';
7314 $this->response = '';
7315 $this->responseData = '';
7316 $this->faultstring = '';
7317 $this->faultcode = '';
7318 $this->opData = array();
7319
7320 $this->debug("call: operation=$operation, namespace=$namespace, soapAction=$soapAction, rpcParams=$rpcParams, style=$style, use=$use, endpointType=$this->endpointType");
7321 $this->appendDebug('params=' . $this->varDump($params));
7322 $this->appendDebug('headers=' . $this->varDump($headers));
7323 if ($headers) {
7324 $this->requestHeaders = $headers;
7325 }
7326 if ($this->endpointType == 'wsdl' && is_null($this->wsdl)) {
7327 $this->loadWSDL();
7328 if ($this->getError()) {
7329 return false;
7330 }
7331 }
7332 // serialize parameters
7333 if ($this->endpointType == 'wsdl' && $opData = $this->getOperationData($operation)) {
7334 // use WSDL for operation
7335 $this->opData = $opData;
7336 $this->debug("found operation");
7337 $this->appendDebug('opData=' . $this->varDump($opData));
7338 if (isset($opData['soapAction'])) {
7339 $soapAction = $opData['soapAction'];
7340 }
7341 if (! $this->forceEndpoint) {
7342 $this->endpoint = $opData['endpoint'];
7343 } else {
7344 $this->endpoint = $this->forceEndpoint;
7345 }
7346 $namespace = isset($opData['input']['namespace']) ? $opData['input']['namespace'] : $namespace;
7347 $style = $opData['style'];
7348 $use = $opData['input']['use'];
7349 // add ns to ns array
7350 if ($namespace != '' && !isset($this->wsdl->namespaces[$namespace])) {
7351 $nsPrefix = 'ns' . rand(1000, 9999);
7352 $this->wsdl->namespaces[$nsPrefix] = $namespace;
7353 }
7354 $nsPrefix = $this->wsdl->getPrefixFromNamespace($namespace);
7355 // serialize payload
7356 if (is_string($params)) {
7357 $this->debug("serializing param string for WSDL operation $operation");
7358 $payload = $params;
7359 } elseif (is_array($params)) {
7360 $this->debug("serializing param array for WSDL operation $operation");
7361 $payload = $this->wsdl->serializeRPCParameters($operation, 'input', $params, $this->bindingType);
7362 } else {
7363 $this->debug('params must be array or string');
7364 $this->setError('params must be array or string');
7365 return false;
7366 }
7367 $usedNamespaces = $this->wsdl->usedNamespaces;
7368 if (isset($opData['input']['encodingStyle'])) {
7369 $encodingStyle = $opData['input']['encodingStyle'];
7370 } else {
7371 $encodingStyle = '';
7372 }
7373 $this->appendDebug($this->wsdl->getDebug());
7374 $this->wsdl->clearDebug();
7375 if ($errstr = $this->wsdl->getError()) {
7376 $this->debug('got wsdl error: ' . $errstr);
7377 $this->setError('wsdl error: ' . $errstr);
7378 return false;
7379 }
7380 } elseif ($this->endpointType == 'wsdl') {
7381 // operation not in WSDL
7382 $this->appendDebug($this->wsdl->getDebug());
7383 $this->wsdl->clearDebug();
7384 $this->setError('operation ' . $operation . ' not present.');
7385 $this->debug("operation '$operation' not present.");
7386 return false;
7387 } else {
7388 // no WSDL
7389 //$this->namespaces['ns1'] = $namespace;
7390 $nsPrefix = 'ns' . rand(1000, 9999);
7391 // serialize
7392 $payload = '';
7393 if (is_string($params)) {
7394 $this->debug("serializing param string for operation $operation");
7395 $payload = $params;
7396 } elseif (is_array($params)) {
7397 $this->debug("serializing param array for operation $operation");
7398 foreach ($params as $k => $v) {
7399 $payload .= $this->serialize_val($v, $k, false, false, false, false, $use);
7400 }
7401 } else {
7402 $this->debug('params must be array or string');
7403 $this->setError('params must be array or string');
7404 return false;
7405 }
7406 $usedNamespaces = array();
7407 if ($use == 'encoded') {
7408 $encodingStyle = 'http://schemas.xmlsoap.org/soap/encoding/';
7409 } else {
7410 $encodingStyle = '';
7411 }
7412 }
7413 // wrap RPC calls with method element
7414 if ($style == 'rpc') {
7415 if ($use == 'literal') {
7416 $this->debug("wrapping RPC request with literal method element");
7417 if ($namespace) {
7418 // http://www.ws-i.org/Profiles/BasicProfile-1.1-2004-08-24.html R2735 says rpc/literal accessor elements should not be in a namespace
7419 $payload = "<$nsPrefix:$operation xmlns:$nsPrefix=\"$namespace\">" .
7420 $payload .
7421 "</$nsPrefix:$operation>";
7422 } else {
7423 $payload = "<$operation>" . $payload . "</$operation>";
7424 }
7425 } else {
7426 $this->debug("wrapping RPC request with encoded method element");
7427 if ($namespace) {
7428 $payload = "<$nsPrefix:$operation xmlns:$nsPrefix=\"$namespace\">" .
7429 $payload .
7430 "</$nsPrefix:$operation>";
7431 } else {
7432 $payload = "<$operation>" .
7433 $payload .
7434 "</$operation>";
7435 }
7436 }
7437 }
7438 // serialize envelope
7439 $soapmsg = $this->serializeEnvelope($payload, $this->requestHeaders, $usedNamespaces, $style, $use, $encodingStyle);
7440 $this->debug("endpoint=$this->endpoint, soapAction=$soapAction, namespace=$namespace, style=$style, use=$use, encodingStyle=$encodingStyle");
7441 $this->debug('SOAP message length=' . strlen($soapmsg) . ' contents (max 1000 bytes)=' . substr($soapmsg, 0, 1000));
7442 // send
7443 $return = $this->send($this->getHTTPBody($soapmsg), $soapAction, $this->timeout, $this->response_timeout);
7444 if ($errstr = $this->getError()) {
7445 $this->debug('Error: ' . $errstr);
7446 return false;
7447 } else {
7448 $this->return = $return;
7449 $this->debug('sent message successfully and got a(n) ' . gettype($return));
7450 $this->appendDebug('return=' . $this->varDump($return));
7451
7452 // fault?
7453 if (is_array($return) && isset($return['faultcode'])) {
7454 $this->debug('got fault');
7455 $this->setError($return['faultcode'] . ': ' . $return['faultstring']);
7456 $this->fault = true;
7457 foreach ($return as $k => $v) {
7458 $this->$k = $v;
7459 $this->debug("$k = $v<br>");
7460 }
7461 return $return;
7462 } elseif ($style == 'document') {
7463 // NOTE: if the response is defined to have multiple parts (i.e. unwrapped),
7464 // we are only going to return the first part here...sorry about that
7465 return $return;
7466 } else {
7467 // array of return values
7468 if (is_array($return)) {
7469 // multiple 'out' parameters, which we return wrapped up
7470 // in the array
7471 if (sizeof($return) > 1) {
7472 return $return;
7473 }
7474 // single 'out' parameter (normally the return value)
7475 $return = array_shift($return);
7476 $this->debug('return shifted value: ');
7477 $this->appendDebug($this->varDump($return));
7478 return $return;
7479 // nothing returned (ie, echoVoid)
7480 } else {
7481 return "";
7482 }
7483 }
7484 }
7485 }
7486
7492 public function checkWSDL()
7493 {
7494 $this->appendDebug($this->wsdl->getDebug());
7495 $this->wsdl->clearDebug();
7496 $this->debug('checkWSDL');
7497 // catch errors
7498 if ($errstr = $this->wsdl->getError()) {
7499 $this->debug('got wsdl error: ' . $errstr);
7500 $this->setError('wsdl error: ' . $errstr);
7501 } elseif ($this->operations = $this->wsdl->getOperations('soap')) {
7502 $this->bindingType = 'soap';
7503 $this->debug('got ' . count($this->operations) . ' operations from wsdl ' . $this->wsdlFile . ' for binding type ' . $this->bindingType);
7504 } elseif ($this->operations = $this->wsdl->getOperations('soap12')) {
7505 $this->bindingType = 'soap12';
7506 $this->debug('got ' . count($this->operations) . ' operations from wsdl ' . $this->wsdlFile . ' for binding type ' . $this->bindingType);
7507 $this->debug('**************** WARNING: SOAP 1.2 BINDING *****************');
7508 } else {
7509 $this->debug('getOperations returned false');
7510 $this->setError('no operations defined in the WSDL document!');
7511 }
7512 }
7513
7519 public function loadWSDL()
7520 {
7521 $this->debug('instantiating wsdl class with doc: ' . $this->wsdlFile);
7522 $this->wsdl = new wsdl('', $this->proxyhost, $this->proxyport, $this->proxyusername, $this->proxypassword, $this->timeout, $this->response_timeout, $this->curl_options, $this->use_curl);
7523 $this->wsdl->setCredentials($this->username, $this->password, $this->authtype, $this->certRequest);
7524 $this->wsdl->fetchWSDL($this->wsdlFile);
7525 $this->checkWSDL();
7526 }
7527
7536 {
7537 if ($this->endpointType == 'wsdl' && is_null($this->wsdl)) {
7538 $this->loadWSDL();
7539 if ($this->getError()) {
7540 return false;
7541 }
7542 }
7543 if (isset($this->operations[$operation])) {
7544 return $this->operations[$operation];
7545 }
7546 $this->debug("No data for operation: $operation");
7547 }
7548
7563 public function send($msg, $soapaction = '', $timeout = 0, $response_timeout = 30)
7564 {
7565 $this->checkCookies();
7566 // detect transport
7567 switch (true) {
7568 // http(s)
7569 case preg_match('/^http/', $this->endpoint):
7570 $this->debug('transporting via HTTP');
7571 if ($this->persistentConnection == true && is_object($this->persistentConnection)) {
7573 } else {
7574 $http = new soap_transport_http($this->endpoint, $this->curl_options, $this->use_curl);
7575 if ($this->persistentConnection) {
7576 $http->usePersistentConnection();
7577 }
7578 }
7579 $http->setContentType($this->getHTTPContentType(), $this->getHTTPContentTypeCharset());
7580 $http->setSOAPAction($soapaction);
7581 if ($this->proxyhost && $this->proxyport) {
7582 $http->setProxy($this->proxyhost, $this->proxyport, $this->proxyusername, $this->proxypassword);
7583 }
7584 if ($this->authtype != '') {
7585 $http->setCredentials($this->username, $this->password, $this->authtype, array(), $this->certRequest);
7586 }
7587 if ($this->http_encoding != '') {
7588 $http->setEncoding($this->http_encoding);
7589 }
7590 $this->debug('sending message, length=' . strlen($msg));
7591 if (preg_match('/^http:/', $this->endpoint)) {
7592 //if(strpos($this->endpoint,'http:')){
7593 $this->responseData = $http->send($msg, $timeout, $response_timeout, $this->cookies);
7594 } elseif (preg_match('/^https/', $this->endpoint)) {
7595 //} elseif(strpos($this->endpoint,'https:')){
7596 //if(phpversion() == '4.3.0-dev'){
7597 //$response = $http->send($msg,$timeout,$response_timeout);
7598 //$this->request = $http->outgoing_payload;
7599 //$this->response = $http->incoming_payload;
7600 //} else
7601 $this->responseData = $http->sendHTTPS($msg, $timeout, $response_timeout, $this->cookies);
7602 } else {
7603 $this->setError('no http/s in endpoint url');
7604 }
7605 $this->request = $http->outgoing_payload;
7606 $this->response = $http->incoming_payload;
7607 $this->appendDebug($http->getDebug());
7608 $this->UpdateCookies($http->incoming_cookies);
7609
7610 // save transport object if using persistent connections
7611 if ($this->persistentConnection) {
7612 $http->clearDebug();
7613 if (!is_object($this->persistentConnection)) {
7614 $this->persistentConnection = $http;
7615 }
7616 }
7617
7618 if ($err = $http->getError()) {
7619 $this->setError('HTTP Error: ' . $err);
7620 return false;
7621 } elseif ($this->getError()) {
7622 return false;
7623 } else {
7624 $this->debug('got response, length=' . strlen($this->responseData) . ' type=' . $http->incoming_headers['content-type']);
7625 return $this->parseResponse($http->incoming_headers, $this->responseData);
7626 }
7627 break;
7628 default:
7629 $this->setError('no transport found, or selected transport is not yet supported!');
7630 return false;
7631 break;
7632 }
7633 }
7634
7643 public function parseResponse($headers, $data)
7644 {
7645 $this->debug('Entering parseResponse() for data of length ' . strlen($data) . ' headers:');
7646 $this->appendDebug($this->varDump($headers));
7647 if (!strstr($headers['content-type'], 'text/xml')) {
7648 $this->setError('Response not of type text/xml: ' . $headers['content-type']);
7649 return false;
7650 }
7651 if (strpos($headers['content-type'], '=')) {
7652 $enc = str_replace('"', '', substr(strstr($headers["content-type"], '='), 1));
7653 $this->debug('Got response encoding: ' . $enc);
7654 if (preg_match('/^(ISO-8859-1|US-ASCII|UTF-8)$/i', $enc)) {
7655 $this->xml_encoding = strtoupper($enc);
7656 } else {
7657 $this->xml_encoding = 'US-ASCII';
7658 }
7659 } else {
7660 // should be US-ASCII for HTTP 1.0 or ISO-8859-1 for HTTP 1.1
7661 $this->xml_encoding = 'ISO-8859-1';
7662 }
7663 $this->debug('Use encoding: ' . $this->xml_encoding . ' when creating nusoap_parser');
7664 $parser = new nusoap_parser($data, $this->xml_encoding, $this->operation, $this->decode_utf8);
7665 // add parser debug data to our debug
7666 $this->appendDebug($parser->getDebug());
7667 // if parse errors
7668 if ($errstr = $parser->getError()) {
7669 $this->setError($errstr);
7670 // destroy the parser object
7671 unset($parser);
7672 return false;
7673 } else {
7674 // get SOAP headers
7675 $this->responseHeaders = $parser->getHeaders();
7676 // get SOAP headers
7677 $this->responseHeader = $parser->get_soapheader();
7678 // get decoded message
7679 $return = $parser->get_soapbody();
7680 // add document for doclit support
7681 $this->document = $parser->document;
7682 // destroy the parser object
7683 unset($parser);
7684 // return decode message
7685 return $return;
7686 }
7687 }
7688
7696 public function setCurlOption($option, $value)
7697 {
7698 $this->debug("setCurlOption option=$option, value=");
7699 $this->appendDebug($this->varDump($value));
7700 $this->curl_options[$option] = $value;
7701 }
7702
7709 public function setEndpoint($endpoint)
7710 {
7711 $this->debug("setEndpoint(\"$endpoint\")");
7712 $this->forceEndpoint = $endpoint;
7713 }
7714
7721 public function setHeaders($headers)
7722 {
7723 $this->debug("setHeaders headers=");
7724 $this->appendDebug($this->varDump($headers));
7725 $this->requestHeaders = $headers;
7726 }
7727
7734 public function getHeaders()
7735 {
7737 }
7738
7745 public function getHeader()
7746 {
7747 return $this->responseHeader;
7748 }
7749
7760 {
7761 $this->proxyhost = $proxyhost;
7762 $this->proxyport = $proxyport;
7763 $this->proxyusername = $proxyusername;
7764 $this->proxypassword = $proxypassword;
7765 }
7766
7776 public function setCredentials($username, $password, $authtype = 'basic', $certRequest = array())
7777 {
7778 $this->debug("setCredentials username=$username authtype=$authtype certRequest=");
7779 $this->appendDebug($this->varDump($certRequest));
7780 $this->username = $username;
7781 $this->password = $password;
7782 $this->authtype = $authtype;
7783 $this->certRequest = $certRequest;
7784 }
7785
7792 public function setHTTPEncoding($enc = 'gzip, deflate')
7793 {
7794 $this->debug("setHTTPEncoding(\"$enc\")");
7795 $this->http_encoding = $enc;
7796 }
7797
7804 public function setUseCURL($use)
7805 {
7806 $this->debug("setUseCURL($use)");
7807 $this->use_curl = $use;
7808 }
7809
7816 {
7817 $this->debug("useHTTPPersistentConnection");
7818 $this->persistentConnection = true;
7819 }
7820
7832 public function getDefaultRpcParams()
7833 {
7835 }
7836
7848 public function setDefaultRpcParams($rpcParams)
7849 {
7850 $this->defaultRpcParams = $rpcParams;
7851 }
7852
7860 public function getProxy()
7861 {
7862 $r = rand();
7863 $evalStr = $this->_getProxyClassCode($r);
7864 //$this->debug("proxy class: $evalStr");
7865 if ($this->getError()) {
7866 $this->debug("Error from _getProxyClassCode, so return NULL");
7867 return null;
7868 }
7869 // eval the class
7870 eval($evalStr);
7871 // instantiate proxy object
7872 eval("\$proxy = new nusoap_proxy_$r('');");
7873 // transfer current wsdl data to the proxy thereby avoiding parsing the wsdl twice
7874 $proxy->endpointType = 'wsdl';
7875 $proxy->wsdlFile = $this->wsdlFile;
7876 $proxy->wsdl = $this->wsdl;
7877 $proxy->operations = $this->operations;
7878 $proxy->defaultRpcParams = $this->defaultRpcParams;
7879 // transfer other state
7880 $proxy->soap_defencoding = $this->soap_defencoding;
7881 $proxy->username = $this->username;
7882 $proxy->password = $this->password;
7883 $proxy->authtype = $this->authtype;
7884 $proxy->certRequest = $this->certRequest;
7885 $proxy->requestHeaders = $this->requestHeaders;
7886 $proxy->endpoint = $this->endpoint;
7887 $proxy->forceEndpoint = $this->forceEndpoint;
7888 $proxy->proxyhost = $this->proxyhost;
7889 $proxy->proxyport = $this->proxyport;
7890 $proxy->proxyusername = $this->proxyusername;
7891 $proxy->proxypassword = $this->proxypassword;
7892 $proxy->http_encoding = $this->http_encoding;
7893 $proxy->timeout = $this->timeout;
7894 $proxy->response_timeout = $this->response_timeout;
7895 $proxy->persistentConnection = &$this->persistentConnection;
7896 $proxy->decode_utf8 = $this->decode_utf8;
7897 $proxy->curl_options = $this->curl_options;
7898 $proxy->bindingType = $this->bindingType;
7899 $proxy->use_curl = $this->use_curl;
7900 return $proxy;
7901 }
7902
7909 public function _getProxyClassCode($r)
7910 {
7911 $this->debug("in getProxy endpointType=$this->endpointType");
7912 $this->appendDebug("wsdl=" . $this->varDump($this->wsdl));
7913 if ($this->endpointType != 'wsdl') {
7914 $evalStr = 'A proxy can only be created for a WSDL client';
7915 $this->setError($evalStr);
7916 $evalStr = "echo \"$evalStr\";";
7917 return $evalStr;
7918 }
7919 if ($this->endpointType == 'wsdl' && is_null($this->wsdl)) {
7920 $this->loadWSDL();
7921 if ($this->getError()) {
7922 return "echo \"" . $this->getError() . "\";";
7923 }
7924 }
7925 $evalStr = '';
7926 foreach ($this->operations as $operation => $opData) {
7927 if ($operation != '') {
7928 // create param string and param comment string
7929 if (sizeof($opData['input']['parts']) > 0) {
7930 $paramStr = '';
7931 $paramArrayStr = '';
7932 $paramCommentStr = '';
7933 foreach ($opData['input']['parts'] as $name => $type) {
7934 $paramStr .= "\$$name, ";
7935 $paramArrayStr .= "'$name' => \$$name, ";
7936 $paramCommentStr .= "$type \$$name, ";
7937 }
7938 $paramStr = substr($paramStr, 0, strlen($paramStr) - 2);
7939 $paramArrayStr = substr($paramArrayStr, 0, strlen($paramArrayStr) - 2);
7940 $paramCommentStr = substr($paramCommentStr, 0, strlen($paramCommentStr) - 2);
7941 } else {
7942 $paramStr = '';
7943 $paramArrayStr = '';
7944 $paramCommentStr = 'void';
7945 }
7946 $opData['namespace'] = !isset($opData['namespace']) ? 'http://testuri.com' : $opData['namespace'];
7947 $evalStr .= "// $paramCommentStr
7948 function " . str_replace('.', '__', $operation) . "($paramStr) {
7949 \$params = array($paramArrayStr);
7950 return \$this->call('$operation', \$params, '" . $opData['namespace'] . "', '" . (isset($opData['soapAction']) ? $opData['soapAction'] : '') . "');
7951 }
7952 ";
7953 unset($paramStr);
7954 unset($paramCommentStr);
7955 }
7956 }
7957 $evalStr = 'class nusoap_proxy_' . $r . ' extends nusoap_client {
7958 ' . $evalStr . '
7959}';
7960 return $evalStr;
7961 }
7962
7969 public function getProxyClassCode()
7970 {
7971 $r = rand();
7972 return $this->_getProxyClassCode($r);
7973 }
7974
7982 public function getHTTPBody($soapmsg)
7983 {
7984 return $soapmsg;
7985 }
7986
7995 public function getHTTPContentType()
7996 {
7997 return 'text/xml';
7998 }
7999
8010 {
8012 }
8013
8014 /*
8015 * whether or not parser should decode utf8 element content
8016 *
8017 * @return always returns true
8018 * @access public
8019 */
8020 public function decodeUTF8($bool)
8021 {
8022 $this->decode_utf8 = $bool;
8023 return true;
8024 }
8025
8034 public function setCookie($name, $value)
8035 {
8036 if (strlen($name) == 0) {
8037 return false;
8038 }
8039 $this->cookies[] = array('name' => $name, 'value' => $value);
8040 return true;
8041 }
8042
8049 public function getCookies()
8050 {
8051 return $this->cookies;
8052 }
8053
8060 public function checkCookies()
8061 {
8062 if (sizeof($this->cookies) == 0) {
8063 return true;
8064 }
8065 $this->debug('checkCookie: check ' . sizeof($this->cookies) . ' cookies');
8066 $curr_cookies = $this->cookies;
8067 $this->cookies = array();
8068 foreach ($curr_cookies as $cookie) {
8069 if (! is_array($cookie)) {
8070 $this->debug('Remove cookie that is not an array');
8071 continue;
8072 }
8073 if ((isset($cookie['expires'])) && (! empty($cookie['expires']))) {
8074 if (strtotime($cookie['expires']) > time()) {
8075 $this->cookies[] = $cookie;
8076 } else {
8077 $this->debug('Remove expired cookie ' . $cookie['name']);
8078 }
8079 } else {
8080 $this->cookies[] = $cookie;
8081 }
8082 }
8083 $this->debug('checkCookie: ' . sizeof($this->cookies) . ' cookies left in array');
8084 return true;
8085 }
8086
8094 public function UpdateCookies($cookies)
8095 {
8096 if (sizeof($this->cookies) == 0) {
8097 // no existing cookies: take whatever is new
8098 if (sizeof($cookies) > 0) {
8099 $this->debug('Setting new cookie(s)');
8100 $this->cookies = $cookies;
8101 }
8102 return true;
8103 }
8104 if (sizeof($cookies) == 0) {
8105 // no new cookies: keep what we've got
8106 return true;
8107 }
8108 // merge
8109 foreach ($cookies as $newCookie) {
8110 if (!is_array($newCookie)) {
8111 continue;
8112 }
8113 if ((!isset($newCookie['name'])) || (!isset($newCookie['value']))) {
8114 continue;
8115 }
8116 $newName = $newCookie['name'];
8117
8118 $found = false;
8119 for ($i = 0; $i < count($this->cookies); $i++) {
8120 $cookie = $this->cookies[$i];
8121 if (!is_array($cookie)) {
8122 continue;
8123 }
8124 if (!isset($cookie['name'])) {
8125 continue;
8126 }
8127 if ($newName != $cookie['name']) {
8128 continue;
8129 }
8130 $newDomain = isset($newCookie['domain']) ? $newCookie['domain'] : 'NODOMAIN';
8131 $domain = isset($cookie['domain']) ? $cookie['domain'] : 'NODOMAIN';
8132 if ($newDomain != $domain) {
8133 continue;
8134 }
8135 $newPath = isset($newCookie['path']) ? $newCookie['path'] : 'NOPATH';
8136 $path = isset($cookie['path']) ? $cookie['path'] : 'NOPATH';
8137 if ($newPath != $path) {
8138 continue;
8139 }
8140 $this->cookies[$i] = $newCookie;
8141 $found = true;
8142 $this->debug('Update cookie ' . $newName . '=' . $newCookie['value']);
8143 break;
8144 }
8145 if (! $found) {
8146 $this->debug('Add cookie ' . $newName . '=' . $newCookie['value']);
8147 $this->cookies[] = $newCookie;
8148 }
8149 }
8150 return true;
8151 }
8152}
8153
8154if (!extension_loaded('soap')) {
8158 class soapclient extends nusoap_client
8159 {
8160 }
8161}
8162?>
$id
plugin.php for ilComponentBuildPluginInfoObjectiveTest::testAddPlugins
Definition: plugin.php:23
$out
Definition: buildRTE.php:24
$location
Definition: buildRTE.php:22
foreach($mandatory_scripts as $file) $timestamp
Definition: buildRTE.php:70
Backward compatibility.
Definition: nusoap.php:2014
nusoap_base
Definition: nusoap.php:55
getPrefix($str)
returns the prefix part of a prefixed string returns false, if not prefixed
Definition: nusoap.php:797
& getDebug()
gets the current debug data for this instance
Definition: nusoap.php:290
& getDebugAsXMLComment()
gets the current debug data for this instance as an XML comment this may change the contents of the d...
Definition: nusoap.php:304
getmicrotime()
returns the time in ODBC canonical form with microseconds
Definition: nusoap.php:847
setError($str)
sets error string
Definition: nusoap.php:353
getNamespaceFromPrefix($prefix)
pass it a prefix, it returns a namespace
Definition: nusoap.php:813
contractQname($qname)
contracts (changes namespace to prefix) a qualified name
Definition: nusoap.php:727
debug($string)
adds debug data to the instance debug string with formatting
Definition: nusoap.php:250
getDebugLevel()
gets the debug level for this instance
Definition: nusoap.php:228
getPrefixFromNamespace($ns)
returns the prefix for a given namespace (or prefix) or false if no prefixes registered for the given...
Definition: nusoap.php:830
serialize_val($val, $name=false, $type=false, $name_ns=false, $type_ns=false, $attributes=false, $use='encoded', $soapval=false)
serializes PHP values in accordance w/ section 5.
Definition: nusoap.php:391
setGlobalDebugLevel($level)
sets the global debug level, which applies to future instances
Definition: nusoap.php:217
serializeEnvelope($body, $headers=false, $namespaces=array(), $style='rpc', $use='encoded', $encodingStyle='http://schemas.xmlsoap.org/soap/encoding/')
serializes a message
Definition: nusoap.php:658
clearDebug()
clears the current debug data for this instance
Definition: nusoap.php:277
expandEntities($val)
expands entities, e.g.
Definition: nusoap.php:321
formatDump($str)
formats a string to be inserted into an HTML stream
Definition: nusoap.php:714
$soap_defencoding
Definition: nusoap.php:122
expandQname($qname)
expands (changes prefix to namespace) a qualified name
Definition: nusoap.php:753
$XMLSchemaVersion
Definition: nusoap.php:113
varDump($data)
Returns a string with the output of var_dump.
Definition: nusoap.php:867
setDebugLevel($level)
sets the debug level for this instance
Definition: nusoap.php:239
getError()
returns error string if present
Definition: nusoap.php:339
__toString()
represents the object as a string
Definition: nusoap.php:882
appendDebug($string)
adds debug data to the instance debug string without formatting
Definition: nusoap.php:263
getLocalPart($str)
returns the local part of a prefixed string returns the original string, if not prefixed
Definition: nusoap.php:779
isArraySimpleOrStruct($val)
detect if array is a simple array or a struct (associative array)
Definition: nusoap.php:365
getGlobalDebugLevel()
gets the global debug level, which applies to future instances
Definition: nusoap.php:206
__construct()
constructor
Definition: nusoap.php:195
[nu]soapclient higher level class for easy usage.
Definition: nusoap.php:7174
setCurlOption($option, $value)
sets user-specified cURL options
Definition: nusoap.php:7696
setCredentials($username, $password, $authtype='basic', $certRequest=array())
if authenticating, set user credentials here
Definition: nusoap.php:7776
setHTTPProxy($proxyhost, $proxyport, $proxyusername='', $proxypassword='')
set proxy info here
Definition: nusoap.php:7759
getProxy()
dynamically creates an instance of a proxy class, allowing user to directly call methods from wsdl
Definition: nusoap.php:7860
send($msg, $soapaction='', $timeout=0, $response_timeout=30)
send the SOAP message
Definition: nusoap.php:7563
setUseCURL($use)
Set whether to try to use cURL connections if possible.
Definition: nusoap.php:7804
call($operation, $params=array(), $namespace='http://tempuri.org', $soapAction='', $headers=false, $rpcParams=null, $style='rpc', $use='encoded')
calls method, returns PHP native type
Definition: nusoap.php:7308
getProxyClassCode()
dynamically creates proxy class code
Definition: nusoap.php:7969
checkCookies()
checks all Cookies and delete those which are expired
Definition: nusoap.php:8060
getHTTPContentType()
gets the HTTP content type for the current request.
Definition: nusoap.php:7995
setHTTPEncoding($enc='gzip, deflate')
use HTTP encoding
Definition: nusoap.php:7792
getHeader()
get the SOAP response Header (parsed)
Definition: nusoap.php:7745
decodeUTF8($bool)
Definition: nusoap.php:8020
useHTTPPersistentConnection()
use HTTP persistent connections if possible
Definition: nusoap.php:7815
setCookie($name, $value)
adds a new Cookie into $this->cookies array
Definition: nusoap.php:8034
getHTTPContentTypeCharset()
gets the HTTP content type charset for the current request.
Definition: nusoap.php:8009
getOperationData($operation)
get available data pertaining to an operation
Definition: nusoap.php:7535
getDefaultRpcParams()
gets the default RPC parameter setting.
Definition: nusoap.php:7832
checkWSDL()
check WSDL passed as an instance or pulled from an endpoint
Definition: nusoap.php:7492
setHeaders($headers)
set the SOAP headers
Definition: nusoap.php:7721
loadWSDL()
instantiate wsdl object and parse wsdl file
Definition: nusoap.php:7519
getHTTPBody($soapmsg)
gets the HTTP body for the current request.
Definition: nusoap.php:7982
setDefaultRpcParams($rpcParams)
sets the default RPC parameter setting.
Definition: nusoap.php:7848
__construct($endpoint, $wsdl=false, $proxyhost=false, $proxyport=false, $proxyusername=false, $proxypassword=false, $timeout=0, $response_timeout=30)
constructor
Definition: nusoap.php:7249
setEndpoint($endpoint)
sets the SOAP endpoint, which can override WSDL
Definition: nusoap.php:7709
UpdateCookies($cookies)
updates the current cookies with a new set
Definition: nusoap.php:8094
getHeaders()
get the SOAP response headers (namespace resolution incomplete)
Definition: nusoap.php:7734
_getProxyClassCode($r)
dynamically creates proxy class code
Definition: nusoap.php:7909
getCookies()
gets all Cookies
Definition: nusoap.php:8049
parseResponse($headers, $data)
processes SOAP message returned from server
Definition: nusoap.php:7643
Contains information for a SOAP fault.
Definition: nusoap.php:994
serialize()
serialize a fault
Definition: nusoap.php:1043
__construct($faultcode, $faultactor='', $faultstring='', $faultdetail='')
constructor
Definition: nusoap.php:1028
nusoap_parser class parses SOAP XML messages into native PHP values
Definition: nusoap.php:6514
$root_struct_namespace
Definition: nusoap.php:6522
character_data($parser, $data)
element content handler
Definition: nusoap.php:6914
get_soapbody()
get the parsed SOAP Body (NULL if there was none)
Definition: nusoap.php:6952
end_element($parser, $name)
end-element handler
Definition: nusoap.php:6809
getHeaders()
get the unparsed SOAP Header
Definition: nusoap.php:6974
get_response()
get the parsed message (SOAP Body)
Definition: nusoap.php:6941
decodeSimple($value, $type, $typens)
decodes simple types into PHP variables
Definition: nusoap.php:6988
get_soapheader()
get the parsed SOAP Header (NULL if there was none)
Definition: nusoap.php:6963
start_element($parser, $name, $attrs)
start-element handler
Definition: nusoap.php:6653
buildVal($pos)
builds response structures for compound values (arrays/structs) and scalars
Definition: nusoap.php:7033
__construct($xml, $encoding='UTF-8', $method='', $decode_utf8=true)
constructor that actually does the parsing
Definition: nusoap.php:6560
nusoap_server allows the user to create a SOAP server that is capable of receiving messages and retur...
Definition: nusoap.php:3476
verify_method($operation, $request)
takes the value that was created by parsing the request and compares to the method's signature,...
Definition: nusoap.php:4258
$methodreturnisliteralxml
Definition: nusoap.php:3587
getHTTPBody($soapmsg)
gets the HTTP body for the current response.
Definition: nusoap.php:4330
invoke_method()
invokes a PHP function for the requested SOAP method
Definition: nusoap.php:3939
add_to_map($methodname, $in, $out)
add a method to the dispatch map (this has been replaced by the register method)
Definition: nusoap.php:4371
getHTTPContentType()
gets the HTTP content type for the current response.
Definition: nusoap.php:4343
__construct($wsdl=false)
constructor the optional parameter is a path to a WSDL file that you'd like to bind the server instan...
Definition: nusoap.php:3635
addInternalPort(string $serviceName, string $url)
Definition: nusoap.php:4551
parse_request($data='')
parses a request
Definition: nusoap.php:3891
getHTTPContentTypeCharset()
gets the HTTP content type charset for the current response.
Definition: nusoap.php:4357
serialize_return()
serializes the return value from a PHP function into a full SOAP Envelope
Definition: nusoap.php:4085
send_response()
sends an HTTP response
Definition: nusoap.php:4178
fault($faultcode, $faultstring, $faultactor='', $faultdetail='')
Specify a fault to be returned to the client.
Definition: nusoap.php:4460
parse_http_headers()
parses HTTP request headers.
Definition: nusoap.php:3762
service($data)
processes request and returns response
Definition: nusoap.php:3699
parseRequest($headers, $data)
processes SOAP message received from client
Definition: nusoap.php:4278
configureWSDL($serviceName, $namespace=false, $endpoint=false, $style='rpc', $transport='http://schemas.xmlsoap.org/soap/http', $schemaTargetNamespace=false)
Sets up wsdl object.
Definition: nusoap.php:4480
parses an XML Schema, allows access to it's data, other utility methods.
Definition: nusoap.php:1086
schemaCharacterData($parser, $data)
element content handler
Definition: nusoap.php:1580
getTypeDef($type)
returns an associative array of information about a given type returns false if no type exists by the...
Definition: nusoap.php:1760
addComplexType($name, $typeClass='complexType', $phpType='array', $compositor='', $restrictionBase='', $elements=array(), $attrs=array(), $arrayType='')
adds a complex type to the schema
Definition: nusoap.php:1947
typeToForm($name, $type)
returns HTML form elements that allow a user to enter values for creating an instance of the given ty...
Definition: nusoap.php:1874
addElement($attrs)
adds an element to the schema
Definition: nusoap.php:1997
getPHPType($type, $ns)
get the PHP type of a user defined type in the schema PHP type is kind of a misnomer since it actuall...
Definition: nusoap.php:1726
xdebug($string)
adds debug data to the clas level debug string
Definition: nusoap.php:1709
addSimpleType($name, $restrictionBase='', $typeClass='simpleType', $phpType='scalar', $enumeration=array())
adds a simple type to the schema
Definition: nusoap.php:1976
serializeSchema()
serialize the schema
Definition: nusoap.php:1591
__construct($schema='', $xml='', $namespaces=array())
constructor
Definition: nusoap.php:1124
parseString($xml, $type)
parse an XML string
Definition: nusoap.php:1184
schemaEndElement($parser, $name)
end-element handler
Definition: nusoap.php:1542
schemaStartElement($parser, $name, $attrs)
start-element handler
Definition: nusoap.php:1244
serializeTypeDef($type)
returns a sample serialization of a given type, or false if no type by the given name
Definition: nusoap.php:1837
parseFile($xml, $type)
parse an XML file
Definition: nusoap.php:1157
CreateTypeName($ename)
gets a type name for an unnamed type
Definition: nusoap.php:1227
Backward compatibility.
Definition: nusoap.php:1069
Backward compatibility.
Definition: nusoap.php:7146
Backward compatibility.
Definition: nusoap.php:4565
transport class for sending/receiving data via HTTP and HTTPS NOTE: PHP must be compiled with the CUR...
Definition: nusoap.php:2139
sendRequest($data, $cookies=null)
sends the SOAP request via HTTP[S]
Definition: nusoap.php:2886
setCurlOption($option, $value)
sets a cURL option
Definition: nusoap.php:2207
getCookiesForRequest($cookies, $secure=false)
sort out cookies for the current request
Definition: nusoap.php:3420
send($data, $timeout=0, $response_timeout=30, $cookies=null)
sends the SOAP request and gets the SOAP response via HTTP[S]
Definition: nusoap.php:2554
parseCookie($cookie_str)
parse an incoming Cookie into it's parts
Definition: nusoap.php:3353
setURL($url)
sets the URL to which to connect
Definition: nusoap.php:2247
getResponse()
gets the SOAP response via HTTP[S]
Definition: nusoap.php:2944
setContentType($type, $charset=false)
sets the content-type for the SOAP message to be sent
Definition: nusoap.php:3321
unsetHeader($name)
unsets an HTTP header
Definition: nusoap.php:2233
isSkippableCurlHeader(&$data)
Test if the given string starts with a header that is to be skipped.
Definition: nusoap.php:2750
setSOAPAction($soapaction)
set the soapaction value
Definition: nusoap.php:2685
setEncoding($enc='gzip, deflate')
use http encoding
Definition: nusoap.php:2696
usePersistentConnection()
specifies that an HTTP persistent connection should be used
Definition: nusoap.php:3332
setCredentials($username, $password, $authtype='basic', $digestRequest=array(), $certRequest=array())
if authenticating, set user credentials here
Definition: nusoap.php:2610
buildPayload($data, $cookie_str='')
Writes the payload, including HTTP headers, to $this->outgoing_payload.
Definition: nusoap.php:2838
connect($connection_timeout=0, $response_timeout=30)
establish an HTTP connection
Definition: nusoap.php:2311
setHeader($name, $value)
sets an HTTP header
Definition: nusoap.php:2221
io_method()
gets the I/O method to use
Definition: nusoap.php:2292
decodeChunked($buffer, $lb)
decode a string that is encoded w/ "chunked' transfer encoding as defined in RFC2068 19....
Definition: nusoap.php:2780
setProxy($proxyhost, $proxyport, $proxyusername='', $proxypassword='', $proxyauthtype='basic')
set proxy info here
Definition: nusoap.php:2721
sendHTTPS($data, $timeout=0, $response_timeout=30, $cookies=null)
sends the SOAP request and gets the SOAP response via HTTPS using CURL
Definition: nusoap.php:2595
__construct($url, $curl_options=null, $use_curl=false)
constructor
Definition: nusoap.php:2185
For creating serializable abstractions of native PHP types.
Definition: nusoap.php:2033
serialize($use='encoded')
return serialized value
Definition: nusoap.php:2106
$element_ns
Definition: nusoap.php:2061
__construct($name='soapval', $type=false, $value=-1, $element_ns=false, $type_ns=false, $attributes=false)
constructor
Definition: nusoap.php:2088
decode()
decodes a soapval object into a PHP native type
Definition: nusoap.php:2117
$attributes
Definition: nusoap.php:2075
parses a WSDL file, allows access to it's data, other utility methods.
Definition: nusoap.php:4582
$currentMessage
Definition: nusoap.php:4594
$import
Definition: nusoap.php:4607
$username
Definition: nusoap.php:4623
$ports
Definition: nusoap.php:4600
$proxyhost
Definition: nusoap.php:4614
character_data($parser, $data)
element content handler
Definition: nusoap.php:5114
serializeComplexTypeAttributes($typeDef, $value, $ns, $uqType)
serializes the attributes for a complexType
Definition: nusoap.php:6179
$opData
Definition: nusoap.php:4602
$currentSchema
Definition: nusoap.php:4590
getBindingData($binding)
Definition: nusoap.php:5144
serializeRPCParameters($operation, $direction, $parameters, $bindingType='soap')
serialize PHP values according to a WSDL message definition contrary to the method name,...
Definition: nusoap.php:5702
$currentPortType
Definition: nusoap.php:4597
addElement($attrs)
adds an element to the WSDL types
Definition: nusoap.php:6408
getTypeDef($type, $ns)
returns an array of information about a given type returns false if no type exists by the given name
Definition: nusoap.php:5261
$status
Definition: nusoap.php:4603
getOperations($bindingType='soap')
returns an assoc array of operation names => operation data
Definition: nusoap.php:5158
setCredentials($username, $password, $authtype='basic', $certRequest=array())
if authenticating, set user credentials here
Definition: nusoap.php:5134
$serviceName
Definition: nusoap.php:4584
$proxypassword
Definition: nusoap.php:4617
$certRequest
Definition: nusoap.php:4626
getOperationData($operation, $bindingType='soap')
returns an associative array of data necessary for calling an operation
Definition: nusoap.php:5190
$currentPortOperation
Definition: nusoap.php:4586
$portTypes
Definition: nusoap.php:4596
$currentOperation
Definition: nusoap.php:4595
$messages
Definition: nusoap.php:4593
serializeParameters($operation, $direction, $parameters)
serialize a PHP value according to a WSDL message definition
Definition: nusoap.php:5797
fetchWSDL($wsdl)
fetches the WSDL document and parses it
Definition: nusoap.php:4664
$password
Definition: nusoap.php:4624
addSimpleType($name, $restrictionBase='', $typeClass='simpleType', $phpType='scalar', $enumeration=array())
adds an XML Schema simple type to the WSDL types
Definition: nusoap.php:6393
$depth
Definition: nusoap.php:4611
$bindings
Definition: nusoap.php:4598
serialize($debug=0)
serialize the parsed wsdl
Definition: nusoap.php:5460
$wsdl
Definition: nusoap.php:4587
$timeout
Definition: nusoap.php:4618
$endpoint
Definition: nusoap.php:4605
$use_curl
Definition: nusoap.php:4621
$proxyusername
Definition: nusoap.php:4616
getOperationDataForSoapAction($soapAction, $bindingType='soap')
returns an associative array of data necessary for calling an operation
Definition: nusoap.php:5222
$documentation
Definition: nusoap.php:4604
webDescription()
prints html description of services
Definition: nusoap.php:5318
serializeType($name, $type, $value, $use='encoded', $encodingStyle=false, $unqualified=false)
serializes a PHP value according a given type definition
Definition: nusoap.php:5875
parseWSDL($wsdl='')
parses the wsdl document
Definition: nusoap.php:4768
$message
Definition: nusoap.php:4591
parametersMatchWrapped($type, &$parameters)
determine whether a set of parameters are unwrapped when they are expect to be wrapped,...
Definition: nusoap.php:5608
start_element($parser, $name, $attrs)
start-element handler
Definition: nusoap.php:4870
$proxyport
Definition: nusoap.php:4615
$authtype
Definition: nusoap.php:4625
end_element($parser, $name)
end-element handler
Definition: nusoap.php:5083
$parser
Definition: nusoap.php:4609
$depth_array
Definition: nusoap.php:4612
serializeComplexTypeElements($typeDef, $value, $ns, $uqType, $use='encoded', $encodingStyle=false)
serializes the elements for a complexType
Definition: nusoap.php:6242
$position
Definition: nusoap.php:4610
$schemas
Definition: nusoap.php:4589
$currentPort
Definition: nusoap.php:4601
$complexTypes
Definition: nusoap.php:4592
$curl_options
Definition: nusoap.php:4620
__construct($wsdl='', $proxyhost=false, $proxyport=false, $proxyusername=false, $proxypassword=false, $timeout=0, $response_timeout=30, $curl_options=null, $use_curl=false)
constructor
Definition: nusoap.php:4642
$response_timeout
Definition: nusoap.php:4619
addComplexType($name, $typeClass='complexType', $phpType='array', $compositor='', $restrictionBase='', $elements=array(), $attrs=array(), $arrayType='')
adds an XML Schema complex type to the WSDL types
Definition: nusoap.php:6345
addOperation($name, $in=false, $out=false, $namespace=false, $soapaction=false, $style='rpc', $use='encoded', $documentation='', $encodingStyle='')
register an operation with the server
Definition: nusoap.php:6428
$currentBinding
Definition: nusoap.php:4599
$opStatus
Definition: nusoap.php:4585
$http
Definition: deliver.php:30
$c
Definition: deliver.php:25
if($err=$client->getError()) $namespace
$_GET['cmd']
Definition: lti.php:26
if(! $DIC->user() ->getId()||!ilLTIConsumerAccess::hasCustomProviderCreationAccess()) $params
Definition: ltiregstart.php:31
$scope
Definition: ltiregstart.php:51
$path
Definition: ltiservices.php:30
if(empty($path)) $serviceName
Definition: ltiservices.php:37
$res
Definition: ltiservices.php:69
if($clientAssertionType !='urn:ietf:params:oauth:client-assertion-type:jwt-bearer'|| $grantType !='client_credentials') $parts
Definition: ltitoken.php:61
if(count($parts) !=3) $payload
Definition: ltitoken.php:67
__construct(Container $dic, ilPlugin $plugin)
@inheritDoc
Interface Observer \BackgroundTasks Contains several chained tasks and infos about them.
$a
thx to https://mlocati.github.io/php-cs-fixer-configurator for the examples
catch(\Exception $e) $req
Definition: xapiproxy.php:78
usleepWindows($usec)
sleeps some number of microseconds
Definition: nusoap.php:970
iso8601_to_timestamp($datestr)
convert ISO 8601 compliant date string to unix timestamp
Definition: nusoap.php:929
timestamp_to_iso8601($timestamp, $utc=true)
convert unix timestamp to ISO 8601 compliant date string
Definition: nusoap.php:899
$_SERVER['HTTP_HOST']
Definition: raiseError.php:26
$url
Definition: shib_logout.php:70
$GLOBALS["DIC"]
Definition: wac.php:54
$param
Definition: xapitoken.php:44