ILIAS  trunk Revision v11.0_alpha-3011-gc6b235a2e85
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
1215 xml_parser_free($this->parser);
1216 } else {
1217 $this->debug('no xml passed to parseString()!!');
1218 $this->setError('no xml passed to parseString()!!');
1219 }
1220 }
1221
1229 public function CreateTypeName($ename)
1230 {
1231 $scope = '';
1232 for ($i = 0; $i < count($this->complexTypeStack); $i++) {
1233 $scope .= $this->complexTypeStack[$i] . '_';
1234 }
1235 return $scope . $ename . '_ContainedType';
1236 }
1237
1246 public function schemaStartElement($parser, $name, $attrs)
1247 {
1248
1249 // position in the total number of elements, starting from 0
1250 $pos = $this->position++;
1251 $depth = $this->depth++;
1252 // set self as current value for this depth
1253 $this->depth_array[$depth] = $pos;
1254 $this->message[$pos] = array('cdata' => '');
1255 if ($depth > 0) {
1256 $this->defaultNamespace[$pos] = $this->defaultNamespace[$this->depth_array[$depth - 1]];
1257 } else {
1258 $this->defaultNamespace[$pos] = false;
1259 }
1260
1261 // get element prefix
1262 if ($prefix = $this->getPrefix($name)) {
1263 // get unqualified name
1264 $name = $this->getLocalPart($name);
1265 } else {
1266 $prefix = '';
1267 }
1268
1269 // loop thru attributes, expanding, and registering namespace declarations
1270 if (count($attrs) > 0) {
1271 foreach ($attrs as $k => $v) {
1272 // if ns declarations, add to class level array of valid namespaces
1273 if (preg_match('/^xmlns/', $k)) {
1274 //$this->xdebug("$k: $v");
1275 //$this->xdebug('ns_prefix: '.$this->getPrefix($k));
1276 if ($ns_prefix = substr(strrchr($k, ':'), 1)) {
1277 //$this->xdebug("Add namespace[$ns_prefix] = $v");
1278 $this->namespaces[$ns_prefix] = $v;
1279 } else {
1280 $this->defaultNamespace[$pos] = $v;
1281 if (! $this->getPrefixFromNamespace($v)) {
1282 $this->namespaces['ns' . (count($this->namespaces) + 1)] = $v;
1283 }
1284 }
1285 if ($v == 'http://www.w3.org/2001/XMLSchema' || $v == 'http://www.w3.org/1999/XMLSchema' || $v == 'http://www.w3.org/2000/10/XMLSchema') {
1286 $this->XMLSchemaVersion = $v;
1287 $this->namespaces['xsi'] = $v . '-instance';
1288 }
1289 }
1290 }
1291 foreach ($attrs as $k => $v) {
1292 // expand each attribute
1293 $k = strpos($k, ':') ? $this->expandQname($k) : $k;
1294 $v = strpos($v, ':') ? $this->expandQname($v) : $v;
1295 $eAttrs[$k] = $v;
1296 }
1297 $attrs = $eAttrs;
1298 } else {
1299 $attrs = array();
1300 }
1301 // find status, register data
1302 switch ($name) {
1303 case 'all': // (optional) compositor content for a complexType
1304 case 'choice':
1305 case 'group':
1306 case 'sequence':
1307 //$this->xdebug("compositor $name for currentComplexType: $this->currentComplexType and currentElement: $this->currentElement");
1308 $this->complexTypes[$this->currentComplexType]['compositor'] = $name;
1309 //if($name == 'all' || $name == 'sequence'){
1310 // $this->complexTypes[$this->currentComplexType]['phpType'] = 'struct';
1311 //}
1312 break;
1313 case 'attribute': // complexType attribute
1314 //$this->xdebug("parsing attribute $attrs[name] $attrs[ref] of value: ".$attrs['http://schemas.xmlsoap.org/wsdl/:arrayType']);
1315 $this->xdebug("parsing attribute:");
1316 $this->appendDebug($this->varDump($attrs));
1317 if (!isset($attrs['form'])) {
1318 $attrs['form'] = $this->schemaInfo['attributeFormDefault'];
1319 }
1320 if (isset($attrs['http://schemas.xmlsoap.org/wsdl/:arrayType'])) {
1321 $v = $attrs['http://schemas.xmlsoap.org/wsdl/:arrayType'];
1322 if (!strpos($v, ':')) {
1323 // no namespace in arrayType attribute value...
1324 if ($this->defaultNamespace[$pos]) {
1325 // ...so use the default
1326 $attrs['http://schemas.xmlsoap.org/wsdl/:arrayType'] = $this->defaultNamespace[$pos] . ':' . $attrs['http://schemas.xmlsoap.org/wsdl/:arrayType'];
1327 }
1328 }
1329 }
1330 if (isset($attrs['name'])) {
1331 $this->attributes[$attrs['name']] = $attrs;
1332 $aname = $attrs['name'];
1333 } elseif (isset($attrs['ref']) && $attrs['ref'] == 'http://schemas.xmlsoap.org/soap/encoding/:arrayType') {
1334 if (isset($attrs['http://schemas.xmlsoap.org/wsdl/:arrayType'])) {
1335 $aname = $attrs['http://schemas.xmlsoap.org/wsdl/:arrayType'];
1336 } else {
1337 $aname = '';
1338 }
1339 } elseif (isset($attrs['ref'])) {
1340 $aname = $attrs['ref'];
1341 $this->attributes[$attrs['ref']] = $attrs;
1342 }
1343
1344 if ($this->currentComplexType) { // This should *always* be
1345 $this->complexTypes[$this->currentComplexType]['attrs'][$aname] = $attrs;
1346 }
1347 // arrayType attribute
1348 if (isset($attrs['http://schemas.xmlsoap.org/wsdl/:arrayType']) || $this->getLocalPart($aname) == 'arrayType') {
1349 $this->complexTypes[$this->currentComplexType]['phpType'] = 'array';
1350 $prefix = $this->getPrefix($aname);
1351 if (isset($attrs['http://schemas.xmlsoap.org/wsdl/:arrayType'])) {
1352 $v = $attrs['http://schemas.xmlsoap.org/wsdl/:arrayType'];
1353 } else {
1354 $v = '';
1355 }
1356 if (strpos($v, '[,]')) {
1357 $this->complexTypes[$this->currentComplexType]['multidimensional'] = true;
1358 }
1359 $v = substr($v, 0, strpos($v, '[')); // clip the []
1360 if (!strpos($v, ':') && isset($this->typemap[$this->XMLSchemaVersion][$v])) {
1361 $v = $this->XMLSchemaVersion . ':' . $v;
1362 }
1363 $this->complexTypes[$this->currentComplexType]['arrayType'] = $v;
1364 }
1365 break;
1366 case 'complexContent': // (optional) content for a complexType
1367 break;
1368 case 'complexType':
1369 array_push($this->complexTypeStack, $this->currentComplexType);
1370 if (isset($attrs['name'])) {
1371 // TODO: what is the scope of named complexTypes that appear
1372 // nested within other c complexTypes?
1373 $this->xdebug('processing named complexType ' . $attrs['name']);
1374 //$this->currentElement = false;
1375 $this->currentComplexType = $attrs['name'];
1376 $this->complexTypes[$this->currentComplexType] = $attrs;
1377 $this->complexTypes[$this->currentComplexType]['typeClass'] = 'complexType';
1378 // This is for constructs like
1379 // <complexType name="ListOfString" base="soap:Array">
1380 // <sequence>
1381 // <element name="string" type="xsd:string"
1382 // minOccurs="0" maxOccurs="unbounded" />
1383 // </sequence>
1384 // </complexType>
1385 if (isset($attrs['base']) && preg_match('/:Array$/', $attrs['base'])) {
1386 $this->xdebug('complexType is unusual array');
1387 $this->complexTypes[$this->currentComplexType]['phpType'] = 'array';
1388 } else {
1389 $this->complexTypes[$this->currentComplexType]['phpType'] = 'struct';
1390 }
1391 } else {
1392 $name = $this->CreateTypeName($this->currentElement);
1393 $this->xdebug('processing unnamed complexType for element ' . $this->currentElement . ' named ' . $name);
1394 $this->currentComplexType = $name;
1395 //$this->currentElement = false;
1396 $this->complexTypes[$this->currentComplexType] = $attrs;
1397 $this->complexTypes[$this->currentComplexType]['typeClass'] = 'complexType';
1398 // This is for constructs like
1399 // <complexType name="ListOfString" base="soap:Array">
1400 // <sequence>
1401 // <element name="string" type="xsd:string"
1402 // minOccurs="0" maxOccurs="unbounded" />
1403 // </sequence>
1404 // </complexType>
1405 if (isset($attrs['base']) && preg_match('/:Array$/', $attrs['base'])) {
1406 $this->xdebug('complexType is unusual array');
1407 $this->complexTypes[$this->currentComplexType]['phpType'] = 'array';
1408 } else {
1409 $this->complexTypes[$this->currentComplexType]['phpType'] = 'struct';
1410 }
1411 }
1412 break;
1413 case 'element':
1414 array_push($this->elementStack, $this->currentElement);
1415 if (!isset($attrs['form'])) {
1416 $attrs['form'] = $this->schemaInfo['elementFormDefault'];
1417 }
1418 if (isset($attrs['type'])) {
1419 $this->xdebug("processing typed element " . $attrs['name'] . " of type " . $attrs['type']);
1420 if (! $this->getPrefix($attrs['type'])) {
1421 if ($this->defaultNamespace[$pos]) {
1422 $attrs['type'] = $this->defaultNamespace[$pos] . ':' . $attrs['type'];
1423 $this->xdebug('used default namespace to make type ' . $attrs['type']);
1424 }
1425 }
1426 // This is for constructs like
1427 // <complexType name="ListOfString" base="soap:Array">
1428 // <sequence>
1429 // <element name="string" type="xsd:string"
1430 // minOccurs="0" maxOccurs="unbounded" />
1431 // </sequence>
1432 // </complexType>
1433 if ($this->currentComplexType && $this->complexTypes[$this->currentComplexType]['phpType'] == 'array') {
1434 $this->xdebug('arrayType for unusual array is ' . $attrs['type']);
1435 $this->complexTypes[$this->currentComplexType]['arrayType'] = $attrs['type'];
1436 }
1437 $this->currentElement = $attrs['name'];
1438 $ename = $attrs['name'];
1439 } elseif (isset($attrs['ref'])) {
1440 $this->xdebug("processing element as ref to " . $attrs['ref']);
1441 $this->currentElement = "ref to " . $attrs['ref'];
1442 $ename = $this->getLocalPart($attrs['ref']);
1443 } else {
1444 $type = $this->CreateTypeName($this->currentComplexType . '_' . $attrs['name']);
1445 $this->xdebug("processing untyped element " . $attrs['name'] . ' type ' . $type);
1446 $this->currentElement = $attrs['name'];
1447 $attrs['type'] = $this->schemaTargetNamespace . ':' . $type;
1448 $ename = $attrs['name'];
1449 }
1450 if (isset($ename) && $this->currentComplexType) {
1451 $this->xdebug("add element $ename to complexType $this->currentComplexType");
1452 $this->complexTypes[$this->currentComplexType]['elements'][$ename] = $attrs;
1453 } elseif (!isset($attrs['ref'])) {
1454 $this->xdebug("add element $ename to elements array");
1455 $this->elements[ $attrs['name'] ] = $attrs;
1456 $this->elements[ $attrs['name'] ]['typeClass'] = 'element';
1457 }
1458 break;
1459 case 'enumeration': // restriction value list member
1460 $this->xdebug('enumeration ' . $attrs['value']);
1461 if ($this->currentSimpleType) {
1462 $this->simpleTypes[$this->currentSimpleType]['enumeration'][] = $attrs['value'];
1463 } elseif ($this->currentComplexType) {
1464 $this->complexTypes[$this->currentComplexType]['enumeration'][] = $attrs['value'];
1465 }
1466 break;
1467 case 'extension': // simpleContent or complexContent type extension
1468 $this->xdebug('extension ' . $attrs['base']);
1469 if ($this->currentComplexType) {
1470 $this->complexTypes[$this->currentComplexType]['extensionBase'] = $attrs['base'];
1471 }
1472 break;
1473 case 'import':
1474 if (isset($attrs['schemaLocation'])) {
1475 //$this->xdebug('import namespace ' . $attrs['namespace'] . ' from ' . $attrs['schemaLocation']);
1476 $this->imports[$attrs['namespace']][] = array('location' => $attrs['schemaLocation'], 'loaded' => false);
1477 } else {
1478 //$this->xdebug('import namespace ' . $attrs['namespace']);
1479 $this->imports[$attrs['namespace']][] = array('location' => '', 'loaded' => true);
1480 if (! $this->getPrefixFromNamespace($attrs['namespace'])) {
1481 $this->namespaces['ns' . (count($this->namespaces) + 1)] = $attrs['namespace'];
1482 }
1483 }
1484 break;
1485 case 'list': // simpleType value list
1486 break;
1487 case 'restriction': // simpleType, simpleContent or complexContent value restriction
1488 $this->xdebug('restriction ' . $attrs['base']);
1489 if ($this->currentSimpleType) {
1490 $this->simpleTypes[$this->currentSimpleType]['type'] = $attrs['base'];
1491 } elseif ($this->currentComplexType) {
1492 $this->complexTypes[$this->currentComplexType]['restrictionBase'] = $attrs['base'];
1493 if (strstr($attrs['base'], ':') == ':Array') {
1494 $this->complexTypes[$this->currentComplexType]['phpType'] = 'array';
1495 }
1496 }
1497 break;
1498 case 'schema':
1499 $this->schemaInfo = $attrs;
1500 $this->schemaInfo['schemaVersion'] = $this->getNamespaceFromPrefix($prefix);
1501 if (isset($attrs['targetNamespace'])) {
1502 $this->schemaTargetNamespace = $attrs['targetNamespace'];
1503 }
1504 if (!isset($attrs['elementFormDefault'])) {
1505 $this->schemaInfo['elementFormDefault'] = 'unqualified';
1506 }
1507 if (!isset($attrs['attributeFormDefault'])) {
1508 $this->schemaInfo['attributeFormDefault'] = 'unqualified';
1509 }
1510 break;
1511 case 'simpleContent': // (optional) content for a complexType
1512 break;
1513 case 'simpleType':
1514 array_push($this->simpleTypeStack, $this->currentSimpleType);
1515 if (isset($attrs['name'])) {
1516 $this->xdebug("processing simpleType for name " . $attrs['name']);
1517 $this->currentSimpleType = $attrs['name'];
1518 $this->simpleTypes[ $attrs['name'] ] = $attrs;
1519 $this->simpleTypes[ $attrs['name'] ]['typeClass'] = 'simpleType';
1520 $this->simpleTypes[ $attrs['name'] ]['phpType'] = 'scalar';
1521 } else {
1522 $name = $this->CreateTypeName($this->currentComplexType . '_' . $this->currentElement);
1523 $this->xdebug('processing unnamed simpleType for element ' . $this->currentElement . ' named ' . $name);
1524 $this->currentSimpleType = $name;
1525 //$this->currentElement = false;
1526 $this->simpleTypes[$this->currentSimpleType] = $attrs;
1527 $this->simpleTypes[$this->currentSimpleType]['phpType'] = 'scalar';
1528 }
1529 break;
1530 case 'union': // simpleType type list
1531 break;
1532 default:
1533 //$this->xdebug("do not have anything to do for element $name");
1534 }
1535 }
1536
1544 public function schemaEndElement($parser, $name)
1545 {
1546 // bring depth down a notch
1547 $this->depth--;
1548 // position of current element is equal to the last value left in depth_array for my depth
1549 if (isset($this->depth_array[$this->depth])) {
1550 $pos = $this->depth_array[$this->depth];
1551 }
1552 // get element prefix
1553 if ($prefix = $this->getPrefix($name)) {
1554 // get unqualified name
1555 $name = $this->getLocalPart($name);
1556 } else {
1557 $prefix = '';
1558 }
1559 // move on...
1560 if ($name == 'complexType') {
1561 $this->xdebug('done processing complexType ' . ($this->currentComplexType ? $this->currentComplexType : '(unknown)'));
1562 $this->currentComplexType = array_pop($this->complexTypeStack);
1563 //$this->currentElement = false;
1564 }
1565 if ($name == 'element') {
1566 $this->xdebug('done processing element ' . ($this->currentElement ? $this->currentElement : '(unknown)'));
1567 $this->currentElement = array_pop($this->elementStack);
1568 }
1569 if ($name == 'simpleType') {
1570 $this->xdebug('done processing simpleType ' . ($this->currentSimpleType ? $this->currentSimpleType : '(unknown)'));
1571 $this->currentSimpleType = array_pop($this->simpleTypeStack);
1572 }
1573 }
1574
1583 {
1584 $pos = $this->depth_array[$this->depth - 1];
1585 $this->message[$pos]['cdata'] .= $data;
1586 }
1587
1593 public function serializeSchema()
1594 {
1595 $schemaPrefix = $this->getPrefixFromNamespace($this->XMLSchemaVersion);
1596 $xml = '';
1597 // imports
1598 if (sizeof($this->imports) > 0) {
1599 foreach ($this->imports as $ns => $list) {
1600 foreach ($list as $ii) {
1601 if ($ii['location'] != '') {
1602 $xml .= " <$schemaPrefix:import location=\"" . $ii['location'] . '" namespace="' . $ns . "\" />\n";
1603 } else {
1604 $xml .= " <$schemaPrefix:import namespace=\"" . $ns . "\" />\n";
1605 }
1606 }
1607 }
1608 }
1609 // complex types
1610 foreach ($this->complexTypes as $typeName => $attrs) {
1611 $contentStr = '';
1612 // serialize child elements
1613 if (isset($attrs['elements']) && (count($attrs['elements']) > 0)) {
1614 foreach ($attrs['elements'] as $element => $eParts) {
1615 if (isset($eParts['ref'])) {
1616 $contentStr .= " <$schemaPrefix:element ref=\"$element\"/>\n";
1617 } else {
1618 $contentStr .= " <$schemaPrefix:element name=\"$element\" type=\"" . $this->contractQName($eParts['type']) . "\"";
1619 foreach ($eParts as $aName => $aValue) {
1620 // handle, e.g., abstract, default, form, minOccurs, maxOccurs, nillable
1621 if ($aName != 'name' && $aName != 'type') {
1622 $contentStr .= " $aName=\"$aValue\"";
1623 }
1624 }
1625 $contentStr .= "/>\n";
1626 }
1627 }
1628 // compositor wraps elements
1629 if (isset($attrs['compositor']) && ($attrs['compositor'] != '')) {
1630 $contentStr = " <$schemaPrefix:$attrs[compositor]>\n" . $contentStr . " </$schemaPrefix:$attrs[compositor]>\n";
1631 }
1632 }
1633 // attributes
1634 if (isset($attrs['attrs']) && (count($attrs['attrs']) >= 1)) {
1635 foreach ($attrs['attrs'] as $attr => $aParts) {
1636 $contentStr .= " <$schemaPrefix:attribute";
1637 foreach ($aParts as $a => $v) {
1638 if ($a == 'ref' || $a == 'type') {
1639 $contentStr .= " $a=\"" . $this->contractQName($v) . '"';
1640 } elseif ($a == 'http://schemas.xmlsoap.org/wsdl/:arrayType') {
1641 $this->usedNamespaces['wsdl'] = $this->namespaces['wsdl'];
1642 $contentStr .= ' wsdl:arrayType="' . $this->contractQName($v) . '"';
1643 } else {
1644 $contentStr .= " $a=\"$v\"";
1645 }
1646 }
1647 $contentStr .= "/>\n";
1648 }
1649 }
1650 // if restriction
1651 if (isset($attrs['restrictionBase']) && $attrs['restrictionBase'] != '') {
1652 $contentStr = " <$schemaPrefix:restriction base=\"" . $this->contractQName($attrs['restrictionBase']) . "\">\n" . $contentStr . " </$schemaPrefix:restriction>\n";
1653 // complex or simple content
1654 if ((isset($attrs['elements']) && count($attrs['elements']) > 0) || (isset($attrs['attrs']) && count($attrs['attrs']) > 0)) {
1655 $contentStr = " <$schemaPrefix:complexContent>\n" . $contentStr . " </$schemaPrefix:complexContent>\n";
1656 }
1657 }
1658 // finalize complex type
1659 if ($contentStr != '') {
1660 $contentStr = " <$schemaPrefix:complexType name=\"$typeName\">\n" . $contentStr . " </$schemaPrefix:complexType>\n";
1661 } else {
1662 $contentStr = " <$schemaPrefix:complexType name=\"$typeName\"/>\n";
1663 }
1664 $xml .= $contentStr;
1665 }
1666 // simple types
1667 if (isset($this->simpleTypes) && count($this->simpleTypes) > 0) {
1668 foreach ($this->simpleTypes as $typeName => $eParts) {
1669 $xml .= " <$schemaPrefix:simpleType name=\"$typeName\">\n <$schemaPrefix:restriction base=\"" . $this->contractQName($eParts['type']) . "\">\n";
1670 if (isset($eParts['enumeration'])) {
1671 foreach ($eParts['enumeration'] as $e) {
1672 $xml .= " <$schemaPrefix:enumeration value=\"$e\"/>\n";
1673 }
1674 }
1675 $xml .= " </$schemaPrefix:restriction>\n </$schemaPrefix:simpleType>";
1676 }
1677 }
1678 // elements
1679 if (isset($this->elements) && count($this->elements) > 0) {
1680 foreach ($this->elements as $element => $eParts) {
1681 $xml .= " <$schemaPrefix:element name=\"$element\" type=\"" . $this->contractQName($eParts['type']) . "\"/>\n";
1682 }
1683 }
1684 // attributes
1685 if (isset($this->attributes) && count($this->attributes) > 0) {
1686 foreach ($this->attributes as $attr => $aParts) {
1687 $xml .= " <$schemaPrefix:attribute name=\"$attr\" type=\"" . $this->contractQName($aParts['type']) . "\"\n/>";
1688 }
1689 }
1690 // finish 'er up
1691 $attr = '';
1692 foreach ($this->schemaInfo as $k => $v) {
1693 if ($k == 'elementFormDefault' || $k == 'attributeFormDefault') {
1694 $attr .= " $k=\"$v\"";
1695 }
1696 }
1697 $el = "<$schemaPrefix:schema$attr targetNamespace=\"$this->schemaTargetNamespace\"\n";
1698 foreach (array_diff($this->usedNamespaces, $this->enclosingNamespaces) as $nsp => $ns) {
1699 $el .= " xmlns:$nsp=\"$ns\"";
1700 }
1701 $xml = $el . ">\n" . $xml . "</$schemaPrefix:schema>\n";
1702 return $xml;
1703 }
1704
1711 public function xdebug($string)
1712 {
1713 $this->debug('<' . $this->schemaTargetNamespace . '> ' . $string);
1714 }
1715
1728 public function getPHPType($type, $ns)
1729 {
1730 if (isset($this->typemap[$ns][$type])) {
1731 //print "found type '$type' and ns $ns in typemap<br>";
1732 return $this->typemap[$ns][$type];
1733 } elseif (isset($this->complexTypes[$type])) {
1734 //print "getting type '$type' and ns $ns from complexTypes array<br>";
1735 return $this->complexTypes[$type]['phpType'];
1736 }
1737 return false;
1738 }
1739
1762 public function getTypeDef($type)
1763 {
1764 //$this->debug("in getTypeDef for type $type");
1765 if (substr($type, -1) == '^') {
1766 $is_element = 1;
1767 $type = substr($type, 0, -1);
1768 } else {
1769 $is_element = 0;
1770 }
1771
1772 if ((! $is_element) && isset($this->complexTypes[$type])) {
1773 $this->xdebug("in getTypeDef, found complexType $type");
1774 return $this->complexTypes[$type];
1775 } elseif ((! $is_element) && isset($this->simpleTypes[$type])) {
1776 $this->xdebug("in getTypeDef, found simpleType $type");
1777 if (!isset($this->simpleTypes[$type]['phpType'])) {
1778 // get info for type to tack onto the simple type
1779 // TODO: can this ever really apply (i.e. what is a simpleType really?)
1780 $uqType = substr($this->simpleTypes[$type]['type'], strrpos($this->simpleTypes[$type]['type'], ':') + 1);
1781 $ns = substr($this->simpleTypes[$type]['type'], 0, strrpos($this->simpleTypes[$type]['type'], ':'));
1782 $etype = $this->getTypeDef($uqType);
1783 if ($etype) {
1784 $this->xdebug("in getTypeDef, found type for simpleType $type:");
1785 $this->xdebug($this->varDump($etype));
1786 if (isset($etype['phpType'])) {
1787 $this->simpleTypes[$type]['phpType'] = $etype['phpType'];
1788 }
1789 if (isset($etype['elements'])) {
1790 $this->simpleTypes[$type]['elements'] = $etype['elements'];
1791 }
1792 }
1793 }
1794 return $this->simpleTypes[$type];
1795 } elseif (isset($this->elements[$type])) {
1796 $this->xdebug("in getTypeDef, found element $type");
1797 if (!isset($this->elements[$type]['phpType'])) {
1798 // get info for type to tack onto the element
1799 $uqType = substr($this->elements[$type]['type'], strrpos($this->elements[$type]['type'], ':') + 1);
1800 $ns = substr($this->elements[$type]['type'], 0, strrpos($this->elements[$type]['type'], ':'));
1801 $etype = $this->getTypeDef($uqType);
1802 if ($etype) {
1803 $this->xdebug("in getTypeDef, found type for element $type:");
1804 $this->xdebug($this->varDump($etype));
1805 if (isset($etype['phpType'])) {
1806 $this->elements[$type]['phpType'] = $etype['phpType'];
1807 }
1808 if (isset($etype['elements'])) {
1809 $this->elements[$type]['elements'] = $etype['elements'];
1810 }
1811 } elseif ($ns == 'http://www.w3.org/2001/XMLSchema') {
1812 $this->xdebug("in getTypeDef, element $type is an XSD type");
1813 $this->elements[$type]['phpType'] = 'scalar';
1814 }
1815 }
1816 return $this->elements[$type];
1817 } elseif (isset($this->attributes[$type])) {
1818 $this->xdebug("in getTypeDef, found attribute $type");
1819 return $this->attributes[$type];
1820 } elseif (preg_match('/_ContainedType$/', $type)) {
1821 $this->xdebug("in getTypeDef, have an untyped element $type");
1822 $typeDef['typeClass'] = 'simpleType';
1823 $typeDef['phpType'] = 'scalar';
1824 $typeDef['type'] = 'http://www.w3.org/2001/XMLSchema:string';
1825 return $typeDef;
1826 }
1827 $this->xdebug("in getTypeDef, did not find $type");
1828 return false;
1829 }
1830
1839 public function serializeTypeDef($type)
1840 {
1841 //print "in sTD() for type $type<br>";
1842 if ($typeDef = $this->getTypeDef($type)) {
1843 $str .= '<' . $type;
1844 if (is_array($typeDef['attrs'])) {
1845 foreach ($typeDef['attrs'] as $attName => $data) {
1846 $str .= " $attName=\"{type = " . $data['type'] . "}\"";
1847 }
1848 }
1849 $str .= " xmlns=\"" . $this->schema['targetNamespace'] . "\"";
1850 if (count($typeDef['elements']) > 0) {
1851 $str .= ">";
1852 foreach ($typeDef['elements'] as $element => $eData) {
1853 $str .= $this->serializeTypeDef($element);
1854 }
1855 $str .= "</$type>";
1856 } elseif ($typeDef['typeClass'] == 'element') {
1857 $str .= "></$type>";
1858 } else {
1859 $str .= "/>";
1860 }
1861 return $str;
1862 }
1863 return false;
1864 }
1865
1876 public function typeToForm($name, $type)
1877 {
1878 // get typedef
1879 if ($typeDef = $this->getTypeDef($type)) {
1880 // if struct
1881 if ($typeDef['phpType'] == 'struct') {
1882 $buffer .= '<table>';
1883 foreach ($typeDef['elements'] as $child => $childDef) {
1884 $buffer .= "
1885 <tr><td align='right'>$childDef[name] (type: " . $this->getLocalPart($childDef['type']) . "):</td>
1886 <td><input type='text' name='parameters[" . $name . "][$childDef[name]]'></td></tr>";
1887 }
1888 $buffer .= '</table>';
1889 // if array
1890 } elseif ($typeDef['phpType'] == 'array') {
1891 $buffer .= '<table>';
1892 for ($i = 0;$i < 3; $i++) {
1893 $buffer .= "
1894 <tr><td align='right'>array item (type: $typeDef[arrayType]):</td>
1895 <td><input type='text' name='parameters[" . $name . "][]'></td></tr>";
1896 }
1897 $buffer .= '</table>';
1898 // if scalar
1899 } else {
1900 $buffer .= "<input type='text' name='parameters[$name]'>";
1901 }
1902 } else {
1903 $buffer .= "<input type='text' name='parameters[$name]'>";
1904 }
1905 return $buffer;
1906 }
1907
1949 public function addComplexType($name, $typeClass = 'complexType', $phpType = 'array', $compositor = '', $restrictionBase = '', $elements = array(), $attrs = array(), $arrayType = '')
1950 {
1951 $this->complexTypes[$name] = array(
1952 'name' => $name,
1953 'typeClass' => $typeClass,
1954 'phpType' => $phpType,
1955 'compositor' => $compositor,
1956 'restrictionBase' => $restrictionBase,
1957 'elements' => $elements,
1958 'attrs' => $attrs,
1959 'arrayType' => $arrayType
1960 );
1961
1962 $this->xdebug("addComplexType $name:");
1963 $this->appendDebug($this->varDump($this->complexTypes[$name]));
1964 }
1965
1978 public function addSimpleType($name, $restrictionBase = '', $typeClass = 'simpleType', $phpType = 'scalar', $enumeration = array())
1979 {
1980 $this->simpleTypes[$name] = array(
1981 'name' => $name,
1982 'typeClass' => $typeClass,
1983 'phpType' => $phpType,
1984 'type' => $restrictionBase,
1985 'enumeration' => $enumeration
1986 );
1987
1988 $this->xdebug("addSimpleType $name:");
1989 $this->appendDebug($this->varDump($this->simpleTypes[$name]));
1990 }
1991
1999 public function addElement($attrs)
2000 {
2001 if (! $this->getPrefix($attrs['type'])) {
2002 $attrs['type'] = $this->schemaTargetNamespace . ':' . $attrs['type'];
2003 }
2004 $this->elements[ $attrs['name'] ] = $attrs;
2005 $this->elements[ $attrs['name'] ]['typeClass'] = 'element';
2006
2007 $this->xdebug("addElement " . $attrs['name']);
2008 $this->appendDebug($this->varDump($this->elements[ $attrs['name'] ]));
2009 }
2010}
2011
2016{
2017}
2018
2019?><?php
2020
2021
2022
2035{
2042 public $name;
2049 public $type;
2056 public $value;
2070 public $type_ns;
2078
2090 public function __construct($name = 'soapval', $type = false, $value = -1, $element_ns = false, $type_ns = false, $attributes = false)
2091 {
2093 $this->name = $name;
2094 $this->type = $type;
2095 $this->value = $value;
2096 $this->element_ns = $element_ns;
2097 $this->type_ns = $type_ns;
2098 $this->attributes = $attributes;
2099 }
2100
2108 public function serialize($use = 'encoded')
2109 {
2110 return $this->serialize_val($this->value, $this->name, $this->type, $this->element_ns, $this->type_ns, $this->attributes, $use, true);
2111 }
2112
2119 public function decode()
2120 {
2121 return $this->value;
2122 }
2123}
2124
2125
2126
2127?><?php
2128
2129
2130
2141{
2142 public $fp;
2144 public $url = '';
2145 public $uri = '';
2146 public $digest_uri = '';
2147 public $scheme = '';
2148 public $host = '';
2149 public $port = '';
2150 public $path = '';
2151 public $request_method = 'POST';
2152 public $protocol_version = '1.0';
2153 public $encoding = '';
2154 public $outgoing_headers = array();
2155 public $incoming_headers = array();
2156 public $incoming_cookies = array();
2159 public $response_status_line; // HTTP response status line
2160 public $useSOAPAction = true;
2162 public $ch = false; // cURL handle
2163 public $ch_options = array(); // cURL custom options
2164 public $use_curl = false; // force cURL use
2165 public $proxy = null; // proxy information (associative array)
2166 public $username = '';
2167 public $password = '';
2168 public $authtype = '';
2169 public $digestRequest = array();
2170 public $certRequest = array(); // keys must be cainfofile (optional), sslcertfile, sslkeyfile, passphrase, certpassword (optional), verifypeer (optional), verifyhost (optional)
2171 // cainfofile: certificate authority file, e.g. '$pathToPemFiles/rootca.pem'
2172 // sslcertfile: SSL certificate file, e.g. '$pathToPemFiles/mycert.pem'
2173 // sslkeyfile: SSL key file, e.g. '$pathToPemFiles/mykey.pem'
2174 // passphrase: SSL key password/passphrase
2175 // certpassword: SSL certificate password
2176 // verifypeer: default is 1
2177 // verifyhost: default is 1
2178
2187 public function __construct($url, $curl_options = null, $use_curl = false)
2188 {
2190 $this->debug("ctor url=$url use_curl=$use_curl curl_options:");
2191 $this->appendDebug($this->varDump($curl_options));
2192 $this->setURL($url);
2193 if (is_array($curl_options)) {
2194 $this->ch_options = $curl_options;
2195 }
2196 $this->use_curl = $use_curl;
2197 preg_match('/\$Revisio' . 'n: ([^ ]+)/', $this->revision, $rev);
2198 // begin-patch php8
2199 $this->setHeader('User-Agent', $this->title . '/' . $this->version . ' (' . ($rev[1] ?? '1.1') . ')');
2200 }
2201
2209 public function setCurlOption($option, $value)
2210 {
2211 $this->debug("setCurlOption option=$option, value=");
2212 $this->appendDebug($this->varDump($value));
2213 curl_setopt($this->ch, $option, $value);
2214 }
2215
2223 public function setHeader($name, $value)
2224 {
2225 $this->outgoing_headers[$name] = $value;
2226 $this->debug("set header $name: $value");
2227 }
2228
2235 public function unsetHeader($name)
2236 {
2237 if (isset($this->outgoing_headers[$name])) {
2238 $this->debug("unset header $name");
2239 unset($this->outgoing_headers[$name]);
2240 }
2241 }
2242
2249 public function setURL($url)
2250 {
2251 $this->url = $url;
2252
2253 $u = parse_url($url);
2254 foreach ($u as $k => $v) {
2255 $this->debug("parsed URL $k = $v");
2256 $this->$k = $v;
2257 }
2258
2259 // add any GET params to path
2260 if (isset($u['query']) && $u['query'] != '') {
2261 $this->path .= '?' . $u['query'];
2262 }
2263
2264 // set default port
2265 if (!isset($u['port'])) {
2266 if ($u['scheme'] == 'https') {
2267 $this->port = 443;
2268 } else {
2269 $this->port = 80;
2270 }
2271 }
2272
2273 $this->uri = $this->path;
2274 $this->digest_uri = $this->uri;
2275
2276 // build headers
2277 if (!isset($u['port'])) {
2278 $this->setHeader('Host', $this->host);
2279 } else {
2280 $this->setHeader('Host', $this->host . ':' . $this->port);
2281 }
2282
2283 if (isset($u['user']) && $u['user'] != '') {
2284 $this->setCredentials(urldecode($u['user']), isset($u['pass']) ? urldecode($u['pass']) : '');
2285 }
2286 }
2287
2294 public function io_method()
2295 {
2296 if ($this->use_curl || ($this->scheme == 'https') || ($this->scheme == 'http' && $this->authtype == 'ntlm') || ($this->scheme == 'http' && is_array($this->proxy) && $this->proxy['authtype'] == 'ntlm')) {
2297 return 'curl';
2298 }
2299 if (($this->scheme == 'http' || $this->scheme == 'ssl') && $this->authtype != 'ntlm' && (!is_array($this->proxy) || $this->proxy['authtype'] != 'ntlm')) {
2300 return 'socket';
2301 }
2302 return 'unknown';
2303 }
2304
2313 public function connect($connection_timeout = 0, $response_timeout = 30)
2314 {
2315 // For PHP 4.3 with OpenSSL, change https scheme to ssl, then treat like
2316 // "regular" socket.
2317 // TODO: disabled for now because OpenSSL must be *compiled* in (not just
2318 // loaded), and until PHP5 stream_get_wrappers is not available.
2319 // if ($this->scheme == 'https') {
2320 // if (version_compare(phpversion(), '4.3.0') >= 0) {
2321 // if (extension_loaded('openssl')) {
2322 // $this->scheme = 'ssl';
2323 // $this->debug('Using SSL over OpenSSL');
2324 // }
2325 // }
2326 // }
2327 $this->debug("connect connection_timeout $connection_timeout, response_timeout $response_timeout, scheme $this->scheme, host $this->host, port $this->port");
2328 if ($this->io_method() == 'socket') {
2329 if (!is_array($this->proxy)) {
2332 } else {
2333 $host = $this->proxy['host'];
2334 $port = $this->proxy['port'];
2335 }
2336
2337 // use persistent connection
2338 if ($this->persistentConnection && isset($this->fp) && is_resource($this->fp)) {
2339 if (!feof($this->fp)) {
2340 $this->debug('Re-use persistent connection');
2341 return true;
2342 }
2343 fclose($this->fp);
2344 $this->debug('Closed persistent connection at EOF');
2345 }
2346
2347 // munge host if using OpenSSL
2348 if ($this->scheme == 'ssl') {
2349 $host = 'ssl://' . $host;
2350 }
2351 $this->debug('calling fsockopen with host ' . $host . ' connection_timeout ' . $connection_timeout);
2352
2353 // open socket
2354 if ($connection_timeout > 0) {
2355 $this->fp = @fsockopen($host, $this->port, $this->errno, $this->error_str, $connection_timeout);
2356 } else {
2357 $this->fp = @fsockopen($host, $this->port, $this->errno, $this->error_str);
2358 }
2359
2360 // test pointer
2361 if (!$this->fp) {
2362 $msg = 'Couldn\'t open socket connection to server ' . $this->url;
2363 if ($this->errno) {
2364 $msg .= ', Error (' . $this->errno . '): ' . $this->error_str;
2365 } else {
2366 $msg .= ' prior to connect(). This is often a problem looking up the host name.';
2367 }
2368 $this->debug($msg);
2369 $this->setError($msg);
2370 return false;
2371 }
2372
2373 // set response timeout
2374 $this->debug('set response timeout to ' . $response_timeout);
2375 socket_set_timeout($this->fp, $response_timeout);
2376
2377 $this->debug('socket connected');
2378 return true;
2379 } elseif ($this->io_method() == 'curl') {
2380 if (!extension_loaded('curl')) {
2381 // $this->setError('cURL Extension, or OpenSSL extension w/ PHP version >= 4.3 is required for HTTPS');
2382 $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.');
2383 return false;
2384 }
2385 // Avoid warnings when PHP does not have these options
2386 if (defined('CURLOPT_CONNECTIONTIMEOUT')) {
2387 $CURLOPT_CONNECTIONTIMEOUT = CURLOPT_CONNECTIONTIMEOUT;
2388 } else {
2389 $CURLOPT_CONNECTIONTIMEOUT = 78;
2390 }
2391 if (defined('CURLOPT_HTTPAUTH')) {
2392 $CURLOPT_HTTPAUTH = CURLOPT_HTTPAUTH;
2393 } else {
2394 $CURLOPT_HTTPAUTH = 107;
2395 }
2396 if (defined('CURLOPT_PROXYAUTH')) {
2397 $CURLOPT_PROXYAUTH = CURLOPT_PROXYAUTH;
2398 } else {
2399 $CURLOPT_PROXYAUTH = 111;
2400 }
2401 if (defined('CURLAUTH_BASIC')) {
2402 $CURLAUTH_BASIC = CURLAUTH_BASIC;
2403 } else {
2404 $CURLAUTH_BASIC = 1;
2405 }
2406 if (defined('CURLAUTH_DIGEST')) {
2407 $CURLAUTH_DIGEST = CURLAUTH_DIGEST;
2408 } else {
2409 $CURLAUTH_DIGEST = 2;
2410 }
2411 if (defined('CURLAUTH_NTLM')) {
2412 $CURLAUTH_NTLM = CURLAUTH_NTLM;
2413 } else {
2414 $CURLAUTH_NTLM = 8;
2415 }
2416
2417 $this->debug('connect using cURL');
2418 // init CURL
2419 $this->ch = curl_init();
2420 // set url
2421 $hostURL = ($this->port != '') ? "$this->scheme://$this->host:$this->port" : "$this->scheme://$this->host";
2422 // add path
2423 $hostURL .= $this->path;
2424 $this->setCurlOption(CURLOPT_URL, $hostURL);
2425 // follow location headers (re-directs)
2426 if (ini_get('safe_mode') || ini_get('open_basedir')) {
2427 $this->debug('safe_mode or open_basedir set, so do not set CURLOPT_FOLLOWLOCATION');
2428 $this->debug('safe_mode = ');
2429 $this->appendDebug($this->varDump(ini_get('safe_mode')));
2430 $this->debug('open_basedir = ');
2431 $this->appendDebug($this->varDump(ini_get('open_basedir')));
2432 } else {
2433 $this->setCurlOption(CURLOPT_FOLLOWLOCATION, 1);
2434 }
2435 // ask for headers in the response output
2436 $this->setCurlOption(CURLOPT_HEADER, 1);
2437 // ask for the response output as the return value
2438 $this->setCurlOption(CURLOPT_RETURNTRANSFER, 1);
2439 // encode
2440 // We manage this ourselves through headers and encoding
2441 // if(function_exists('gzuncompress')){
2442 // $this->setCurlOption(CURLOPT_ENCODING, 'deflate');
2443 // }
2444 // persistent connection
2445 if ($this->persistentConnection) {
2446 // I believe the following comment is now bogus, having applied to
2447 // the code when it used CURLOPT_CUSTOMREQUEST to send the request.
2448 // The way we send data, we cannot use persistent connections, since
2449 // there will be some "junk" at the end of our request.
2450 //$this->setCurlOption(CURL_HTTP_VERSION_1_1, true);
2451 $this->persistentConnection = false;
2452 $this->setHeader('Connection', 'close');
2453 }
2454 // set timeouts
2455 if ($connection_timeout != 0) {
2456 $this->setCurlOption($CURLOPT_CONNECTIONTIMEOUT, $connection_timeout);
2457 }
2458 if ($response_timeout != 0) {
2459 $this->setCurlOption(CURLOPT_TIMEOUT, $response_timeout);
2460 }
2461
2462 if ($this->scheme == 'https') {
2463 $this->debug('set cURL SSL verify options');
2464 // recent versions of cURL turn on peer/host checking by default,
2465 // while PHP binaries are not compiled with a default location for the
2466 // CA cert bundle, so disable peer/host checking.
2467 //$this->setCurlOption(CURLOPT_CAINFO, 'f:\php-4.3.2-win32\extensions\curl-ca-bundle.crt');
2468 $this->setCurlOption(CURLOPT_SSL_VERIFYPEER, 0);
2469 $this->setCurlOption(CURLOPT_SSL_VERIFYHOST, 0);
2470
2471 // support client certificates (thanks Tobias Boes, Doug Anarino, Eryan Ariobowo)
2472 if ($this->authtype == 'certificate') {
2473 $this->debug('set cURL certificate options');
2474 if (isset($this->certRequest['cainfofile'])) {
2475 $this->setCurlOption(CURLOPT_CAINFO, $this->certRequest['cainfofile']);
2476 }
2477 if (isset($this->certRequest['verifypeer'])) {
2478 $this->setCurlOption(CURLOPT_SSL_VERIFYPEER, $this->certRequest['verifypeer']);
2479 } else {
2480 $this->setCurlOption(CURLOPT_SSL_VERIFYPEER, 1);
2481 }
2482 if (isset($this->certRequest['verifyhost'])) {
2483 $this->setCurlOption(CURLOPT_SSL_VERIFYHOST, $this->certRequest['verifyhost']);
2484 } else {
2485 $this->setCurlOption(CURLOPT_SSL_VERIFYHOST, 1);
2486 }
2487 if (isset($this->certRequest['sslcertfile'])) {
2488 $this->setCurlOption(CURLOPT_SSLCERT, $this->certRequest['sslcertfile']);
2489 }
2490 if (isset($this->certRequest['sslkeyfile'])) {
2491 $this->setCurlOption(CURLOPT_SSLKEY, $this->certRequest['sslkeyfile']);
2492 }
2493 if (isset($this->certRequest['passphrase'])) {
2494 $this->setCurlOption(CURLOPT_SSLKEYPASSWD, $this->certRequest['passphrase']);
2495 }
2496 if (isset($this->certRequest['certpassword'])) {
2497 $this->setCurlOption(CURLOPT_SSLCERTPASSWD, $this->certRequest['certpassword']);
2498 }
2499 }
2500 }
2501 if ($this->authtype && ($this->authtype != 'certificate')) {
2502 if ($this->username) {
2503 $this->debug('set cURL username/password');
2504 $this->setCurlOption(CURLOPT_USERPWD, "$this->username:$this->password");
2505 }
2506 if ($this->authtype == 'basic') {
2507 $this->debug('set cURL for Basic authentication');
2508 $this->setCurlOption($CURLOPT_HTTPAUTH, $CURLAUTH_BASIC);
2509 }
2510 if ($this->authtype == 'digest') {
2511 $this->debug('set cURL for digest authentication');
2512 $this->setCurlOption($CURLOPT_HTTPAUTH, $CURLAUTH_DIGEST);
2513 }
2514 if ($this->authtype == 'ntlm') {
2515 $this->debug('set cURL for NTLM authentication');
2516 $this->setCurlOption($CURLOPT_HTTPAUTH, $CURLAUTH_NTLM);
2517 }
2518 }
2519 if (is_array($this->proxy)) {
2520 $this->debug('set cURL proxy options');
2521 if ($this->proxy['port'] != '') {
2522 $this->setCurlOption(CURLOPT_PROXY, $this->proxy['host'] . ':' . $this->proxy['port']);
2523 } else {
2524 $this->setCurlOption(CURLOPT_PROXY, $this->proxy['host']);
2525 }
2526 if ($this->proxy['username'] || $this->proxy['password']) {
2527 $this->debug('set cURL proxy authentication options');
2528 $this->setCurlOption(CURLOPT_PROXYUSERPWD, $this->proxy['username'] . ':' . $this->proxy['password']);
2529 if ($this->proxy['authtype'] == 'basic') {
2530 $this->setCurlOption($CURLOPT_PROXYAUTH, $CURLAUTH_BASIC);
2531 }
2532 if ($this->proxy['authtype'] == 'ntlm') {
2533 $this->setCurlOption($CURLOPT_PROXYAUTH, $CURLAUTH_NTLM);
2534 }
2535 }
2536 }
2537 $this->debug('cURL connection set up');
2538 return true;
2539 } else {
2540 $this->setError('Unknown scheme ' . $this->scheme);
2541 $this->debug('Unknown scheme ' . $this->scheme);
2542 return false;
2543 }
2544 }
2545
2556 public function send($data, $timeout = 0, $response_timeout = 30, $cookies = null)
2557 {
2558 $this->debug('entered send() with data of length: ' . strlen($data));
2559
2560 $this->tryagain = true;
2561 $tries = 0;
2562 while ($this->tryagain) {
2563 $this->tryagain = false;
2564 if ($tries++ < 2) {
2565 // make connnection
2566 if (!$this->connect($timeout, $response_timeout)) {
2567 return false;
2568 }
2569
2570 // send request
2571 if (!$this->sendRequest($data, $cookies)) {
2572 return false;
2573 }
2574
2575 // get response
2576 $respdata = $this->getResponse();
2577 } else {
2578 $this->setError("Too many tries to get an OK response ($this->response_status_line)");
2579 }
2580 }
2581 $this->debug('end of send()');
2582 return $respdata;
2583 }
2584
2585
2597 public function sendHTTPS($data, $timeout = 0, $response_timeout = 30, $cookies = null)
2598 {
2599 return $this->send($data, $timeout, $response_timeout, $cookies);
2600 }
2601
2612 public function setCredentials($username, $password, $authtype = 'basic', $digestRequest = array(), $certRequest = array())
2613 {
2614 $this->debug("setCredentials username=$username authtype=$authtype digestRequest=");
2615 $this->appendDebug($this->varDump($digestRequest));
2616 $this->debug("certRequest=");
2617 $this->appendDebug($this->varDump($certRequest));
2618 // cf. RFC 2617
2619 if ($authtype == 'basic') {
2620 $this->setHeader('Authorization', 'Basic ' . base64_encode(str_replace(':', '', $username) . ':' . $password));
2621 } elseif ($authtype == 'digest') {
2622 if (isset($digestRequest['nonce'])) {
2623 $digestRequest['nc'] = isset($digestRequest['nc']) ? $digestRequest['nc']++ : 1;
2624
2625 // calculate the Digest hashes (calculate code based on digest implementation found at: http://www.rassoc.com/gregr/weblog/stories/2002/07/09/webServicesSecurityHttpDigestAuthenticationWithoutActiveDirectory.html)
2626
2627 // A1 = unq(username-value) ":" unq(realm-value) ":" passwd
2628 $A1 = $username . ':' . (isset($digestRequest['realm']) ? $digestRequest['realm'] : '') . ':' . $password;
2629
2630 // H(A1) = MD5(A1)
2631 $HA1 = md5($A1);
2632
2633 // A2 = Method ":" digest-uri-value
2634 $A2 = $this->request_method . ':' . $this->digest_uri;
2635
2636 // H(A2)
2637 $HA2 = md5($A2);
2638
2639 // KD(secret, data) = H(concat(secret, ":", data))
2640 // if qop == auth:
2641 // request-digest = <"> < KD ( H(A1), unq(nonce-value)
2642 // ":" nc-value
2643 // ":" unq(cnonce-value)
2644 // ":" unq(qop-value)
2645 // ":" H(A2)
2646 // ) <">
2647 // if qop is missing,
2648 // request-digest = <"> < KD ( H(A1), unq(nonce-value) ":" H(A2) ) > <">
2649
2650 $unhashedDigest = '';
2651 $nonce = isset($digestRequest['nonce']) ? $digestRequest['nonce'] : '';
2652 $cnonce = $nonce;
2653 if ($digestRequest['qop'] != '') {
2654 $unhashedDigest = $HA1 . ':' . $nonce . ':' . sprintf("%08d", $digestRequest['nc']) . ':' . $cnonce . ':' . $digestRequest['qop'] . ':' . $HA2;
2655 } else {
2656 $unhashedDigest = $HA1 . ':' . $nonce . ':' . $HA2;
2657 }
2658
2659 $hashedDigest = md5($unhashedDigest);
2660
2661 $opaque = '';
2662 if (isset($digestRequest['opaque'])) {
2663 $opaque = ', opaque="' . $digestRequest['opaque'] . '"';
2664 }
2665
2666 $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 . '"');
2667 }
2668 } elseif ($authtype == 'certificate') {
2669 $this->certRequest = $certRequest;
2670 $this->debug('Authorization header not set for certificate');
2671 } elseif ($authtype == 'ntlm') {
2672 // do nothing
2673 $this->debug('Authorization header not set for ntlm');
2674 }
2675 $this->username = $username;
2676 $this->password = $password;
2677 $this->authtype = $authtype;
2678 $this->digestRequest = $digestRequest;
2679 }
2680
2687 public function setSOAPAction($soapaction)
2688 {
2689 $this->setHeader('SOAPAction', '"' . $soapaction . '"');
2690 }
2691
2698 public function setEncoding($enc = 'gzip, deflate')
2699 {
2700 if (function_exists('gzdeflate')) {
2701 $this->protocol_version = '1.1';
2702 $this->setHeader('Accept-Encoding', $enc);
2703 if (!isset($this->outgoing_headers['Connection'])) {
2704 $this->setHeader('Connection', 'close');
2705 $this->persistentConnection = false;
2706 }
2707 #set_magic_quotes_runtime(0);
2708 // deprecated
2709 $this->encoding = $enc;
2710 }
2711 }
2712
2723 public function setProxy($proxyhost, $proxyport, $proxyusername = '', $proxypassword = '', $proxyauthtype = 'basic')
2724 {
2725 if ($proxyhost) {
2726 $this->proxy = array(
2727 'host' => $proxyhost,
2728 'port' => $proxyport,
2729 'username' => $proxyusername,
2730 'password' => $proxypassword,
2731 'authtype' => $proxyauthtype
2732 );
2733 if ($proxyusername != '' && $proxypassword != '' && $proxyauthtype = 'basic') {
2734 $this->setHeader('Proxy-Authorization', ' Basic ' . base64_encode($proxyusername . ':' . $proxypassword));
2735 }
2736 } else {
2737 $this->debug('remove proxy');
2738 $proxy = null;
2739 unsetHeader('Proxy-Authorization');
2740 }
2741 }
2742
2743
2753 {
2754 $skipHeaders = array( 'HTTP/1.1 100',
2755 'HTTP/1.0 301',
2756 'HTTP/1.1 301',
2757 'HTTP/1.0 302',
2758 'HTTP/1.1 302',
2759 'HTTP/1.0 401',
2760 'HTTP/1.1 401',
2761 'HTTP/1.0 200 Connection established');
2762 foreach ($skipHeaders as $hd) {
2763 $prefix = substr($data, 0, strlen($hd));
2764 if ($prefix == $hd) {
2765 return true;
2766 }
2767 }
2768
2769 return false;
2770 }
2771
2782 public function decodeChunked($buffer, $lb)
2783 {
2784 // length := 0
2785 $length = 0;
2786 $new = '';
2787
2788 // read chunk-size, chunk-extension (if any) and CRLF
2789 // get the position of the linebreak
2790 $chunkend = strpos($buffer, $lb);
2791 if ($chunkend == false) {
2792 $this->debug('no linebreak found in decodeChunked');
2793 return $new;
2794 }
2795 $temp = substr($buffer, 0, $chunkend);
2796 $chunk_size = hexdec(trim($temp));
2797 $chunkstart = $chunkend + strlen($lb);
2798 // while (chunk-size > 0) {
2799 while ($chunk_size > 0) {
2800 $this->debug("chunkstart: $chunkstart chunk_size: $chunk_size");
2801 $chunkend = strpos($buffer, $lb, $chunkstart + $chunk_size);
2802
2803 // Just in case we got a broken connection
2804 if ($chunkend == false) {
2805 $chunk = substr($buffer, $chunkstart);
2806 // append chunk-data to entity-body
2807 $new .= $chunk;
2808 $length += strlen($chunk);
2809 break;
2810 }
2811
2812 // read chunk-data and CRLF
2813 $chunk = substr($buffer, $chunkstart, $chunkend - $chunkstart);
2814 // append chunk-data to entity-body
2815 $new .= $chunk;
2816 // length := length + chunk-size
2817 $length += strlen($chunk);
2818 // read chunk-size and CRLF
2819 $chunkstart = $chunkend + strlen($lb);
2820
2821 $chunkend = strpos($buffer, $lb, $chunkstart) + strlen($lb);
2822 if ($chunkend == false) {
2823 break; //Just in case we got a broken connection
2824 }
2825 $temp = substr($buffer, $chunkstart, $chunkend - $chunkstart);
2826 $chunk_size = hexdec(trim($temp));
2827 $chunkstart = $chunkend;
2828 }
2829 return $new;
2830 }
2831
2840 public function buildPayload($data, $cookie_str = '')
2841 {
2842 // Note: for cURL connections, $this->outgoing_payload is ignored,
2843 // as is the Content-Length header, but these are still created as
2844 // debugging guides.
2845
2846 // add content-length header
2847 $this->setHeader('Content-Length', strlen($data));
2848
2849 // start building outgoing payload:
2850 if ($this->proxy) {
2851 $uri = $this->url;
2852 } else {
2853 $uri = $this->uri;
2854 }
2855 $req = "$this->request_method $uri HTTP/$this->protocol_version";
2856 $this->debug("HTTP request: $req");
2857 $this->outgoing_payload = "$req\r\n";
2858
2859 // loop thru headers, serializing
2860 foreach ($this->outgoing_headers as $k => $v) {
2861 $hdr = $k . ': ' . $v;
2862 $this->debug("HTTP header: $hdr");
2863 $this->outgoing_payload .= "$hdr\r\n";
2864 }
2865
2866 // add any cookies
2867 if ($cookie_str != '') {
2868 $hdr = 'Cookie: ' . $cookie_str;
2869 $this->debug("HTTP header: $hdr");
2870 $this->outgoing_payload .= "$hdr\r\n";
2871 }
2872
2873 // header/body separator
2874 $this->outgoing_payload .= "\r\n";
2875
2876 // add data
2877 $this->outgoing_payload .= $data;
2878 }
2879
2888 public function sendRequest($data, $cookies = null)
2889 {
2890 // build cookie string
2891 $cookie_str = $this->getCookiesForRequest($cookies, (($this->scheme == 'ssl') || ($this->scheme == 'https')));
2892
2893 // build payload
2894 $this->buildPayload($data, $cookie_str);
2895
2896 if ($this->io_method() == 'socket') {
2897 // send payload
2898 if (!fputs($this->fp, $this->outgoing_payload, strlen($this->outgoing_payload))) {
2899 $this->setError('couldn\'t write message data to socket');
2900 $this->debug('couldn\'t write message data to socket');
2901 return false;
2902 }
2903 $this->debug('wrote data to socket, length = ' . strlen($this->outgoing_payload));
2904 return true;
2905 } elseif ($this->io_method() == 'curl') {
2906 // set payload
2907 // cURL does say this should only be the verb, and in fact it
2908 // turns out that the URI and HTTP version are appended to this, which
2909 // some servers refuse to work with (so we no longer use this method!)
2910 //$this->setCurlOption(CURLOPT_CUSTOMREQUEST, $this->outgoing_payload);
2911 $curl_headers = array();
2912 foreach ($this->outgoing_headers as $k => $v) {
2913 if ($k == 'Connection' || $k == 'Content-Length' || $k == 'Host' || $k == 'Authorization' || $k == 'Proxy-Authorization') {
2914 $this->debug("Skip cURL header $k: $v");
2915 } else {
2916 $curl_headers[] = "$k: $v";
2917 }
2918 }
2919 if ($cookie_str != '') {
2920 $curl_headers[] = 'Cookie: ' . $cookie_str;
2921 }
2922 $this->setCurlOption(CURLOPT_HTTPHEADER, $curl_headers);
2923 $this->debug('set cURL HTTP headers');
2924 if ($this->request_method == "POST") {
2925 $this->setCurlOption(CURLOPT_POST, 1);
2926 $this->setCurlOption(CURLOPT_POSTFIELDS, $data);
2927 $this->debug('set cURL POST data');
2928 } else {
2929 }
2930 // insert custom user-set cURL options
2931 foreach ($this->ch_options as $key => $val) {
2932 $this->setCurlOption($key, $val);
2933 }
2934
2935 $this->debug('set cURL payload');
2936 return true;
2937 }
2938 }
2939
2946 public function getResponse()
2947 {
2948 $this->incoming_payload = '';
2949
2950 if ($this->io_method() == 'socket') {
2951 // loop until headers have been retrieved
2952 $data = '';
2953 while (!isset($lb)) {
2954 // We might EOF during header read.
2955 if (feof($this->fp)) {
2956 $this->incoming_payload = $data;
2957 $this->debug('found no headers before EOF after length ' . strlen($data));
2958 $this->debug("received before EOF:\n" . $data);
2959 $this->setError('server failed to send headers');
2960 return false;
2961 }
2962
2963 $tmp = fgets($this->fp, 256);
2964 $tmplen = strlen($tmp);
2965 $this->debug("read line of $tmplen bytes: " . trim($tmp));
2966
2967 if ($tmplen == 0) {
2968 $this->incoming_payload = $data;
2969 $this->debug('socket read of headers timed out after length ' . strlen($data));
2970 $this->debug("read before timeout: " . $data);
2971 $this->setError('socket read of headers timed out');
2972 return false;
2973 }
2974
2975 $data .= $tmp;
2976 $pos = strpos($data, "\r\n\r\n");
2977 if ($pos > 1) {
2978 $lb = "\r\n";
2979 } else {
2980 $pos = strpos($data, "\n\n");
2981 if ($pos > 1) {
2982 $lb = "\n";
2983 }
2984 }
2985 // remove 100 headers
2986 if (isset($lb) && preg_match('/^HTTP\/1.1 100/', $data)) {
2987 unset($lb);
2988 $data = '';
2989 }//
2990 }
2991 // store header data
2992 $this->incoming_payload .= $data;
2993 $this->debug('found end of headers after length ' . strlen($data));
2994 // process headers
2995 $header_data = trim(substr($data, 0, $pos));
2996 $header_array = explode($lb, $header_data);
2997 $this->incoming_headers = array();
2998 $this->incoming_cookies = array();
2999 foreach ($header_array as $header_line) {
3000 $arr = explode(':', $header_line, 2);
3001 if (count($arr) > 1) {
3002 $header_name = strtolower(trim($arr[0]));
3003 $this->incoming_headers[$header_name] = trim($arr[1]);
3004 if ($header_name == 'set-cookie') {
3005 // TODO: allow multiple cookies from parseCookie
3006 $cookie = $this->parseCookie(trim($arr[1]));
3007 if ($cookie) {
3008 $this->incoming_cookies[] = $cookie;
3009 $this->debug('found cookie: ' . $cookie['name'] . ' = ' . $cookie['value']);
3010 } else {
3011 $this->debug('did not find cookie in ' . trim($arr[1]));
3012 }
3013 }
3014 } elseif (isset($header_name)) {
3015 // append continuation line to previous header
3016 $this->incoming_headers[$header_name] .= $lb . ' ' . $header_line;
3017 }
3018 }
3019
3020 // loop until msg has been received
3021 if (isset($this->incoming_headers['transfer-encoding']) && strtolower($this->incoming_headers['transfer-encoding']) == 'chunked') {
3022 $content_length = 2147483647; // ignore any content-length header
3023 $chunked = true;
3024 $this->debug("want to read chunked content");
3025 } elseif (isset($this->incoming_headers['content-length'])) {
3026 $content_length = $this->incoming_headers['content-length'];
3027 $chunked = false;
3028 $this->debug("want to read content of length $content_length");
3029 } else {
3030 $content_length = 2147483647;
3031 $chunked = false;
3032 $this->debug("want to read content to EOF");
3033 }
3034 $data = '';
3035 do {
3036 if ($chunked) {
3037 $tmp = fgets($this->fp, 256);
3038 $tmplen = strlen($tmp);
3039 $this->debug("read chunk line of $tmplen bytes");
3040 if ($tmplen == 0) {
3041 $this->incoming_payload = $data;
3042 $this->debug('socket read of chunk length timed out after length ' . strlen($data));
3043 $this->debug("read before timeout:\n" . $data);
3044 $this->setError('socket read of chunk length timed out');
3045 return false;
3046 }
3047 $content_length = hexdec(trim($tmp));
3048 $this->debug("chunk length $content_length");
3049 }
3050 $strlen = 0;
3051 while (($strlen < $content_length) && (!feof($this->fp))) {
3052 $readlen = min(8192, $content_length - $strlen);
3053 $tmp = fread($this->fp, $readlen);
3054 $tmplen = strlen($tmp);
3055 $this->debug("read buffer of $tmplen bytes");
3056 if (($tmplen == 0) && (!feof($this->fp))) {
3057 $this->incoming_payload = $data;
3058 $this->debug('socket read of body timed out after length ' . strlen($data));
3059 $this->debug("read before timeout:\n" . $data);
3060 $this->setError('socket read of body timed out');
3061 return false;
3062 }
3063 $strlen += $tmplen;
3064 $data .= $tmp;
3065 }
3066 if ($chunked && ($content_length > 0)) {
3067 $tmp = fgets($this->fp, 256);
3068 $tmplen = strlen($tmp);
3069 $this->debug("read chunk terminator of $tmplen bytes");
3070 if ($tmplen == 0) {
3071 $this->incoming_payload = $data;
3072 $this->debug('socket read of chunk terminator timed out after length ' . strlen($data));
3073 $this->debug("read before timeout:\n" . $data);
3074 $this->setError('socket read of chunk terminator timed out');
3075 return false;
3076 }
3077 }
3078 } while ($chunked && ($content_length > 0) && (!feof($this->fp)));
3079 if (feof($this->fp)) {
3080 $this->debug('read to EOF');
3081 }
3082 $this->debug('read body of length ' . strlen($data));
3083 $this->incoming_payload .= $data;
3084 $this->debug('received a total of ' . strlen($this->incoming_payload) . ' bytes of data from server');
3085
3086 // close filepointer
3087 if (
3088 (isset($this->incoming_headers['connection']) && strtolower($this->incoming_headers['connection']) == 'close') ||
3089 (! $this->persistentConnection) || feof($this->fp)) {
3090 fclose($this->fp);
3091 $this->fp = false;
3092 $this->debug('closed socket');
3093 }
3094
3095 // connection was closed unexpectedly
3096 if ($this->incoming_payload == '') {
3097 $this->setError('no response from server');
3098 return false;
3099 }
3100
3101 // decode transfer-encoding
3102 // if(isset($this->incoming_headers['transfer-encoding']) && strtolower($this->incoming_headers['transfer-encoding']) == 'chunked'){
3103 // if(!$data = $this->decodeChunked($data, $lb)){
3104 // $this->setError('Decoding of chunked data failed');
3105 // return false;
3106 // }
3107 //print "<pre>\nde-chunked:\n---------------\n$data\n\n---------------\n</pre>";
3108 // set decoded payload
3109 // $this->incoming_payload = $header_data.$lb.$lb.$data;
3110 // }
3111 } elseif ($this->io_method() == 'curl') {
3112 // send and receive
3113 $this->debug('send and receive with cURL');
3114 $this->incoming_payload = curl_exec($this->ch);
3116
3117 $cErr = curl_error($this->ch);
3118 if ($cErr != '') {
3119 $err = 'cURL ERROR: ' . curl_errno($this->ch) . ': ' . $cErr . '<br>';
3120 // TODO: there is a PHP bug that can cause this to SEGV for CURLINFO_CONTENT_TYPE
3121 foreach (curl_getinfo($this->ch) as $k => $v) {
3122 $err .= "$k: $v<br>";
3123 }
3124 $this->debug($err);
3125 $this->setError($err);
3126 curl_close($this->ch);
3127 return false;
3128 } else {
3129 //echo '<pre>';
3130 //var_dump(curl_getinfo($this->ch));
3131 //echo '</pre>';
3132 }
3133 // close curl
3134 $this->debug('No cURL error, closing cURL');
3135 curl_close($this->ch);
3136
3137 // try removing skippable headers
3138 $savedata = $data;
3139 while ($this->isSkippableCurlHeader($data)) {
3140 $this->debug("Found HTTP header to skip");
3141 if ($pos = strpos($data, "\r\n\r\n")) {
3142 $data = ltrim(substr($data, $pos));
3143 } elseif ($pos = strpos($data, "\n\n")) {
3144 $data = ltrim(substr($data, $pos));
3145 }
3146 }
3147
3148 if ($data == '') {
3149 // have nothing left; just remove 100 header(s)
3150 $data = $savedata;
3151 while (preg_match('/^HTTP\/1.1 100/', $data)) {
3152 if ($pos = strpos($data, "\r\n\r\n")) {
3153 $data = ltrim(substr($data, $pos));
3154 } elseif ($pos = strpos($data, "\n\n")) {
3155 $data = ltrim(substr($data, $pos));
3156 }
3157 }
3158 }
3159
3160 // separate content from HTTP headers
3161 if ($pos = strpos($data, "\r\n\r\n")) {
3162 $lb = "\r\n";
3163 } elseif ($pos = strpos($data, "\n\n")) {
3164 $lb = "\n";
3165 } else {
3166 $this->debug('no proper separation of headers and document');
3167 $this->setError('no proper separation of headers and document');
3168 return false;
3169 }
3170 $header_data = trim(substr($data, 0, $pos));
3171 $header_array = explode($lb, $header_data);
3172 $data = ltrim(substr($data, $pos));
3173 $this->debug('found proper separation of headers and document');
3174 $this->debug('cleaned data, stringlen: ' . strlen($data));
3175 // clean headers
3176 foreach ($header_array as $header_line) {
3177 $arr = explode(':', $header_line, 2);
3178 if (count($arr) > 1) {
3179 $header_name = strtolower(trim($arr[0]));
3180 $this->incoming_headers[$header_name] = trim($arr[1]);
3181 if ($header_name == 'set-cookie') {
3182 // TODO: allow multiple cookies from parseCookie
3183 $cookie = $this->parseCookie(trim($arr[1]));
3184 if ($cookie) {
3185 $this->incoming_cookies[] = $cookie;
3186 $this->debug('found cookie: ' . $cookie['name'] . ' = ' . $cookie['value']);
3187 } else {
3188 $this->debug('did not find cookie in ' . trim($arr[1]));
3189 }
3190 }
3191 } elseif (isset($header_name)) {
3192 // append continuation line to previous header
3193 $this->incoming_headers[$header_name] .= $lb . ' ' . $header_line;
3194 }
3195 }
3196 }
3197
3198 $this->response_status_line = $header_array[0];
3199 $arr = explode(' ', $this->response_status_line, 3);
3200 $http_version = $arr[0];
3201 $http_status = intval($arr[1]);
3202 $http_reason = count($arr) > 2 ? $arr[2] : '';
3203
3204 // see if we need to resend the request with http digest authentication
3205 if (isset($this->incoming_headers['location']) && ($http_status == 301 || $http_status == 302)) {
3206 $this->debug("Got $http_status $http_reason with Location: " . $this->incoming_headers['location']);
3207 $this->setURL($this->incoming_headers['location']);
3208 $this->tryagain = true;
3209 return false;
3210 }
3211
3212 // see if we need to resend the request with http digest authentication
3213 if (isset($this->incoming_headers['www-authenticate']) && $http_status == 401) {
3214 $this->debug("Got 401 $http_reason with WWW-Authenticate: " . $this->incoming_headers['www-authenticate']);
3215 if (strstr($this->incoming_headers['www-authenticate'], "Digest ")) {
3216 $this->debug('Server wants digest authentication');
3217 // remove "Digest " from our elements
3218 $digestString = str_replace('Digest ', '', $this->incoming_headers['www-authenticate']);
3219
3220 // parse elements into array
3221 $digestElements = explode(',', $digestString);
3222 foreach ($digestElements as $val) {
3223 $tempElement = explode('=', trim($val), 2);
3224 $digestRequest[$tempElement[0]] = str_replace("\"", '', $tempElement[1]);
3225 }
3226
3227 // should have (at least) qop, realm, nonce
3228 if (isset($digestRequest['nonce'])) {
3229 $this->setCredentials($this->username, $this->password, 'digest', $digestRequest);
3230 $this->tryagain = true;
3231 return false;
3232 }
3233 }
3234 $this->debug('HTTP authentication failed');
3235 $this->setError('HTTP authentication failed');
3236 return false;
3237 }
3238
3239 if (
3240 ($http_status >= 300 && $http_status <= 307) ||
3241 ($http_status >= 400 && $http_status <= 417) ||
3242 ($http_status >= 501 && $http_status <= 505)
3243 ) {
3244 $this->setError("Unsupported HTTP response status $http_status $http_reason (soapclient->response has contents of the response)");
3245 return false;
3246 }
3247
3248 // decode content-encoding
3249 if (isset($this->incoming_headers['content-encoding']) && $this->incoming_headers['content-encoding'] != '') {
3250 if (strtolower($this->incoming_headers['content-encoding']) == 'deflate' || strtolower($this->incoming_headers['content-encoding']) == 'gzip') {
3251 // if decoding works, use it. else assume data wasn't gzencoded
3252 if (function_exists('gzinflate')) {
3253 //$timer->setMarker('starting decoding of gzip/deflated content');
3254 // IIS 5 requires gzinflate instead of gzuncompress (similar to IE 5 and gzdeflate v. gzcompress)
3255 // this means there are no Zlib headers, although there should be
3256 $this->debug('The gzinflate function exists');
3257 $datalen = strlen($data);
3258 if ($this->incoming_headers['content-encoding'] == 'deflate') {
3259 if ($degzdata = @gzinflate($data)) {
3260 $data = $degzdata;
3261 $this->debug('The payload has been inflated to ' . strlen($data) . ' bytes');
3262 if (strlen($data) < $datalen) {
3263 // test for the case that the payload has been compressed twice
3264 $this->debug('The inflated payload is smaller than the gzipped one; try again');
3265 if ($degzdata = @gzinflate($data)) {
3266 $data = $degzdata;
3267 $this->debug('The payload has been inflated again to ' . strlen($data) . ' bytes');
3268 }
3269 }
3270 } else {
3271 $this->debug('Error using gzinflate to inflate the payload');
3272 $this->setError('Error using gzinflate to inflate the payload');
3273 }
3274 } elseif ($this->incoming_headers['content-encoding'] == 'gzip') {
3275 if ($degzdata = @gzinflate(substr($data, 10))) { // do our best
3276 $data = $degzdata;
3277 $this->debug('The payload has been un-gzipped to ' . strlen($data) . ' bytes');
3278 if (strlen($data) < $datalen) {
3279 // test for the case that the payload has been compressed twice
3280 $this->debug('The un-gzipped payload is smaller than the gzipped one; try again');
3281 if ($degzdata = @gzinflate(substr($data, 10))) {
3282 $data = $degzdata;
3283 $this->debug('The payload has been un-gzipped again to ' . strlen($data) . ' bytes');
3284 }
3285 }
3286 } else {
3287 $this->debug('Error using gzinflate to un-gzip the payload');
3288 $this->setError('Error using gzinflate to un-gzip the payload');
3289 }
3290 }
3291 //$timer->setMarker('finished decoding of gzip/deflated content');
3292 //print "<xmp>\nde-inflated:\n---------------\n$data\n-------------\n</xmp>";
3293 // set decoded payload
3294 $this->incoming_payload = $header_data . $lb . $lb . $data;
3295 } else {
3296 $this->debug('The server sent compressed data. Your php install must have the Zlib extension compiled in to support this.');
3297 $this->setError('The server sent compressed data. Your php install must have the Zlib extension compiled in to support this.');
3298 }
3299 } else {
3300 $this->debug('Unsupported Content-Encoding ' . $this->incoming_headers['content-encoding']);
3301 $this->setError('Unsupported Content-Encoding ' . $this->incoming_headers['content-encoding']);
3302 }
3303 } else {
3304 $this->debug('No Content-Encoding header');
3305 }
3306
3307 if (strlen($data) == 0) {
3308 $this->debug('no data after headers!');
3309 $this->setError('no data present after HTTP headers');
3310 return false;
3311 }
3312
3313 return $data;
3314 }
3315
3323 public function setContentType($type, $charset = false)
3324 {
3325 $this->setHeader('Content-Type', $type . ($charset ? '; charset=' . $charset : ''));
3326 }
3327
3334 public function usePersistentConnection()
3335 {
3336 if (isset($this->outgoing_headers['Accept-Encoding'])) {
3337 return false;
3338 }
3339 $this->protocol_version = '1.1';
3340 $this->persistentConnection = true;
3341 $this->setHeader('Connection', 'Keep-Alive');
3342 return true;
3343 }
3344
3352 /*
3353 * TODO: allow a Set-Cookie string to be parsed into multiple cookies
3354 */
3355 public function parseCookie($cookie_str)
3356 {
3357 $cookie_str = str_replace('; ', ';', $cookie_str) . ';';
3358 // begin-patch php8
3359 //$data = split(';', $cookie_str);
3360 $data = explode(';', $cookie_str);
3361 $value_str = $data[0];
3362
3363 $cookie_param = 'domain=';
3364 $start = strpos($cookie_str, $cookie_param);
3365 if ($start > 0) {
3366 $domain = substr($cookie_str, $start + strlen($cookie_param));
3367 $domain = substr($domain, 0, strpos($domain, ';'));
3368 } else {
3369 $domain = '';
3370 }
3371
3372 $cookie_param = 'expires=';
3373 $start = strpos($cookie_str, $cookie_param);
3374 if ($start > 0) {
3375 $expires = substr($cookie_str, $start + strlen($cookie_param));
3376 $expires = substr($expires, 0, strpos($expires, ';'));
3377 } else {
3378 $expires = '';
3379 }
3380
3381 $cookie_param = 'path=';
3382 $start = strpos($cookie_str, $cookie_param);
3383 if ($start > 0) {
3384 $path = substr($cookie_str, $start + strlen($cookie_param));
3385 $path = substr($path, 0, strpos($path, ';'));
3386 } else {
3387 $path = '/';
3388 }
3389
3390 $cookie_param = ';secure;';
3391 if (strpos($cookie_str, $cookie_param) !== false) {
3392 $secure = true;
3393 } else {
3394 $secure = false;
3395 }
3396
3397 $sep_pos = strpos($value_str, '=');
3398
3399 if ($sep_pos) {
3400 $name = substr($value_str, 0, $sep_pos);
3401 $value = substr($value_str, $sep_pos + 1);
3402 $cookie = array( 'name' => $name,
3403 'value' => $value,
3404 'domain' => $domain,
3405 'path' => $path,
3406 'expires' => $expires,
3407 'secure' => $secure
3408 );
3409 return $cookie;
3410 }
3411 return false;
3412 }
3413
3422 public function getCookiesForRequest($cookies, $secure = false)
3423 {
3424 $cookie_str = '';
3425 if ((! is_null($cookies)) && (is_array($cookies))) {
3426 foreach ($cookies as $cookie) {
3427 if (! is_array($cookie)) {
3428 continue;
3429 }
3430 $this->debug("check cookie for validity: " . $cookie['name'] . '=' . $cookie['value']);
3431 if ((isset($cookie['expires'])) && (! empty($cookie['expires']))) {
3432 if (strtotime($cookie['expires']) <= time()) {
3433 $this->debug('cookie has expired');
3434 continue;
3435 }
3436 }
3437 if ((isset($cookie['domain'])) && (! empty($cookie['domain']))) {
3438 $domain = preg_quote($cookie['domain']);
3439 if (! preg_match("'.*$domain$'i", $this->host)) {
3440 $this->debug('cookie has different domain');
3441 continue;
3442 }
3443 }
3444 if ((isset($cookie['path'])) && (! empty($cookie['path']))) {
3445 $path = preg_quote($cookie['path']);
3446 if (! preg_match("'^$path.*'i", $this->path)) {
3447 $this->debug('cookie is for a different path');
3448 continue;
3449 }
3450 }
3451 if ((! $secure) && (isset($cookie['secure'])) && ($cookie['secure'])) {
3452 $this->debug('cookie is secure, transport is not');
3453 continue;
3454 }
3455 $cookie_str .= $cookie['name'] . '=' . $cookie['value'] . '; ';
3456 $this->debug('add cookie to Cookie-String: ' . $cookie['name'] . '=' . $cookie['value']);
3457 }
3458 }
3459 return $cookie_str;
3460 }
3461}
3462
3463?><?php
3464
3465
3466
3478{
3479 public $opData;
3485 public $headers = array();
3491 public $request = '';
3497 public $requestHeaders = '';
3503 public $requestHeader = null;
3509 public $document = '';
3515 public $requestSOAP = '';
3521 public $methodURI = '';
3527 public $methodname = '';
3533 public $methodparams = array();
3539 public $SOAPAction = '';
3545 public $xml_encoding = '';
3551 public $decode_utf8 = true;
3552 public $class;
3553
3559 public $outgoing_headers = array();
3565 public $response = '';
3571 public $responseHeaders = '';
3577 public $responseSOAP = '';
3583 public $methodreturn = false;
3595 public $fault = false;
3601 public $result = 'successful';
3602
3609 public $operations = array();
3615 public $wsdl = false;
3621 public $externalWSDLURL = false;
3627 public $debug_flag = false;
3628
3629
3637 public function __construct($wsdl = false)
3638 {
3640 // turn on debugging?
3641 global $debug;
3642 global $HTTP_SERVER_VARS;
3643
3644 if (isset($_SERVER)) {
3645 $this->debug("_SERVER is defined:");
3646 $this->appendDebug($this->varDump($_SERVER));
3647 } elseif (isset($HTTP_SERVER_VARS)) {
3648 $this->debug("HTTP_SERVER_VARS is defined:");
3649 $this->appendDebug($this->varDump($HTTP_SERVER_VARS));
3650 } else {
3651 $this->debug("Neither _SERVER nor HTTP_SERVER_VARS is defined.");
3652 }
3653
3654 if (isset($debug)) {
3655 $this->debug("In nusoap_server, set debug_flag=$debug based on global flag");
3656 $this->debug_flag = $debug;
3657 } elseif (isset($_SERVER['QUERY_STRING'])) {
3658 $qs = explode('&', $_SERVER['QUERY_STRING']);
3659 foreach ($qs as $v) {
3660 if (substr($v, 0, 6) == 'debug=') {
3661 $this->debug("In nusoap_server, set debug_flag=" . substr($v, 6) . " based on query string #1");
3662 $this->debug_flag = substr($v, 6);
3663 }
3664 }
3665 } elseif (isset($HTTP_SERVER_VARS['QUERY_STRING'])) {
3666 $qs = explode('&', $HTTP_SERVER_VARS['QUERY_STRING']);
3667 foreach ($qs as $v) {
3668 if (substr($v, 0, 6) == 'debug=') {
3669 $this->debug("In nusoap_server, set debug_flag=" . substr($v, 6) . " based on query string #2");
3670 $this->debug_flag = substr($v, 6);
3671 }
3672 }
3673 }
3674
3675 // wsdl
3676 if ($wsdl) {
3677 $this->debug("In nusoap_server, WSDL is specified");
3678 if (is_object($wsdl) && (get_class($wsdl) == 'wsdl')) {
3679 $this->wsdl = $wsdl;
3680 $this->externalWSDLURL = $this->wsdl->wsdl;
3681 $this->debug('Use existing wsdl instance from ' . $this->externalWSDLURL);
3682 } else {
3683 $this->debug('Create wsdl from ' . $wsdl);
3684 $this->wsdl = new wsdl($wsdl);
3685 $this->externalWSDLURL = $wsdl;
3686 }
3687 $this->appendDebug($this->wsdl->getDebug());
3688 $this->wsdl->clearDebug();
3689 if ($err = $this->wsdl->getError()) {
3690 die('WSDL ERROR: ' . $err);
3691 }
3692 }
3693 }
3694
3701 public function service($data)
3702 {
3703 global $HTTP_SERVER_VARS;
3704
3705 if (isset($_SERVER['QUERY_STRING'])) {
3706 $qs = $_SERVER['QUERY_STRING'];
3707 } elseif (isset($HTTP_SERVER_VARS['QUERY_STRING'])) {
3708 $qs = $HTTP_SERVER_VARS['QUERY_STRING'];
3709 } else {
3710 $qs = '';
3711 }
3712 $this->debug("In service, query string=$qs");
3713
3714 if (preg_match('/wsdl/', $qs)) {
3715 $this->debug("In service, this is a request for WSDL");
3716 if ($this->externalWSDLURL) {
3717 if (strpos($this->externalWSDLURL, "://") !== false) { // assume URL
3718 header('Location: ' . $this->externalWSDLURL);
3719 } else { // assume file
3720 header("Content-Type: text/xml\r\n");
3721 $fp = fopen($this->externalWSDLURL, 'r');
3722 fpassthru($fp);
3723 }
3724 } elseif ($this->wsdl) {
3725 header("Content-Type: text/xml; charset=ISO-8859-1\r\n");
3726 print $this->wsdl->serialize($this->debug_flag);
3727 if ($this->debug_flag) {
3728 $this->debug('wsdl:');
3729 $this->appendDebug($this->varDump($this->wsdl));
3730 print $this->getDebugAsXMLComment();
3731 }
3732 } else {
3733 header("Content-Type: text/html; charset=ISO-8859-1\r\n");
3734 print "This service does not provide WSDL";
3735 }
3736 } elseif ($data == '' && $this->wsdl) {
3737 $this->debug("In service, there is no data, so return Web description");
3738 print $this->wsdl->webDescription();
3739 } else {
3740 $this->debug("In service, invoke the request");
3741 $this->parse_request($data);
3742 if (! $this->fault) {
3743 $this->invoke_method();
3744 }
3745 if (! $this->fault) {
3746 $this->serialize_return();
3747 }
3748 $this->send_response();
3749 }
3750 }
3751
3764 public function parse_http_headers()
3765 {
3766 global $HTTP_SERVER_VARS;
3767
3768 $this->request = '';
3769 $this->SOAPAction = '';
3770 if (function_exists('getallheaders')) {
3771 $this->debug("In parse_http_headers, use getallheaders");
3772 $headers = getallheaders();
3773 foreach ($headers as $k => $v) {
3774 $k = strtolower($k);
3775 $this->headers[$k] = $v;
3776 $this->request .= "$k: $v\r\n";
3777 $this->debug("$k: $v");
3778 }
3779 // get SOAPAction header
3780 if (isset($this->headers['soapaction'])) {
3781 $this->SOAPAction = str_replace('"', '', $this->headers['soapaction']);
3782 }
3783 // get the character encoding of the incoming request
3784 if (isset($this->headers['content-type']) && strpos($this->headers['content-type'], '=')) {
3785 $enc = str_replace('"', '', substr(strstr($this->headers["content-type"], '='), 1));
3786 if (preg_match('/^(ISO-8859-1|US-ASCII|UTF-8)$/i', $enc)) {
3787 $this->xml_encoding = strtoupper($enc);
3788 } else {
3789 $this->xml_encoding = 'US-ASCII';
3790 }
3791 } else {
3792 // should be US-ASCII for HTTP 1.0 or ISO-8859-1 for HTTP 1.1
3793 $this->xml_encoding = 'ISO-8859-1';
3794 }
3795 } elseif (isset($_SERVER) && is_array($_SERVER)) {
3796 $this->debug("In parse_http_headers, use _SERVER");
3797 foreach ($_SERVER as $k => $v) {
3798 if (substr($k, 0, 5) == 'HTTP_') {
3799 $k = str_replace(' ', '-', strtolower(str_replace('_', ' ', substr($k, 5))));
3800 } else {
3801 $k = str_replace(' ', '-', strtolower(str_replace('_', ' ', $k)));
3802 }
3803 if ($k == 'soapaction') {
3804 // get SOAPAction header
3805 $k = 'SOAPAction';
3806 $v = str_replace('"', '', $v);
3807 $v = str_replace('\\', '', $v);
3808 $this->SOAPAction = $v;
3809 } elseif ($k == 'content-type') {
3810 // get the character encoding of the incoming request
3811 if (strpos($v, '=')) {
3812 $enc = substr(strstr($v, '='), 1);
3813 $enc = str_replace('"', '', $enc);
3814 $enc = str_replace('\\', '', $enc);
3815 if (preg_match('/^(ISO-8859-1|US-ASCII|UTF-8)$/i', $enc)) {
3816 $this->xml_encoding = strtoupper($enc);
3817 } else {
3818 $this->xml_encoding = 'US-ASCII';
3819 }
3820 } else {
3821 // should be US-ASCII for HTTP 1.0 or ISO-8859-1 for HTTP 1.1
3822 $this->xml_encoding = 'ISO-8859-1';
3823 }
3824 }
3825 $this->headers[$k] = $v;
3826 $this->request .= "$k: $v\r\n";
3827 $this->debug("$k: $v");
3828 }
3829 } elseif (is_array($HTTP_SERVER_VARS)) {
3830 $this->debug("In parse_http_headers, use HTTP_SERVER_VARS");
3831 foreach ($HTTP_SERVER_VARS as $k => $v) {
3832 if (substr($k, 0, 5) == 'HTTP_') {
3833 $k = str_replace(' ', '-', strtolower(str_replace('_', ' ', substr($k, 5))));
3834 $k = strtolower(substr($k, 5));
3835 } else {
3836 $k = str_replace(' ', '-', strtolower(str_replace('_', ' ', $k)));
3837 $k = strtolower($k);
3838 }
3839 if ($k == 'soapaction') {
3840 // get SOAPAction header
3841 $k = 'SOAPAction';
3842 $v = str_replace('"', '', $v);
3843 $v = str_replace('\\', '', $v);
3844 $this->SOAPAction = $v;
3845 } elseif ($k == 'content-type') {
3846 // get the character encoding of the incoming request
3847 if (strpos($v, '=')) {
3848 $enc = substr(strstr($v, '='), 1);
3849 $enc = str_replace('"', '', $enc);
3850 $enc = str_replace('\\', '', $enc);
3851 if (preg_match('/^(ISO-8859-1|US-ASCII|UTF-8)$/i', $enc)) {
3852 $this->xml_encoding = strtoupper($enc);
3853 } else {
3854 $this->xml_encoding = 'US-ASCII';
3855 }
3856 } else {
3857 // should be US-ASCII for HTTP 1.0 or ISO-8859-1 for HTTP 1.1
3858 $this->xml_encoding = 'ISO-8859-1';
3859 }
3860 }
3861 $this->headers[$k] = $v;
3862 $this->request .= "$k: $v\r\n";
3863 $this->debug("$k: $v");
3864 }
3865 } else {
3866 $this->debug("In parse_http_headers, HTTP headers not accessible");
3867 $this->setError("HTTP headers not accessible");
3868 }
3869 }
3870
3893 public function parse_request($data = '')
3894 {
3895 $this->debug('entering parse_request()');
3896 $this->parse_http_headers();
3897 $this->debug('got character encoding: ' . $this->xml_encoding);
3898 // uncompress if necessary
3899 if (isset($this->headers['content-encoding']) && $this->headers['content-encoding'] != '') {
3900 $this->debug('got content encoding: ' . $this->headers['content-encoding']);
3901 if ($this->headers['content-encoding'] == 'deflate' || $this->headers['content-encoding'] == 'gzip') {
3902 // if decoding works, use it. else assume data wasn't gzencoded
3903 if (function_exists('gzuncompress')) {
3904 if ($this->headers['content-encoding'] == 'deflate' && $degzdata = @gzuncompress($data)) {
3905 $data = $degzdata;
3906 } elseif ($this->headers['content-encoding'] == 'gzip' && $degzdata = gzinflate(substr($data, 10))) {
3907 $data = $degzdata;
3908 } else {
3909 $this->fault('SOAP-ENV:Client', 'Errors occurred when trying to decode the data');
3910 return;
3911 }
3912 } else {
3913 $this->fault('SOAP-ENV:Client', 'This Server does not support compressed data');
3914 return;
3915 }
3916 }
3917 }
3918 $this->request .= "\r\n" . $data;
3919 $data = $this->parseRequest($this->headers, $data);
3920 $this->requestSOAP = $data;
3921 $this->debug('leaving parse_request');
3922 }
3923
3941 public function invoke_method()
3942 {
3943 $this->debug('in invoke_method, methodname=' . $this->methodname . ' methodURI=' . $this->methodURI . ' SOAPAction=' . $this->SOAPAction);
3944
3945 if ($this->wsdl) {
3946 if ($this->opData = $this->wsdl->getOperationData($this->methodname)) {
3947 $this->debug('in invoke_method, found WSDL operation=' . $this->methodname);
3948 $this->appendDebug('opData=' . $this->varDump($this->opData));
3949 } elseif ($this->opData = $this->wsdl->getOperationDataForSoapAction($this->SOAPAction)) {
3950 // Note: hopefully this case will only be used for doc/lit, since rpc services should have wrapper element
3951 $this->debug('in invoke_method, found WSDL soapAction=' . $this->SOAPAction . ' for operation=' . $this->opData['name']);
3952 $this->appendDebug('opData=' . $this->varDump($this->opData));
3953 $this->methodname = $this->opData['name'];
3954 } else {
3955 $this->debug('in invoke_method, no WSDL for operation=' . $this->methodname);
3956 $this->fault('SOAP-ENV:Client', "Operation '" . $this->methodname . "' is not defined in the WSDL for this service");
3957 return;
3958 }
3959 } else {
3960 $this->debug('in invoke_method, no WSDL to validate method');
3961 }
3962
3963 // if a . is present in $this->methodname, we see if there is a class in scope,
3964 // which could be referred to. We will also distinguish between two deliminators,
3965 // to allow methods to be called a the class or an instance
3966 $class = '';
3967 $method = '';
3968 if (strpos($this->methodname, '..') > 0) {
3969 $delim = '..';
3970 } elseif (strpos($this->methodname, '.') > 0) {
3971 $delim = '.';
3972 } else {
3973 $delim = '';
3974 }
3975
3976 if (strlen($delim) > 0 && substr_count($this->methodname, $delim) == 1 &&
3977 class_exists(substr($this->methodname, 0, strpos($this->methodname, $delim)))) {
3978 // get the class and method name
3979 $class = substr($this->methodname, 0, strpos($this->methodname, $delim));
3980 $method = substr($this->methodname, strpos($this->methodname, $delim) + strlen($delim));
3981 $this->debug("in invoke_method, class=$class method=$method delim=$delim");
3982 }
3983 // set class handler
3984 // added to support single operations
3985 if ($class == '' && $this->class != '') {
3987 $delim = "..";
3988 $method = $this->methodname;
3989 }
3990
3991 // does method exist?
3992 if ($class == '') {
3993 if (!function_exists($this->methodname)) {
3994 $this->debug("in invoke_method, function '$this->methodname' not found!");
3995 $this->result = 'fault: method not found';
3996 $this->fault('SOAP-ENV:Client', "method '$this->methodname' not defined in service");
3997 return;
3998 }
3999 } else {
4000 $method_to_compare = (substr(phpversion(), 0, 2) == '4.') ? strtolower($method) : $method;
4001 if (!in_array($method_to_compare, get_class_methods($class))) {
4002 $this->debug("in invoke_method, method '$this->methodname' not found in class '$class'!");
4003 $this->result = 'fault: method not found';
4004 $this->fault('SOAP-ENV:Client', "method '$this->methodname' not defined in service");
4005 return;
4006 }
4007 }
4008
4009 // evaluate message, getting back parameters
4010 // verify that request parameters match the method's signature
4011 if (! $this->verify_method($this->methodname, $this->methodparams)) {
4012 // debug
4013 $this->debug('ERROR: request not verified against method signature');
4014 $this->result = 'fault: request failed validation against method signature';
4015 // return fault
4016 $this->fault('SOAP-ENV:Client', "Operation '$this->methodname' not defined in service.");
4017 return;
4018 }
4019
4020 // if there are parameters to pass
4021 $this->debug('in invoke_method, params:');
4022 $this->appendDebug($this->varDump($this->methodparams));
4023 $this->debug("in invoke_method, calling '$this->methodname'");
4024 if (!function_exists('call_user_func_array')) {
4025 if ($class == '') {
4026 $this->debug('in invoke_method, calling function using eval()');
4027 $funcCall = "\$this->methodreturn = $this->methodname(";
4028 } else {
4029 if ($delim == '..') {
4030 $this->debug('in invoke_method, calling class method using eval()');
4031 $funcCall = "\$this->methodreturn = " . $class . "::" . $method . "(";
4032 } else {
4033 $this->debug('in invoke_method, calling instance method using eval()');
4034 // generate unique instance name
4035 $instname = "\$inst_" . time();
4036 $funcCall = $instname . " = new " . $class . "(); ";
4037 $funcCall .= "\$this->methodreturn = " . $instname . "->" . $method . "(";
4038 }
4039 }
4040 if ($this->methodparams) {
4041 foreach ($this->methodparams as $param) {
4042 if (is_array($param) || is_object($param)) {
4043 $this->fault('SOAP-ENV:Client', 'NuSOAP does not handle complexType parameters correctly when using eval; call_user_func_array must be available');
4044 return;
4045 }
4046 $funcCall .= "\"$param\",";
4047 }
4048 $funcCall = substr($funcCall, 0, -1);
4049 }
4050 $funcCall .= ');';
4051 $this->debug('in invoke_method, function call: ' . $funcCall);
4052 @eval($funcCall);
4053 } else {
4054 if ($class == '') {
4055 $this->debug('in invoke_method, calling function using call_user_func_array()');
4056 $call_arg = "$this->methodname"; // straight assignment changes $this->methodname to lower case after call_user_func_array()
4057 } elseif ($delim == '..') {
4058 $this->debug('in invoke_method, calling class method using call_user_func_array()');
4059 $call_arg = array($class, $method);
4060 } else {
4061 $this->debug('in invoke_method, calling instance method using call_user_func_array()');
4062 $instance = new $class();
4063 $call_arg = array(&$instance, $method);
4064 }
4065 if (is_array($this->methodparams)) {
4066 $this->methodreturn = call_user_func_array($call_arg, array_values($this->methodparams));
4067 } else {
4068 $this->methodreturn = call_user_func_array($call_arg, array());
4069 }
4070 }
4071 $this->debug('in invoke_method, methodreturn:');
4072 $this->appendDebug($this->varDump($this->methodreturn));
4073 $this->debug("in invoke_method, called method $this->methodname, received data of type " . gettype($this->methodreturn));
4074 }
4075
4087 public function serialize_return()
4088 {
4089 $this->debug('Entering serialize_return methodname: ' . $this->methodname . ' methodURI: ' . $this->methodURI);
4090 // if fault
4091 if (isset($this->methodreturn) && ((get_class((object) $this->methodreturn) == 'soap_fault') || (get_class((object) $this->methodreturn) == 'nusoap_fault'))) {
4092 $this->debug('got a fault object from method');
4093 $this->fault = $this->methodreturn;
4094 return;
4095 } elseif ($this->methodreturnisliteralxml) {
4096 $return_val = $this->methodreturn;
4097 // returned value(s)
4098 } else {
4099 $this->debug('got a(n) ' . gettype($this->methodreturn) . ' from method');
4100 $this->debug('serializing return value');
4101 if ($this->wsdl) {
4102 if (sizeof($this->opData['output']['parts']) > 1) {
4103 $this->debug('more than one output part, so use the method return unchanged');
4104 $opParams = $this->methodreturn;
4105 } elseif (sizeof($this->opData['output']['parts']) == 1) {
4106 $this->debug('exactly one output part, so wrap the method return in a simple array');
4107 // TODO: verify that it is not already wrapped!
4108 //foreach ($this->opData['output']['parts'] as $name => $type) {
4109 // $this->debug('wrap in element named ' . $name);
4110 //}
4111 $opParams = array($this->methodreturn);
4112 }
4113 $return_val = $this->wsdl->serializeRPCParameters($this->methodname, 'output', $opParams);
4114 $this->appendDebug($this->wsdl->getDebug());
4115 $this->wsdl->clearDebug();
4116 if ($errstr = $this->wsdl->getError()) {
4117 $this->debug('got wsdl error: ' . $errstr);
4118 $this->fault('SOAP-ENV:Server', 'unable to serialize result');
4119 return;
4120 }
4121 } else {
4122 if (isset($this->methodreturn)) {
4123 $return_val = $this->serialize_val($this->methodreturn, 'return');
4124 } else {
4125 $return_val = '';
4126 $this->debug('in absence of WSDL, assume void return for backward compatibility');
4127 }
4128 }
4129 }
4130 $this->debug('return value:');
4131 $this->appendDebug($this->varDump($return_val));
4132
4133 $this->debug('serializing response');
4134 if ($this->wsdl) {
4135 $this->debug('have WSDL for serialization: style is ' . $this->opData['style']);
4136 if ($this->opData['style'] == 'rpc') {
4137 $this->debug('style is rpc for serialization: use is ' . $this->opData['output']['use']);
4138 if ($this->opData['output']['use'] == 'literal') {
4139 // 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
4140 $payload = '<ns1:' . $this->methodname . 'Response xmlns:ns1="' . $this->methodURI . '">' . $return_val . '</ns1:' . $this->methodname . "Response>";
4141 } else {
4142 $payload = '<ns1:' . $this->methodname . 'Response xmlns:ns1="' . $this->methodURI . '">' . $return_val . '</ns1:' . $this->methodname . "Response>";
4143 }
4144 } else {
4145 $this->debug('style is not rpc for serialization: assume document');
4146 $payload = $return_val;
4147 }
4148 } else {
4149 $this->debug('do not have WSDL for serialization: assume rpc/encoded');
4150 $payload = '<ns1:' . $this->methodname . 'Response xmlns:ns1="' . $this->methodURI . '">' . $return_val . '</ns1:' . $this->methodname . "Response>";
4151 }
4152 $this->result = 'successful';
4153 if ($this->wsdl) {
4154 //if($this->debug_flag){
4155 $this->appendDebug($this->wsdl->getDebug());
4156 // }
4157 if (isset($opData['output']['encodingStyle'])) {
4158 $encodingStyle = $opData['output']['encodingStyle'];
4159 } else {
4160 $encodingStyle = '';
4161 }
4162 // Added: In case we use a WSDL, return a serialized env. WITH the usedNamespaces.
4163 $this->responseSOAP = $this->serializeEnvelope($payload, $this->responseHeaders, $this->wsdl->usedNamespaces, $this->opData['style'], $this->opData['output']['use'], $encodingStyle);
4164 } else {
4165 $this->responseSOAP = $this->serializeEnvelope($payload, $this->responseHeaders);
4166 }
4167 $this->debug("Leaving serialize_return");
4168 }
4169
4180 public function send_response()
4181 {
4182 $this->debug('Enter send_response');
4183 if ($this->fault) {
4184 $payload = $this->fault->serialize();
4185 $this->outgoing_headers[] = "HTTP/1.0 500 Internal Server Error";
4186 $this->outgoing_headers[] = "Status: 500 Internal Server Error";
4187 } else {
4189 // Some combinations of PHP+Web server allow the Status
4190 // to come through as a header. Since OK is the default
4191 // just do nothing.
4192 // $this->outgoing_headers[] = "HTTP/1.0 200 OK";
4193 // $this->outgoing_headers[] = "Status: 200 OK";
4194 }
4195 // add debug data if in debug mode
4196 if (isset($this->debug_flag) && $this->debug_flag) {
4197 $payload .= $this->getDebugAsXMLComment();
4198 }
4199 $this->outgoing_headers[] = "Server: $this->title Server v$this->version";
4200 preg_match('/\$Revisio' . 'n: ([^ ]+)/', $this->revision, $rev);
4201 $this->outgoing_headers[] = "X-SOAP-Server: $this->title/$this->version (" . $rev[1] . ")";
4202 // Let the Web server decide about this
4203 //$this->outgoing_headers[] = "Connection: Close\r\n";
4204 $payload = $this->getHTTPBody($payload);
4205 $type = $this->getHTTPContentType();
4206 $charset = $this->getHTTPContentTypeCharset();
4207 $this->outgoing_headers[] = "Content-Type: $type" . ($charset ? '; charset=' . $charset : '');
4208 //begin code to compress payload - by John
4209 // NOTE: there is no way to know whether the Web server will also compress
4210 // this data.
4211 if (strlen($payload) > 1024 && isset($this->headers) && isset($this->headers['accept-encoding'])) {
4212 if (strstr($this->headers['accept-encoding'], 'gzip')) {
4213 if (function_exists('gzencode')) {
4214 if (isset($this->debug_flag) && $this->debug_flag) {
4215 $payload .= "<!-- Content being gzipped -->";
4216 }
4217 $this->outgoing_headers[] = "Content-Encoding: gzip";
4218 $payload = gzencode($payload);
4219 } else {
4220 if (isset($this->debug_flag) && $this->debug_flag) {
4221 $payload .= "<!-- Content will not be gzipped: no gzencode -->";
4222 }
4223 }
4224 } elseif (strstr($this->headers['accept-encoding'], 'deflate')) {
4225 // Note: MSIE requires gzdeflate output (no Zlib header and checksum),
4226 // instead of gzcompress output,
4227 // which conflicts with HTTP 1.1 spec (http://www.w3.org/Protocols/rfc2616/rfc2616-sec3.html#sec3.5)
4228 if (function_exists('gzdeflate')) {
4229 if (isset($this->debug_flag) && $this->debug_flag) {
4230 $payload .= "<!-- Content being deflated -->";
4231 }
4232 $this->outgoing_headers[] = "Content-Encoding: deflate";
4233 $payload = gzdeflate($payload);
4234 } else {
4235 if (isset($this->debug_flag) && $this->debug_flag) {
4236 $payload .= "<!-- Content will not be deflated: no gzcompress -->";
4237 }
4238 }
4239 }
4240 }
4241 //end code
4242 $this->outgoing_headers[] = "Content-Length: " . strlen($payload);
4243 reset($this->outgoing_headers);
4244 foreach ($this->outgoing_headers as $hdr) {
4245 header($hdr, false);
4246 }
4247 print $payload;
4248 $this->response = join("\r\n", $this->outgoing_headers) . "\r\n\r\n" . $payload;
4249 }
4250
4260 public function verify_method($operation, $request)
4261 {
4262 if (isset($this->wsdl) && is_object($this->wsdl)) {
4263 if ($this->wsdl->getOperationData($operation)) {
4264 return true;
4265 }
4266 } elseif (isset($this->operations[$operation])) {
4267 return true;
4268 }
4269 return false;
4270 }
4271
4280 public function parseRequest($headers, $data)
4281 {
4282 $this->debug('Entering parseRequest() for data of length ' . strlen($data) . ' and type ' . $headers['content-type']);
4283 if (!strstr($headers['content-type'], 'text/xml')) {
4284 $this->setError('Request not of type text/xml');
4285 return false;
4286 }
4287 if (strpos($headers['content-type'], '=')) {
4288 $enc = str_replace('"', '', substr(strstr($headers["content-type"], '='), 1));
4289 $this->debug('Got response encoding: ' . $enc);
4290 if (preg_match('/^(ISO-8859-1|US-ASCII|UTF-8)$/i', $enc)) {
4291 $this->xml_encoding = strtoupper($enc);
4292 } else {
4293 $this->xml_encoding = 'US-ASCII';
4294 }
4295 } else {
4296 // should be US-ASCII for HTTP 1.0 or ISO-8859-1 for HTTP 1.1
4297 $this->xml_encoding = 'ISO-8859-1';
4298 }
4299 $this->debug('Use encoding: ' . $this->xml_encoding . ' when creating nusoap_parser');
4300 // parse response, get soap parser obj
4301 $parser = new nusoap_parser($data, $this->xml_encoding, '', $this->decode_utf8);
4302 // parser debug
4303 $this->debug("parser debug: \n" . $parser->getDebug());
4304 // if fault occurred during message parsing
4305 if ($err = $parser->getError()) {
4306 $this->result = 'fault: error in msg parsing: ' . $err;
4307 $this->fault('SOAP-ENV:Client', "error in msg parsing:\n" . $err);
4308 // else successfully parsed request into soapval object
4309 } else {
4310 // get/set methodname
4311 $this->methodURI = $parser->root_struct_namespace;
4312 $this->methodname = $parser->root_struct_name;
4313 $this->debug('methodname: ' . $this->methodname . ' methodURI: ' . $this->methodURI);
4314 $this->debug('calling parser->get_soapbody()');
4315 $this->methodparams = $parser->get_soapbody();
4316 // get SOAP headers
4317 $this->requestHeaders = $parser->getHeaders();
4318 // get SOAP Header
4319 $this->requestHeader = $parser->get_soapheader();
4320 // add document for doclit support
4321 $this->document = $parser->document;
4322 }
4323 }
4324
4332 public function getHTTPBody($soapmsg)
4333 {
4334 return $soapmsg;
4335 }
4336
4345 public function getHTTPContentType()
4346 {
4347 return 'text/xml';
4348 }
4349
4360 {
4362 }
4363
4373 public function add_to_map($methodname, $in, $out)
4374 {
4375 $this->operations[$methodname] = array('name' => $methodname,'in' => $in,'out' => $out);
4376 }
4377
4392 public function register($name, $in = array(), $out = array(), $namespace = false, $soapaction = false, $style = false, $use = false, $documentation = '', $encodingStyle = '')
4393 {
4394 global $HTTP_SERVER_VARS;
4395
4396 if ($this->externalWSDLURL) {
4397 die('You cannot bind to an external WSDL file, and register methods outside of it! Please choose either WSDL or no WSDL.');
4398 }
4399 if (! $name) {
4400 die('You must specify a name when you register an operation');
4401 }
4402 if (!is_array($in)) {
4403 die('You must provide an array for operation inputs');
4404 }
4405 if (!is_array($out)) {
4406 die('You must provide an array for operation outputs');
4407 }
4408 if (false == $namespace) {
4409 }
4410 if (false == $soapaction) {
4411 if (isset($_SERVER)) {
4412 $SERVER_NAME = $_SERVER['SERVER_NAME'];
4413 $SCRIPT_NAME = isset($_SERVER['PHP_SELF']) ? $_SERVER['PHP_SELF'] : $_SERVER['SCRIPT_NAME'];
4414 $HTTPS = isset($_SERVER['HTTPS']) ? $_SERVER['HTTPS'] : (isset($HTTP_SERVER_VARS['HTTPS']) ? $HTTP_SERVER_VARS['HTTPS'] : 'off');
4415 } elseif (isset($HTTP_SERVER_VARS)) {
4416 $SERVER_NAME = $HTTP_SERVER_VARS['SERVER_NAME'];
4417 $SCRIPT_NAME = isset($HTTP_SERVER_VARS['PHP_SELF']) ? $HTTP_SERVER_VARS['PHP_SELF'] : $HTTP_SERVER_VARS['SCRIPT_NAME'];
4418 $HTTPS = isset($HTTP_SERVER_VARS['HTTPS']) ? $HTTP_SERVER_VARS['HTTPS'] : 'off';
4419 } else {
4420 $this->setError("Neither _SERVER nor HTTP_SERVER_VARS is available");
4421 }
4422 if ($HTTPS == '1' || $HTTPS == 'on') {
4423 $SCHEME = 'https';
4424 } else {
4425 $SCHEME = 'http';
4426 }
4427 $soapaction = "$SCHEME://$SERVER_NAME$SCRIPT_NAME/$name";
4428 }
4429 if (false == $style) {
4430 $style = "rpc";
4431 }
4432 if (false == $use) {
4433 $use = "encoded";
4434 }
4435 if ($use == 'encoded' && $encodingStyle = '') {
4436 $encodingStyle = 'http://schemas.xmlsoap.org/soap/encoding/';
4437 }
4438
4439 $this->operations[$name] = array(
4440 'name' => $name,
4441 'in' => $in,
4442 'out' => $out,
4443 'namespace' => $namespace,
4444 'soapaction' => $soapaction,
4445 'style' => $style);
4446 if ($this->wsdl) {
4447 $this->wsdl->addOperation($name, $in, $out, $namespace, $soapaction, $style, $use, $documentation, $encodingStyle);
4448 }
4449 return true;
4450 }
4451
4462 public function fault($faultcode, $faultstring, $faultactor = '', $faultdetail = '')
4463 {
4464 if ($faultdetail == '' && $this->debug_flag) {
4465 $faultdetail = $this->getDebug();
4466 }
4467 $this->fault = new nusoap_fault($faultcode, $faultactor, $faultstring, $faultdetail);
4468 $this->fault->soap_defencoding = $this->soap_defencoding;
4469 }
4470
4482 public function configureWSDL($serviceName, $namespace = false, $endpoint = false, $style = 'rpc', $transport = 'http://schemas.xmlsoap.org/soap/http', $schemaTargetNamespace = false)
4483 {
4484 global $HTTP_SERVER_VARS;
4485
4486 if (isset($_SERVER)) {
4487 $SERVER_NAME = $_SERVER['SERVER_NAME'];
4488 $SERVER_PORT = $_SERVER['SERVER_PORT'];
4489 $SCRIPT_NAME = isset($_SERVER['PHP_SELF']) ? $_SERVER['PHP_SELF'] : $_SERVER['SCRIPT_NAME'];
4490 $HTTPS = isset($_SERVER['HTTPS']) ? $_SERVER['HTTPS'] : (isset($HTTP_SERVER_VARS['HTTPS']) ? $HTTP_SERVER_VARS['HTTPS'] : 'off');
4491 } elseif (isset($HTTP_SERVER_VARS)) {
4492 $SERVER_NAME = $HTTP_SERVER_VARS['SERVER_NAME'];
4493 $SERVER_PORT = $HTTP_SERVER_VARS['SERVER_PORT'];
4494 $SCRIPT_NAME = isset($HTTP_SERVER_VARS['PHP_SELF']) ? $HTTP_SERVER_VARS['PHP_SELF'] : $HTTP_SERVER_VARS['SCRIPT_NAME'];
4495 $HTTPS = isset($HTTP_SERVER_VARS['HTTPS']) ? $HTTP_SERVER_VARS['HTTPS'] : 'off';
4496 } else {
4497 $this->setError("Neither _SERVER nor HTTP_SERVER_VARS is available");
4498 }
4499 // If server name has port number attached then strip it (else port number gets duplicated in WSDL output) (occurred using lighttpd and FastCGI)
4500 $colon = strpos($SERVER_NAME, ":");
4501 if ($colon) {
4502 $SERVER_NAME = substr($SERVER_NAME, 0, $colon);
4503 }
4504 if ($SERVER_PORT == 80) {
4505 $SERVER_PORT = '';
4506 } else {
4507 $SERVER_PORT = ':' . $SERVER_PORT;
4508 }
4509 if (false == $namespace) {
4510 $namespace = "http://$SERVER_NAME/soap/$serviceName";
4511 }
4512
4513 if (false == $endpoint) {
4514 if ($HTTPS == '1' || $HTTPS == 'on') {
4515 $SCHEME = 'https';
4516 } else {
4517 $SCHEME = 'http';
4518 }
4519 $endpoint = "$SCHEME://$SERVER_NAME$SERVER_PORT$SCRIPT_NAME";
4520 }
4521
4522 if (false == $schemaTargetNamespace) {
4523 $schemaTargetNamespace = $namespace;
4524 }
4525
4526 $this->wsdl = new wsdl();
4527 $this->wsdl->serviceName = $serviceName;
4528 $this->wsdl->endpoint = $endpoint;
4529 $this->wsdl->namespaces['tns'] = $namespace;
4530 $this->wsdl->namespaces['soap'] = 'http://schemas.xmlsoap.org/wsdl/soap/';
4531 $this->wsdl->namespaces['wsdl'] = 'http://schemas.xmlsoap.org/wsdl/';
4532 if ($schemaTargetNamespace != $namespace) {
4533 $this->wsdl->namespaces['types'] = $schemaTargetNamespace;
4534 }
4535 $this->wsdl->schemas[$schemaTargetNamespace][0] = new nusoap_xmlschema('', '', $this->wsdl->namespaces);
4536 if ($style == 'document') {
4537 $this->wsdl->schemas[$schemaTargetNamespace][0]->schemaInfo['elementFormDefault'] = 'qualified';
4538 }
4539 $this->wsdl->schemas[$schemaTargetNamespace][0]->schemaTargetNamespace = $schemaTargetNamespace;
4540 $this->wsdl->schemas[$schemaTargetNamespace][0]->imports['http://schemas.xmlsoap.org/soap/encoding/'][0] = array('location' => '', 'loaded' => true);
4541 $this->wsdl->schemas[$schemaTargetNamespace][0]->imports['http://schemas.xmlsoap.org/wsdl/'][0] = array('location' => '', 'loaded' => true);
4542 $this->wsdl->bindings[$serviceName . 'Binding'] = array(
4543 'name' => $serviceName . 'Binding',
4544 'style' => $style,
4545 'transport' => $transport,
4546 'portType' => $serviceName . 'PortType');
4547 $this->wsdl->ports[$serviceName . 'Port'] = array(
4548 'binding' => $serviceName . 'Binding',
4549 'location' => $endpoint,
4550 'bindingType' => 'http://schemas.xmlsoap.org/wsdl/soap/');
4551 }
4552
4553 public function addInternalPort(string $serviceName, string $url): void
4554 {
4555 $this->wsdl->ports['Internal' . $serviceName . 'Port'] = [
4556 'binding' => $serviceName . 'Binding',
4557 'location' => (string) (new \ILIAS\Data\URI($url))->withQuery(),
4558 'bindingType' => 'http://schemas.xmlsoap.org/wsdl/soap/'
4559 ];
4560 }
4561}
4562
4567{
4568}
4569
4570?><?php
4571
4572
4573
4583class wsdl extends nusoap_base
4584{
4585 // URL or filename of the root of this WSDL
4589 public $wsdl;
4590 // define internal arrays of bindings, ports, operations, messages, etc.
4591 public $schemas = array();
4593 public $message = array();
4594 public $complexTypes = array();
4595 public $messages = array();
4598 public $portTypes = array();
4600 public $bindings = array();
4602 public $ports = array();
4604 public $opData = array();
4605 public $status = '';
4606 public $documentation = false;
4607 public $endpoint = '';
4608 // array of wsdl docs to import
4609 public $import = array();
4610 // parser vars
4611 public $parser;
4612 public $position = 0;
4613 public $depth = 0;
4614 public $depth_array = array();
4615 // for getting wsdl
4616 public $proxyhost = '';
4617 public $proxyport = '';
4618 public $proxyusername = '';
4619 public $proxypassword = '';
4620 public $timeout = 0;
4622 public $curl_options = array(); // User-specified cURL options
4623 public $use_curl = false; // whether to always try to use cURL
4624 // for HTTP authentication
4625 public $username = ''; // Username for HTTP authentication
4626 public $password = ''; // Password for HTTP authentication
4627 public $authtype = ''; // Type of HTTP authentication
4628 public $certRequest = array(); // Certificate for HTTP SSL authentication
4629
4644 public function __construct($wsdl = '', $proxyhost = false, $proxyport = false, $proxyusername = false, $proxypassword = false, $timeout = 0, $response_timeout = 30, $curl_options = null, $use_curl = false)
4645 {
4647 $this->debug("ctor wsdl=$wsdl timeout=$timeout response_timeout=$response_timeout");
4648 $this->proxyhost = $proxyhost;
4649 $this->proxyport = $proxyport;
4650 $this->proxyusername = $proxyusername;
4651 $this->proxypassword = $proxypassword;
4652 $this->timeout = $timeout;
4653 $this->response_timeout = $response_timeout;
4654 if (is_array($curl_options)) {
4655 $this->curl_options = $curl_options;
4656 }
4657 $this->use_curl = $use_curl;
4658 $this->fetchWSDL($wsdl);
4659 }
4660
4666 public function fetchWSDL($wsdl)
4667 {
4668 $this->debug("parse and process WSDL path=$wsdl");
4669 $this->wsdl = $wsdl;
4670 // parse wsdl file
4671 if ($this->wsdl != "") {
4672 $this->parseWSDL($this->wsdl);
4673 }
4674 // imports
4675 // TODO: handle imports more properly, grabbing them in-line and nesting them
4676 $imported_urls = array();
4677 $imported = 1;
4678 while ($imported > 0) {
4679 $imported = 0;
4680 // Schema imports
4681 foreach ($this->schemas as $ns => $list) {
4682 foreach ($list as $xs) {
4683 $wsdlparts = parse_url($this->wsdl); // this is bogusly simple!
4684 foreach ($xs->imports as $ns2 => $list2) {
4685 for ($ii = 0; $ii < count($list2); $ii++) {
4686 if (! $list2[$ii]['loaded']) {
4687 $this->schemas[$ns]->imports[$ns2][$ii]['loaded'] = true;
4688 $url = $list2[$ii]['location'];
4689 if ($url != '') {
4690 $urlparts = parse_url($url);
4691 if (!isset($urlparts['host'])) {
4692 $url = $wsdlparts['scheme'] . '://' . $wsdlparts['host'] . (isset($wsdlparts['port']) ? ':' . $wsdlparts['port'] : '') .
4693 substr($wsdlparts['path'], 0, strrpos($wsdlparts['path'], '/') + 1) . $urlparts['path'];
4694 }
4695 if (! in_array($url, $imported_urls)) {
4696 $this->parseWSDL($url);
4697 $imported++;
4698 $imported_urls[] = $url;
4699 }
4700 } else {
4701 $this->debug("Unexpected scenario: empty URL for unloaded import");
4702 }
4703 }
4704 }
4705 }
4706 }
4707 }
4708 // WSDL imports
4709 $wsdlparts = parse_url($this->wsdl); // this is bogusly simple!
4710 foreach ($this->import as $ns => $list) {
4711 for ($ii = 0; $ii < count($list); $ii++) {
4712 if (! $list[$ii]['loaded']) {
4713 $this->import[$ns][$ii]['loaded'] = true;
4714 $url = $list[$ii]['location'];
4715 if ($url != '') {
4716 $urlparts = parse_url($url);
4717 if (!isset($urlparts['host'])) {
4718 $url = $wsdlparts['scheme'] . '://' . $wsdlparts['host'] . (isset($wsdlparts['port']) ? ':' . $wsdlparts['port'] : '') .
4719 substr($wsdlparts['path'], 0, strrpos($wsdlparts['path'], '/') + 1) . $urlparts['path'];
4720 }
4721 if (! in_array($url, $imported_urls)) {
4722 $this->parseWSDL($url);
4723 $imported++;
4724 $imported_urls[] = $url;
4725 }
4726 } else {
4727 $this->debug("Unexpected scenario: empty URL for unloaded import");
4728 }
4729 }
4730 }
4731 }
4732 }
4733 // add new data to operation data
4734 foreach ($this->bindings as $binding => $bindingData) {
4735 if (isset($bindingData['operations']) && is_array($bindingData['operations'])) {
4736 foreach ($bindingData['operations'] as $operation => $data) {
4737 $this->debug('post-parse data gathering for ' . $operation);
4738 $this->bindings[$binding]['operations'][$operation]['input'] =
4739 isset($this->bindings[$binding]['operations'][$operation]['input']) ?
4740 array_merge($this->bindings[$binding]['operations'][$operation]['input'], $this->portTypes[ $bindingData['portType'] ][$operation]['input']) :
4741 $this->portTypes[ $bindingData['portType'] ][$operation]['input'];
4742 $this->bindings[$binding]['operations'][$operation]['output'] =
4743 isset($this->bindings[$binding]['operations'][$operation]['output']) ?
4744 array_merge($this->bindings[$binding]['operations'][$operation]['output'], $this->portTypes[ $bindingData['portType'] ][$operation]['output']) :
4745 $this->portTypes[ $bindingData['portType'] ][$operation]['output'];
4746 if (isset($this->messages[ $this->bindings[$binding]['operations'][$operation]['input']['message'] ])) {
4747 $this->bindings[$binding]['operations'][$operation]['input']['parts'] = $this->messages[ $this->bindings[$binding]['operations'][$operation]['input']['message'] ];
4748 }
4749 if (isset($this->messages[ $this->bindings[$binding]['operations'][$operation]['output']['message'] ])) {
4750 $this->bindings[$binding]['operations'][$operation]['output']['parts'] = $this->messages[ $this->bindings[$binding]['operations'][$operation]['output']['message'] ];
4751 }
4752 // Set operation style if necessary, but do not override one already provided
4753 if (isset($bindingData['style']) && !isset($this->bindings[$binding]['operations'][$operation]['style'])) {
4754 $this->bindings[$binding]['operations'][$operation]['style'] = $bindingData['style'];
4755 }
4756 $this->bindings[$binding]['operations'][$operation]['transport'] = isset($bindingData['transport']) ? $bindingData['transport'] : '';
4757 $this->bindings[$binding]['operations'][$operation]['documentation'] = isset($this->portTypes[ $bindingData['portType'] ][$operation]['documentation']) ? $this->portTypes[ $bindingData['portType'] ][$operation]['documentation'] : '';
4758 $this->bindings[$binding]['operations'][$operation]['endpoint'] = isset($bindingData['endpoint']) ? $bindingData['endpoint'] : '';
4759 }
4760 }
4761 }
4762 }
4763
4770 public function parseWSDL($wsdl = '')
4771 {
4772 $this->debug("parse WSDL at path=$wsdl");
4773
4774 if ($wsdl == '') {
4775 $this->debug('no wsdl passed to parseWSDL()!!');
4776 $this->setError('no wsdl passed to parseWSDL()!!');
4777 return false;
4778 }
4779
4780 // parse $wsdl for url format
4781 $wsdl_props = parse_url($wsdl);
4782
4783 if (isset($wsdl_props['scheme']) && ($wsdl_props['scheme'] == 'http' || $wsdl_props['scheme'] == 'https')) {
4784 $this->debug('getting WSDL http(s) URL ' . $wsdl);
4785 // get wsdl
4786 $tr = new soap_transport_http($wsdl, $this->curl_options, $this->use_curl);
4787 $tr->request_method = 'GET';
4788 $tr->useSOAPAction = false;
4789 if ($this->proxyhost && $this->proxyport) {
4790 $tr->setProxy($this->proxyhost, $this->proxyport, $this->proxyusername, $this->proxypassword);
4791 }
4792 if ($this->authtype != '') {
4793 $tr->setCredentials($this->username, $this->password, $this->authtype, array(), $this->certRequest);
4794 }
4795 $tr->setEncoding('gzip, deflate');
4796 $wsdl_string = $tr->send('', $this->timeout, $this->response_timeout);
4797 //$this->debug("WSDL request\n" . $tr->outgoing_payload);
4798 //$this->debug("WSDL response\n" . $tr->incoming_payload);
4799 $this->appendDebug($tr->getDebug());
4800 // catch errors
4801 if ($err = $tr->getError()) {
4802 $errstr = 'HTTP ERROR: ' . $err;
4803 $this->debug($errstr);
4804 $this->setError($errstr);
4805 unset($tr);
4806 return false;
4807 }
4808 unset($tr);
4809 $this->debug("got WSDL URL");
4810 } else {
4811 // $wsdl is not http(s), so treat it as a file URL or plain file path
4812 if (isset($wsdl_props['scheme']) && ($wsdl_props['scheme'] == 'file') && isset($wsdl_props['path'])) {
4813 $path = isset($wsdl_props['host']) ? ($wsdl_props['host'] . ':' . $wsdl_props['path']) : $wsdl_props['path'];
4814 } else {
4815 $path = $wsdl;
4816 }
4817 $this->debug('getting WSDL file ' . $path);
4818 if ($fp = @fopen($path, 'r')) {
4819 $wsdl_string = '';
4820 while ($data = fread($fp, 32768)) {
4821 $wsdl_string .= $data;
4822 }
4823 fclose($fp);
4824 } else {
4825 $errstr = "Bad path to WSDL file $path";
4826 $this->debug($errstr);
4827 $this->setError($errstr);
4828 return false;
4829 }
4830 }
4831 $this->debug('Parse WSDL');
4832 // end new code added
4833 // Create an XML parser.
4834 $this->parser = xml_parser_create();
4835 // Set the options for parsing the XML data.
4836 // xml_parser_set_option($parser, XML_OPTION_SKIP_WHITE, 1);
4837 xml_parser_set_option($this->parser, XML_OPTION_CASE_FOLDING, 0);
4838 // Set the object for the parser.
4839 // Set the element handlers for the parser.
4840 xml_set_element_handler($this->parser, $this->start_element(...), $this->end_element(...));
4841 xml_set_character_data_handler($this->parser, $this->character_data(...));
4842 // Parse the XML file.
4843 if (!xml_parse($this->parser, $wsdl_string, true)) {
4844 // Display an error message.
4845 $errstr = sprintf(
4846 'XML error parsing WSDL from %s on line %d: %s',
4847 $wsdl,
4848 xml_get_current_line_number($this->parser),
4849 xml_error_string(xml_get_error_code($this->parser))
4850 );
4851 $this->debug($errstr);
4852 $this->debug("XML payload:\n" . $wsdl_string);
4853 $this->setError($errstr);
4854 return false;
4855 }
4856 // free the parser
4857 xml_parser_free($this->parser);
4858 $this->debug('Parsing WSDL done');
4859 // catch wsdl parse errors
4860 if ($this->getError()) {
4861 return false;
4862 }
4863 return true;
4864 }
4865
4874 public function start_element($parser, $name, $attrs)
4875 {
4876 if ($this->status == 'schema') {
4877 $this->currentSchema->schemaStartElement($parser, $name, $attrs);
4878 $this->appendDebug($this->currentSchema->getDebug());
4879 $this->currentSchema->clearDebug();
4880 } elseif (preg_match('/schema$/', $name)) {
4881 $this->debug('Parsing WSDL schema');
4882 // $this->debug("startElement for $name ($attrs[name]). status = $this->status (".$this->getLocalPart($name).")");
4883 $this->status = 'schema';
4884 $this->currentSchema = new nusoap_xmlschema('', '', $this->namespaces);
4885 $this->currentSchema->schemaStartElement($parser, $name, $attrs);
4886 $this->appendDebug($this->currentSchema->getDebug());
4887 $this->currentSchema->clearDebug();
4888 } else {
4889 // position in the total number of elements, starting from 0
4890 $pos = $this->position++;
4891 $depth = $this->depth++;
4892 // set self as current value for this depth
4893 $this->depth_array[$depth] = $pos;
4894 $this->message[$pos] = array('cdata' => '');
4895 // process attributes
4896 if (count($attrs) > 0) {
4897 // register namespace declarations
4898 foreach ($attrs as $k => $v) {
4899 if (preg_match('/^xmlns/', $k)) {
4900 if ($ns_prefix = substr(strrchr($k, ':'), 1)) {
4901 $this->namespaces[$ns_prefix] = $v;
4902 } else {
4903 $this->namespaces['ns' . (count($this->namespaces) + 1)] = $v;
4904 }
4905 if ($v == 'http://www.w3.org/2001/XMLSchema' || $v == 'http://www.w3.org/1999/XMLSchema' || $v == 'http://www.w3.org/2000/10/XMLSchema') {
4906 $this->XMLSchemaVersion = $v;
4907 $this->namespaces['xsi'] = $v . '-instance';
4908 }
4909 }
4910 }
4911 // expand each attribute prefix to its namespace
4912 foreach ($attrs as $k => $v) {
4913 $k = strpos($k, ':') ? $this->expandQname($k) : $k;
4914 if ($k != 'location' && $k != 'soapAction' && $k != 'namespace') {
4915 $v = strpos($v, ':') ? $this->expandQname($v) : $v;
4916 }
4917 $eAttrs[$k] = $v;
4918 }
4919 $attrs = $eAttrs;
4920 } else {
4921 $attrs = array();
4922 }
4923 // get element prefix, namespace and name
4924 if (preg_match('/:/', $name)) {
4925 // get ns prefix
4926 $prefix = substr($name, 0, strpos($name, ':'));
4927 // get ns
4928 $namespace = isset($this->namespaces[$prefix]) ? $this->namespaces[$prefix] : '';
4929 // get unqualified name
4930 $name = substr(strstr($name, ':'), 1);
4931 }
4932 // process attributes, expanding any prefixes to namespaces
4933 // find status, register data
4934 switch ($this->status) {
4935 case 'message':
4936 if ($name == 'part') {
4937 if (isset($attrs['type'])) {
4938 $this->debug("msg " . $this->currentMessage . ": found part (with type) $attrs[name]: " . implode(',', $attrs));
4939 $this->messages[$this->currentMessage][$attrs['name']] = $attrs['type'];
4940 }
4941 if (isset($attrs['element'])) {
4942 $this->debug("msg " . $this->currentMessage . ": found part (with element) $attrs[name]: " . implode(',', $attrs));
4943 $this->messages[$this->currentMessage][$attrs['name']] = $attrs['element'] . '^';
4944 }
4945 }
4946 break;
4947 case 'portType':
4948 switch ($name) {
4949 case 'operation':
4950 $this->currentPortOperation = $attrs['name'];
4951 $this->debug("portType $this->currentPortType operation: $this->currentPortOperation");
4952 if (isset($attrs['parameterOrder'])) {
4953 $this->portTypes[$this->currentPortType][$attrs['name']]['parameterOrder'] = $attrs['parameterOrder'];
4954 }
4955 break;
4956 case 'documentation':
4957 $this->documentation = true;
4958 break;
4959 // merge input/output data
4960 default:
4961 $m = isset($attrs['message']) ? $this->getLocalPart($attrs['message']) : '';
4962 $this->portTypes[$this->currentPortType][$this->currentPortOperation][$name]['message'] = $m;
4963 break;
4964 }
4965 break;
4966 case 'binding':
4967 switch ($name) {
4968 case 'binding':
4969 // get ns prefix
4970 if (isset($attrs['style'])) {
4971 $this->bindings[$this->currentBinding]['prefix'] = $prefix;
4972 }
4973 $this->bindings[$this->currentBinding] = array_merge($this->bindings[$this->currentBinding], $attrs);
4974 break;
4975 case 'header':
4976 $this->bindings[$this->currentBinding]['operations'][$this->currentOperation][$this->opStatus]['headers'][] = $attrs;
4977 break;
4978 case 'operation':
4979 if (isset($attrs['soapAction'])) {
4980 $this->bindings[$this->currentBinding]['operations'][$this->currentOperation]['soapAction'] = $attrs['soapAction'];
4981 }
4982 if (isset($attrs['style'])) {
4983 $this->bindings[$this->currentBinding]['operations'][$this->currentOperation]['style'] = $attrs['style'];
4984 }
4985 if (isset($attrs['name'])) {
4986 $this->currentOperation = $attrs['name'];
4987 $this->debug("current binding operation: $this->currentOperation");
4988 $this->bindings[$this->currentBinding]['operations'][$this->currentOperation]['name'] = $attrs['name'];
4989 $this->bindings[$this->currentBinding]['operations'][$this->currentOperation]['binding'] = $this->currentBinding;
4990 $this->bindings[$this->currentBinding]['operations'][$this->currentOperation]['endpoint'] = isset($this->bindings[$this->currentBinding]['endpoint']) ? $this->bindings[$this->currentBinding]['endpoint'] : '';
4991 }
4992 break;
4993 case 'input':
4994 $this->opStatus = 'input';
4995 break;
4996 case 'output':
4997 $this->opStatus = 'output';
4998 break;
4999 case 'body':
5000 if (isset($this->bindings[$this->currentBinding]['operations'][$this->currentOperation][$this->opStatus])) {
5001 $this->bindings[$this->currentBinding]['operations'][$this->currentOperation][$this->opStatus] = array_merge($this->bindings[$this->currentBinding]['operations'][$this->currentOperation][$this->opStatus], $attrs);
5002 } else {
5003 $this->bindings[$this->currentBinding]['operations'][$this->currentOperation][$this->opStatus] = $attrs;
5004 }
5005 break;
5006 }
5007 break;
5008 case 'service':
5009 switch ($name) {
5010 case 'port':
5011 $this->currentPort = $attrs['name'];
5012 $this->debug('current port: ' . $this->currentPort);
5013 $this->ports[$this->currentPort]['binding'] = $this->getLocalPart($attrs['binding']);
5014
5015 break;
5016 case 'address':
5017 $this->ports[$this->currentPort]['location'] = $attrs['location'];
5018 $this->ports[$this->currentPort]['bindingType'] = $namespace;
5019 $this->bindings[ $this->ports[$this->currentPort]['binding'] ]['bindingType'] = $namespace;
5020 $this->bindings[ $this->ports[$this->currentPort]['binding'] ]['endpoint'] = $attrs['location'];
5021 break;
5022 }
5023 break;
5024 }
5025 // set status
5026 switch ($name) {
5027 case 'import':
5028 if (isset($attrs['location'])) {
5029 $this->import[$attrs['namespace']][] = array('location' => $attrs['location'], 'loaded' => false);
5030 $this->debug('parsing import ' . $attrs['namespace'] . ' - ' . $attrs['location'] . ' (' . count($this->import[$attrs['namespace']]) . ')');
5031 } else {
5032 $this->import[$attrs['namespace']][] = array('location' => '', 'loaded' => true);
5033 if (! $this->getPrefixFromNamespace($attrs['namespace'])) {
5034 $this->namespaces['ns' . (count($this->namespaces) + 1)] = $attrs['namespace'];
5035 }
5036 $this->debug('parsing import ' . $attrs['namespace'] . ' - [no location] (' . count($this->import[$attrs['namespace']]) . ')');
5037 }
5038 break;
5039 //wait for schema
5040 //case 'types':
5041 // $this->status = 'schema';
5042 // break;
5043 case 'message':
5044 $this->status = 'message';
5045 $this->messages[$attrs['name']] = array();
5046 $this->currentMessage = $attrs['name'];
5047 break;
5048 case 'portType':
5049 $this->status = 'portType';
5050 $this->portTypes[$attrs['name']] = array();
5051 $this->currentPortType = $attrs['name'];
5052 break;
5053 case "binding":
5054 if (isset($attrs['name'])) {
5055 // get binding name
5056 if (strpos($attrs['name'], ':')) {
5057 $this->currentBinding = $this->getLocalPart($attrs['name']);
5058 } else {
5059 $this->currentBinding = $attrs['name'];
5060 }
5061 $this->status = 'binding';
5062 $this->bindings[$this->currentBinding]['portType'] = $this->getLocalPart($attrs['type']);
5063 $this->debug("current binding: $this->currentBinding of portType: " . $attrs['type']);
5064 }
5065 break;
5066 case 'service':
5067 $this->serviceName = $attrs['name'];
5068 $this->status = 'service';
5069 $this->debug('current service: ' . $this->serviceName);
5070 break;
5071 case 'definitions':
5072 foreach ($attrs as $name => $value) {
5073 $this->wsdl_info[$name] = $value;
5074 }
5075 break;
5076 }
5077 }
5078 }
5079
5087 public function end_element($parser, $name)
5088 {
5089 // unset schema status
5090 if (/*preg_match('/types$/', $name) ||*/ preg_match('/schema$/', $name)) {
5091 $this->status = "";
5092 $this->appendDebug($this->currentSchema->getDebug());
5093 $this->currentSchema->clearDebug();
5094 $this->schemas[$this->currentSchema->schemaTargetNamespace][] = $this->currentSchema;
5095 $this->debug('Parsing WSDL schema done');
5096 }
5097 if ($this->status == 'schema') {
5098 $this->currentSchema->schemaEndElement($parser, $name);
5099 } else {
5100 // bring depth down a notch
5101 $this->depth--;
5102 }
5103 // end documentation
5104 if ($this->documentation) {
5105 //TODO: track the node to which documentation should be assigned; it can be a part, message, etc.
5106 //$this->portTypes[$this->currentPortType][$this->currentPortOperation]['documentation'] = $this->documentation;
5107 $this->documentation = false;
5108 }
5109 }
5110
5118 public function character_data($parser, $data)
5119 {
5120 $pos = isset($this->depth_array[$this->depth]) ? $this->depth_array[$this->depth] : 0;
5121 if (isset($this->message[$pos]['cdata'])) {
5122 $this->message[$pos]['cdata'] .= $data;
5123 }
5124 if ($this->documentation) {
5125 $this->documentation .= $data;
5126 }
5127 }
5128
5138 public function setCredentials($username, $password, $authtype = 'basic', $certRequest = array())
5139 {
5140 $this->debug("setCredentials username=$username authtype=$authtype certRequest=");
5141 $this->appendDebug($this->varDump($certRequest));
5142 $this->username = $username;
5143 $this->password = $password;
5144 $this->authtype = $authtype;
5145 $this->certRequest = $certRequest;
5146 }
5147
5148 public function getBindingData($binding)
5149 {
5150 if (is_array($this->bindings[$binding])) {
5151 return $this->bindings[$binding];
5152 }
5153 }
5154
5162 public function getOperations($bindingType = 'soap')
5163 {
5164 $ops = array();
5165 if ($bindingType == 'soap') {
5166 $bindingType = 'http://schemas.xmlsoap.org/wsdl/soap/';
5167 } elseif ($bindingType == 'soap12') {
5168 $bindingType = 'http://schemas.xmlsoap.org/wsdl/soap12/';
5169 }
5170 // loop thru ports
5171 foreach ($this->ports as $port => $portData) {
5172 // binding type of port matches parameter
5173 if ($portData['bindingType'] == $bindingType) {
5174 //$this->debug("getOperations for port $port");
5175 //$this->debug("port data: " . $this->varDump($portData));
5176 //$this->debug("bindings: " . $this->varDump($this->bindings[ $portData['binding'] ]));
5177 // merge bindings
5178 if (isset($this->bindings[ $portData['binding'] ]['operations'])) {
5179 $ops = array_merge($ops, $this->bindings[ $portData['binding'] ]['operations']);
5180 }
5181 }
5182 }
5183 return $ops;
5184 }
5185
5194 public function getOperationData($operation, $bindingType = 'soap')
5195 {
5196 if ($bindingType == 'soap') {
5197 $bindingType = 'http://schemas.xmlsoap.org/wsdl/soap/';
5198 } elseif ($bindingType == 'soap12') {
5199 $bindingType = 'http://schemas.xmlsoap.org/wsdl/soap12/';
5200 }
5201 // loop thru ports
5202 foreach ($this->ports as $port => $portData) {
5203 // binding type of port matches parameter
5204 if ($portData['bindingType'] == $bindingType) {
5205 // get binding
5206 //foreach($this->bindings[ $portData['binding'] ]['operations'] as $bOperation => $opData) {
5207 foreach (array_keys($this->bindings[ $portData['binding'] ]['operations']) as $bOperation) {
5208 // note that we could/should also check the namespace here
5209 if ($operation == $bOperation) {
5210 $opData = $this->bindings[ $portData['binding'] ]['operations'][$operation];
5211 return $opData;
5212 }
5213 }
5214 }
5215 }
5216 }
5217
5226 public function getOperationDataForSoapAction($soapAction, $bindingType = 'soap')
5227 {
5228 if ($bindingType == 'soap') {
5229 $bindingType = 'http://schemas.xmlsoap.org/wsdl/soap/';
5230 } elseif ($bindingType == 'soap12') {
5231 $bindingType = 'http://schemas.xmlsoap.org/wsdl/soap12/';
5232 }
5233 // loop thru ports
5234 foreach ($this->ports as $port => $portData) {
5235 // binding type of port matches parameter
5236 if ($portData['bindingType'] == $bindingType) {
5237 // loop through operations for the binding
5238 foreach ($this->bindings[ $portData['binding'] ]['operations'] as $bOperation => $opData) {
5239 if ($opData['soapAction'] == $soapAction) {
5240 return $opData;
5241 }
5242 }
5243 }
5244 }
5245 }
5246
5265 public function getTypeDef($type, $ns)
5266 {
5267 $this->debug("in getTypeDef: type=$type, ns=$ns");
5268 if ((! $ns) && isset($this->namespaces['tns'])) {
5269 $ns = $this->namespaces['tns'];
5270 $this->debug("in getTypeDef: type namespace forced to $ns");
5271 }
5272 if (!isset($this->schemas[$ns])) {
5273 foreach ($this->schemas as $ns0 => $schema0) {
5274 if (strcasecmp($ns, $ns0) == 0) {
5275 $this->debug("in getTypeDef: replacing schema namespace $ns with $ns0");
5276 $ns = $ns0;
5277 break;
5278 }
5279 }
5280 }
5281 if (isset($this->schemas[$ns])) {
5282 $this->debug("in getTypeDef: have schema for namespace $ns");
5283 for ($i = 0; $i < count($this->schemas[$ns]); $i++) {
5284 $xs = &$this->schemas[$ns][$i];
5285 $t = $xs->getTypeDef($type);
5286 //$this->appendDebug($xs->getDebug());
5287 //$xs->clearDebug();
5288 if ($t) {
5289 if (!isset($t['phpType'])) {
5290 // get info for type to tack onto the element
5291 $uqType = substr($t['type'], strrpos($t['type'], ':') + 1);
5292 $ns = substr($t['type'], 0, strrpos($t['type'], ':'));
5293 $etype = $this->getTypeDef($uqType, $ns);
5294 if ($etype) {
5295 $this->debug("found type for [element] $type:");
5296 $this->debug($this->varDump($etype));
5297 if (isset($etype['phpType'])) {
5298 $t['phpType'] = $etype['phpType'];
5299 }
5300 if (isset($etype['elements'])) {
5301 $t['elements'] = $etype['elements'];
5302 }
5303 if (isset($etype['attrs'])) {
5304 $t['attrs'] = $etype['attrs'];
5305 }
5306 }
5307 }
5308 return $t;
5309 }
5310 }
5311 } else {
5312 $this->debug("in getTypeDef: do not have schema for namespace $ns");
5313 }
5314 return false;
5315 }
5316
5322 public function webDescription()
5323 {
5324 global $HTTP_SERVER_VARS;
5325
5326 if (isset($_SERVER)) {
5327 $PHP_SELF = $_SERVER['PHP_SELF'];
5328 } elseif (isset($HTTP_SERVER_VARS)) {
5329 $PHP_SELF = $HTTP_SERVER_VARS['PHP_SELF'];
5330 } else {
5331 $this->setError("Neither _SERVER nor HTTP_SERVER_VARS is available");
5332 }
5333 // begin-patch: https://mantis.ilias.de/view.php?id=28866
5334 $PHP_SELF = htmlspecialchars($PHP_SELF, ENT_QUOTES | ENT_HTML5, 'UTF-8');
5335 // end-patch
5336
5337 $b = '
5338 <html><head><title>NuSOAP: ' . $this->serviceName . '</title>
5339 <style type="text/css">
5340 body { font-family: arial; color: #000000; background-color: #ffffff; margin: 0px 0px 0px 0px; }
5341 p { font-family: arial; color: #000000; margin-top: 0px; margin-bottom: 12px; }
5342 pre { background-color: silver; padding: 5px; font-family: Courier New; font-size: x-small; color: #000000;}
5343 ul { margin-top: 10px; margin-left: 20px; }
5344 li { list-style-type: none; margin-top: 10px; color: #000000; }
5345 .content{
5346 margin-left: 0px; padding-bottom: 2em; }
5347 .nav {
5348 padding-top: 10px; padding-bottom: 10px; padding-left: 15px; font-size: .70em;
5349 margin-top: 10px; margin-left: 0px; color: #000000;
5350 background-color: #ccccff; width: 20%; margin-left: 20px; margin-top: 20px; }
5351 .title {
5352 font-family: arial; font-size: 26px; color: #ffffff;
5353 background-color: #999999; width: 105%; margin-left: 0px;
5354 padding-top: 10px; padding-bottom: 10px; padding-left: 15px;}
5355 .hidden {
5356 position: absolute; visibility: hidden; z-index: 200; left: 250px; top: 100px;
5357 font-family: arial; overflow: hidden; width: 600;
5358 padding: 20px; font-size: 10px; background-color: #999999;
5359 layer-background-color:#FFFFFF; }
5360 a,a:active { color: charcoal; font-weight: bold; }
5361 a:visited { color: #666666; font-weight: bold; }
5362 a:hover { color: cc3300; font-weight: bold; }
5363 </style>
5364 <script language="JavaScript" type="text/javascript">
5365 <!--
5366 // POP-UP CAPTIONS...
5367 function lib_bwcheck(){ //Browsercheck (needed)
5368 this.ver=navigator.appVersion
5369 this.agent=navigator.userAgent
5370 this.dom=document.getElementById?1:0
5371 this.opera5=this.agent.indexOf("Opera 5")>-1
5372 this.ie5=(this.ver.indexOf("MSIE 5")>-1 && this.dom && !this.opera5)?1:0;
5373 this.ie6=(this.ver.indexOf("MSIE 6")>-1 && this.dom && !this.opera5)?1:0;
5374 this.ie4=(document.all && !this.dom && !this.opera5)?1:0;
5375 this.ie=this.ie4||this.ie5||this.ie6
5376 this.mac=this.agent.indexOf("Mac")>-1
5377 this.ns6=(this.dom && parseInt(this.ver) >= 5) ?1:0;
5378 this.ns4=(document.layers && !this.dom)?1:0;
5379 this.bw=(this.ie6 || this.ie5 || this.ie4 || this.ns4 || this.ns6 || this.opera5)
5380 return this
5381 }
5382 var bw = new lib_bwcheck()
5383 //Makes crossbrowser object.
5384 function makeObj(obj){
5385 this.evnt=bw.dom? document.getElementById(obj):bw.ie4?document.all[obj]:bw.ns4?document.layers[obj]:0;
5386 if(!this.evnt) return false
5387 this.css=bw.dom||bw.ie4?this.evnt.style:bw.ns4?this.evnt:0;
5388 this.wref=bw.dom||bw.ie4?this.evnt:bw.ns4?this.css.document:0;
5389 this.writeIt=b_writeIt;
5390 return this
5391 }
5392 // A unit of measure that will be added when setting the position of a layer.
5393 //var px = bw.ns4||window.opera?"":"px";
5394 function b_writeIt(text){
5395 if (bw.ns4){this.wref.write(text);this.wref.close()}
5396 else this.wref.innerHTML = text
5397 }
5398 //Shows the messages
5399 var oDesc;
5400 function popup(divid){
5401 if(oDesc = new makeObj(divid)){
5402 oDesc.css.visibility = "visible"
5403 }
5404 }
5405 function popout(){ // Hides message
5406 if(oDesc) oDesc.css.visibility = "hidden"
5407 }
5408 //-->
5409 </script>
5410 </head>
5411 <body>
5412 <div class=content>
5413 <br><br>
5414 <div class=title>' . $this->serviceName . '</div>
5415 <div class=nav>
5416 <p>View the <a href="' . $PHP_SELF . '?wsdl">WSDL</a> for the service.
5417 Click on an operation name to view it&apos;s details.</p>
5418 <ul>';
5419 foreach ($this->getOperations() as $op => $data) {
5420 // begin-patch: https://mantis.ilias.de/view.php?id=28866
5421 if (isset($data['endpoint'])) {
5422 $data['endpoint'] = htmlspecialchars($data['endpoint'], ENT_QUOTES | ENT_HTML5, 'UTF-8');
5423 }
5424 // end-patch
5425 $b .= "<li><a href='#' onclick=\"popout();popup('$op')\">$op</a></li>";
5426 // create hidden div
5427 $b .= "<div id='$op' class='hidden'>
5428 <a href='#' onclick='popout()'><font color='#ffffff'>Close</font></a><br><br>";
5429 foreach ($data as $donnie => $marie) { // loop through opdata
5430 if ($donnie == 'input' || $donnie == 'output') { // show input/output data
5431 $b .= "<font color='white'>" . ucfirst($donnie) . ':</font><br>';
5432 foreach ($marie as $captain => $tenille) { // loop through data
5433 if ($captain == 'parts') { // loop thru parts
5434 $b .= "&nbsp;&nbsp;$captain:<br>";
5435 //if(is_array($tenille)){
5436 foreach ($tenille as $joanie => $chachi) {
5437 $b .= "&nbsp;&nbsp;&nbsp;&nbsp;$joanie: $chachi<br>";
5438 }
5439 //}
5440 } else {
5441 $b .= "&nbsp;&nbsp;$captain: $tenille<br>";
5442 }
5443 }
5444 } else {
5445 $b .= "<font color='white'>" . ucfirst($donnie) . ":</font> $marie<br>";
5446 }
5447 }
5448 $b .= '</div>';
5449 }
5450 $b .= '
5451 <ul>
5452 </div>
5453 </div></body></html>';
5454 return $b;
5455 }
5456
5464 public function serialize($debug = 0)
5465 {
5466 $xml = '<?xml version="1.0" encoding="ISO-8859-1"?>';
5467 $xml .= "\n<definitions";
5468 foreach ($this->namespaces as $k => $v) {
5469 $xml .= " xmlns:$k=\"$v\"";
5470 }
5471 // 10.9.02 - add poulter fix for wsdl and tns declarations
5472 if (isset($this->namespaces['wsdl'])) {
5473 $xml .= " xmlns=\"" . $this->namespaces['wsdl'] . "\"";
5474 }
5475 if (isset($this->namespaces['tns'])) {
5476 $xml .= " targetNamespace=\"" . $this->namespaces['tns'] . "\"";
5477 }
5478 $xml .= '>';
5479 // imports
5480 if (sizeof($this->import) > 0) {
5481 foreach ($this->import as $ns => $list) {
5482 foreach ($list as $ii) {
5483 if ($ii['location'] != '') {
5484 $xml .= '<import location="' . $ii['location'] . '" namespace="' . $ns . '" />';
5485 } else {
5486 $xml .= '<import namespace="' . $ns . '" />';
5487 }
5488 }
5489 }
5490 }
5491 // types
5492 if (count($this->schemas) >= 1) {
5493 $xml .= "\n<types>\n";
5494 foreach ($this->schemas as $ns => $list) {
5495 foreach ($list as $xs) {
5496 $xml .= $xs->serializeSchema();
5497 }
5498 }
5499 $xml .= '</types>';
5500 }
5501 // messages
5502 if (count($this->messages) >= 1) {
5503 foreach ($this->messages as $msgName => $msgParts) {
5504 $xml .= "\n<message name=\"" . $msgName . '">';
5505 if (is_array($msgParts)) {
5506 foreach ($msgParts as $partName => $partType) {
5507 // print 'serializing '.$partType.', sv: '.$this->XMLSchemaVersion.'<br>';
5508 if (strpos($partType, ':')) {
5509 $typePrefix = $this->getPrefixFromNamespace($this->getPrefix($partType));
5510 } elseif (isset($this->typemap[$this->namespaces['xsd']][$partType])) {
5511 // print 'checking typemap: '.$this->XMLSchemaVersion.'<br>';
5512 $typePrefix = 'xsd';
5513 } else {
5514 foreach ($this->typemap as $ns => $types) {
5515 if (isset($types[$partType])) {
5516 $typePrefix = $this->getPrefixFromNamespace($ns);
5517 }
5518 }
5519 if (!isset($typePrefix)) {
5520 die("$partType has no namespace!");
5521 }
5522 }
5523 $ns = $this->getNamespaceFromPrefix($typePrefix);
5524 $localPart = $this->getLocalPart($partType);
5525 $typeDef = $this->getTypeDef($localPart, $ns);
5526 if (($typeDef['typeClass'] ?? '') == 'element') {
5527 $elementortype = 'element';
5528 if (substr($localPart, -1) == '^') {
5529 $localPart = substr($localPart, 0, -1);
5530 }
5531 } else {
5532 $elementortype = 'type';
5533 }
5534 $xml .= "\n" . ' <part name="' . $partName . '" ' . $elementortype . '="' . $typePrefix . ':' . $localPart . '" />';
5535 }
5536 }
5537 $xml .= '</message>';
5538 }
5539 }
5540 // bindings & porttypes
5541 if (count($this->bindings) >= 1) {
5542 $binding_xml = '';
5543 $portType_xml = '';
5544 foreach ($this->bindings as $bindingName => $attrs) {
5545 $binding_xml .= "\n<binding name=\"" . $bindingName . '" type="tns:' . $attrs['portType'] . '">';
5546 $binding_xml .= "\n" . ' <soap:binding style="' . $attrs['style'] . '" transport="' . $attrs['transport'] . '"/>';
5547 $portType_xml .= "\n<portType name=\"" . $attrs['portType'] . '">';
5548 foreach ($attrs['operations'] as $opName => $opParts) {
5549 $binding_xml .= "\n" . ' <operation name="' . $opName . '">';
5550 $binding_xml .= "\n" . ' <soap:operation soapAction="' . $opParts['soapAction'] . '" style="' . $opParts['style'] . '"/>';
5551 if (isset($opParts['input']['encodingStyle']) && $opParts['input']['encodingStyle'] != '') {
5552 $enc_style = ' encodingStyle="' . $opParts['input']['encodingStyle'] . '"';
5553 } else {
5554 $enc_style = '';
5555 }
5556 $binding_xml .= "\n" . ' <input><soap:body use="' . $opParts['input']['use'] . '" namespace="' . $opParts['input']['namespace'] . '"' . $enc_style . '/></input>';
5557 if (isset($opParts['output']['encodingStyle']) && $opParts['output']['encodingStyle'] != '') {
5558 $enc_style = ' encodingStyle="' . $opParts['output']['encodingStyle'] . '"';
5559 } else {
5560 $enc_style = '';
5561 }
5562 $binding_xml .= "\n" . ' <output><soap:body use="' . $opParts['output']['use'] . '" namespace="' . $opParts['output']['namespace'] . '"' . $enc_style . '/></output>';
5563 $binding_xml .= "\n" . ' </operation>';
5564 $portType_xml .= "\n" . ' <operation name="' . $opParts['name'] . '"';
5565 if (isset($opParts['parameterOrder'])) {
5566 $portType_xml .= ' parameterOrder="' . $opParts['parameterOrder'] . '"';
5567 }
5568 $portType_xml .= '>';
5569 if (isset($opParts['documentation']) && $opParts['documentation'] != '') {
5570 $portType_xml .= "\n" . ' <documentation>' . htmlspecialchars($opParts['documentation']) . '</documentation>';
5571 }
5572 $portType_xml .= "\n" . ' <input message="tns:' . $opParts['input']['message'] . '"/>';
5573 $portType_xml .= "\n" . ' <output message="tns:' . $opParts['output']['message'] . '"/>';
5574 $portType_xml .= "\n" . ' </operation>';
5575 }
5576 $portType_xml .= "\n" . '</portType>';
5577 $binding_xml .= "\n" . '</binding>';
5578 }
5579 $xml .= $portType_xml . $binding_xml;
5580 }
5581 // services
5582 $xml .= "\n<service name=\"" . $this->serviceName . '">';
5583 $has_client = isset($_GET['client_id']);
5584 if (count($this->ports) >= 1) {
5585 foreach ($this->ports as $pName => $attrs) {
5586 $xml .= "\n" . ' <port name="' . $pName . '" binding="tns:' . $attrs['binding'] . '">';
5587 $locations = $attrs['location'];
5588 $locations = is_array($locations) ? $locations : [$locations];
5589 foreach ($locations as $location) {
5590 $address = $location . ($debug || $has_client ? "?" : "")
5591 . ($debug ? 'debug=1' : '') . ($debug && $has_client ? "&amp;" : "")
5592 . ($has_client ? 'client_id=' . $_GET['client_id'] : '');
5593 $xml .= "\n" . ' <soap:address location="' . $address . '"/>';
5594 }
5595 $xml .= "\n" . ' </port>';
5596 }
5597 }
5598
5599 $xml .= "\n" . '</service>';
5600 return $xml . "\n</definitions>";
5601 }
5602
5612 public function parametersMatchWrapped($type, &$parameters)
5613 {
5614 $this->debug("in parametersMatchWrapped type=$type, parameters=");
5615 $this->appendDebug($this->varDump($parameters));
5616
5617 // split type into namespace:unqualified-type
5618 if (strpos($type, ':')) {
5619 $uqType = substr($type, strrpos($type, ':') + 1);
5620 $ns = substr($type, 0, strrpos($type, ':'));
5621 $this->debug("in parametersMatchWrapped: got a prefixed type: $uqType, $ns");
5622 if ($this->getNamespaceFromPrefix($ns)) {
5623 $ns = $this->getNamespaceFromPrefix($ns);
5624 $this->debug("in parametersMatchWrapped: expanded prefixed type: $uqType, $ns");
5625 }
5626 } else {
5627 // TODO: should the type be compared to types in XSD, and the namespace
5628 // set to XSD if the type matches?
5629 $this->debug("in parametersMatchWrapped: No namespace for type $type");
5630 $ns = '';
5631 $uqType = $type;
5632 }
5633
5634 // get the type information
5635 if (!$typeDef = $this->getTypeDef($uqType, $ns)) {
5636 $this->debug("in parametersMatchWrapped: $type ($uqType) is not a supported type.");
5637 return false;
5638 }
5639 $this->debug("in parametersMatchWrapped: found typeDef=");
5640 $this->appendDebug($this->varDump($typeDef));
5641 if (substr($uqType, -1) == '^') {
5642 $uqType = substr($uqType, 0, -1);
5643 }
5644 $phpType = $typeDef['phpType'];
5645 $arrayType = (isset($typeDef['arrayType']) ? $typeDef['arrayType'] : '');
5646 $this->debug("in parametersMatchWrapped: uqType: $uqType, ns: $ns, phptype: $phpType, arrayType: $arrayType");
5647
5648 // we expect a complexType or element of complexType
5649 if ($phpType != 'struct') {
5650 $this->debug("in parametersMatchWrapped: not a struct");
5651 return false;
5652 }
5653
5654 // see whether the parameter names match the elements
5655 if (isset($typeDef['elements']) && is_array($typeDef['elements'])) {
5656 $elements = 0;
5657 $matches = 0;
5658 $change = false;
5659 if ($this->isArraySimpleOrStruct($parameters) == 'arraySimple' && count($parameters) == count($typeDef['elements'])) {
5660 $this->debug("in parametersMatchWrapped: (wrapped return value kludge) correct number of elements in simple array, so change array and wrap");
5661 $change = true;
5662 }
5663 foreach ($typeDef['elements'] as $name => $attrs) {
5664 if ($change) {
5665 $this->debug("in parametersMatchWrapped: change parameter $element to name $name");
5666 $parameters[$name] = $parameters[$elements];
5667 unset($parameters[$elements]);
5668 $matches++;
5669 } elseif (isset($parameters[$name])) {
5670 $this->debug("in parametersMatchWrapped: have parameter named $name");
5671 $matches++;
5672 } else {
5673 $this->debug("in parametersMatchWrapped: do not have parameter named $name");
5674 }
5675 $elements++;
5676 }
5677
5678 $this->debug("in parametersMatchWrapped: $matches parameter names match $elements wrapped parameter names");
5679 if ($matches == 0) {
5680 return false;
5681 }
5682 return true;
5683 }
5684
5685 // since there are no elements for the type, if the user passed no
5686 // parameters, the parameters match wrapped.
5687 $this->debug("in parametersMatchWrapped: no elements type $ns:$uqType");
5688 return count($parameters) == 0;
5689 }
5690
5706 public function serializeRPCParameters($operation, $direction, $parameters, $bindingType = 'soap')
5707 {
5708 $this->debug("in serializeRPCParameters: operation=$operation, direction=$direction, XMLSchemaVersion=$this->XMLSchemaVersion, bindingType=$bindingType");
5709 $this->appendDebug('parameters=' . $this->varDump($parameters));
5710
5711 if ($direction != 'input' && $direction != 'output') {
5712 $this->debug('The value of the \$direction argument needs to be either "input" or "output"');
5713 $this->setError('The value of the \$direction argument needs to be either "input" or "output"');
5714 return false;
5715 }
5716 if (!$opData = $this->getOperationData($operation, $bindingType)) {
5717 $this->debug('Unable to retrieve WSDL data for operation: ' . $operation . ' bindingType: ' . $bindingType);
5718 $this->setError('Unable to retrieve WSDL data for operation: ' . $operation . ' bindingType: ' . $bindingType);
5719 return false;
5720 }
5721 $this->debug('in serializeRPCParameters: opData:');
5722 $this->appendDebug($this->varDump($opData));
5723
5724 // Get encoding style for output and set to current
5725 $encodingStyle = 'http://schemas.xmlsoap.org/soap/encoding/';
5726 if (($direction == 'input') && isset($opData['output']['encodingStyle']) && ($opData['output']['encodingStyle'] != $encodingStyle)) {
5727 $encodingStyle = $opData['output']['encodingStyle'];
5728 $enc_style = $encodingStyle;
5729 }
5730
5731 // set input params
5732 $xml = '';
5733 if (isset($opData[$direction]['parts']) && sizeof($opData[$direction]['parts']) > 0) {
5734 $parts = &$opData[$direction]['parts'];
5735 $part_count = sizeof($parts);
5736 $style = $opData['style'];
5737 $use = $opData[$direction]['use'];
5738 $this->debug("have $part_count part(s) to serialize using $style/$use");
5739 if (is_array($parameters)) {
5740 $parametersArrayType = $this->isArraySimpleOrStruct($parameters);
5741 $parameter_count = count($parameters);
5742 $this->debug("have $parameter_count parameter(s) provided as $parametersArrayType to serialize");
5743 // check for Microsoft-style wrapped parameters
5744 if ($style == 'document' && $use == 'literal' && $part_count == 1 && isset($parts['parameters'])) {
5745 $this->debug('check whether the caller has wrapped the parameters');
5746 if ((($parametersArrayType == 'arrayStruct' || $parameter_count == 0) && !isset($parameters['parameters'])) || ($direction == 'output' && $parametersArrayType == 'arraySimple' && $parameter_count == 1)) {
5747 $this->debug('check whether caller\'s parameters match the wrapped ones');
5748 if ($this->parametersMatchWrapped($parts['parameters'], $parameters)) {
5749 $this->debug('wrap the parameters for the caller');
5750 $parameters = array('parameters' => $parameters);
5751 $parameter_count = 1;
5752 }
5753 }
5754 }
5755 foreach ($parts as $name => $type) {
5756 $this->debug("serializing part $name of type $type");
5757 // Track encoding style
5758 if (isset($opData[$direction]['encodingStyle']) && $encodingStyle != $opData[$direction]['encodingStyle']) {
5759 $encodingStyle = $opData[$direction]['encodingStyle'];
5760 $enc_style = $encodingStyle;
5761 } else {
5762 $enc_style = false;
5763 }
5764 // NOTE: add error handling here
5765 // if serializeType returns false, then catch global error and fault
5766 if ($parametersArrayType == 'arraySimple') {
5767 $p = array_shift($parameters);
5768 $this->debug('calling serializeType w/indexed param');
5769 $xml .= $this->serializeType($name, $type, $p, $use, $enc_style);
5770 } elseif (isset($parameters[$name])) {
5771 $this->debug('calling serializeType w/named param');
5772 $xml .= $this->serializeType($name, $type, $parameters[$name], $use, $enc_style);
5773 } else {
5774 // TODO: only send nillable
5775 $this->debug('calling serializeType w/null param');
5776 $xml .= $this->serializeType($name, $type, null, $use, $enc_style);
5777 }
5778 }
5779 } else {
5780 $this->debug('no parameters passed.');
5781 }
5782 }
5783 $this->debug("serializeRPCParameters returning: $xml");
5784 return $xml;
5785 }
5786
5801 public function serializeParameters($operation, $direction, $parameters)
5802 {
5803 $this->debug("in serializeParameters: operation=$operation, direction=$direction, XMLSchemaVersion=$this->XMLSchemaVersion");
5804 $this->appendDebug('parameters=' . $this->varDump($parameters));
5805
5806 if ($direction != 'input' && $direction != 'output') {
5807 $this->debug('The value of the \$direction argument needs to be either "input" or "output"');
5808 $this->setError('The value of the \$direction argument needs to be either "input" or "output"');
5809 return false;
5810 }
5811 if (!$opData = $this->getOperationData($operation)) {
5812 $this->debug('Unable to retrieve WSDL data for operation: ' . $operation);
5813 $this->setError('Unable to retrieve WSDL data for operation: ' . $operation);
5814 return false;
5815 }
5816 $this->debug('opData:');
5817 $this->appendDebug($this->varDump($opData));
5818
5819 // Get encoding style for output and set to current
5820 $encodingStyle = 'http://schemas.xmlsoap.org/soap/encoding/';
5821 if (($direction == 'input') && isset($opData['output']['encodingStyle']) && ($opData['output']['encodingStyle'] != $encodingStyle)) {
5822 $encodingStyle = $opData['output']['encodingStyle'];
5823 $enc_style = $encodingStyle;
5824 }
5825
5826 // set input params
5827 $xml = '';
5828 if (isset($opData[$direction]['parts']) && sizeof($opData[$direction]['parts']) > 0) {
5829 $use = $opData[$direction]['use'];
5830 $this->debug("use=$use");
5831 $this->debug('got ' . count($opData[$direction]['parts']) . ' part(s)');
5832 if (is_array($parameters)) {
5833 $parametersArrayType = $this->isArraySimpleOrStruct($parameters);
5834 $this->debug('have ' . $parametersArrayType . ' parameters');
5835 foreach ($opData[$direction]['parts'] as $name => $type) {
5836 $this->debug('serializing part "' . $name . '" of type "' . $type . '"');
5837 // Track encoding style
5838 if (isset($opData[$direction]['encodingStyle']) && $encodingStyle != $opData[$direction]['encodingStyle']) {
5839 $encodingStyle = $opData[$direction]['encodingStyle'];
5840 $enc_style = $encodingStyle;
5841 } else {
5842 $enc_style = false;
5843 }
5844 // NOTE: add error handling here
5845 // if serializeType returns false, then catch global error and fault
5846 if ($parametersArrayType == 'arraySimple') {
5847 $p = array_shift($parameters);
5848 $this->debug('calling serializeType w/indexed param');
5849 $xml .= $this->serializeType($name, $type, $p, $use, $enc_style);
5850 } elseif (isset($parameters[$name])) {
5851 $this->debug('calling serializeType w/named param');
5852 $xml .= $this->serializeType($name, $type, $parameters[$name], $use, $enc_style);
5853 } else {
5854 // TODO: only send nillable
5855 $this->debug('calling serializeType w/null param');
5856 $xml .= $this->serializeType($name, $type, null, $use, $enc_style);
5857 }
5858 }
5859 } else {
5860 $this->debug('no parameters passed.');
5861 }
5862 }
5863 $this->debug("serializeParameters returning: $xml");
5864 return $xml;
5865 }
5866
5879 public function serializeType($name, $type, $value, $use = 'encoded', $encodingStyle = false, $unqualified = false)
5880 {
5881 $this->debug("in serializeType: name=$name, type=$type, use=$use, encodingStyle=$encodingStyle, unqualified=" . ($unqualified ? "unqualified" : "qualified"));
5882 $this->appendDebug("value=" . $this->varDump($value));
5883 if ($use == 'encoded' && $encodingStyle) {
5884 $encodingStyle = ' SOAP-ENV:encodingStyle="' . $encodingStyle . '"';
5885 }
5886
5887 // if a soapval has been supplied, let its type override the WSDL
5888 if (is_object($value) && get_class($value) == 'soapval') {
5889 if ($value->type_ns) {
5890 $type = $value->type_ns . ':' . $value->type;
5891 $forceType = true;
5892 $this->debug("in serializeType: soapval overrides type to $type");
5893 } elseif ($value->type) {
5894 $type = $value->type;
5895 $forceType = true;
5896 $this->debug("in serializeType: soapval overrides type to $type");
5897 } else {
5898 $forceType = false;
5899 $this->debug("in serializeType: soapval does not override type");
5900 }
5901 $attrs = $value->attributes;
5902 $value = $value->value;
5903 $this->debug("in serializeType: soapval overrides value to $value");
5904 if ($attrs) {
5905 if (!is_array($value)) {
5906 $value['!'] = $value;
5907 }
5908 foreach ($attrs as $n => $v) {
5909 $value['!' . $n] = $v;
5910 }
5911 $this->debug("in serializeType: soapval provides attributes");
5912 }
5913 } else {
5914 $forceType = false;
5915 }
5916
5917 $xml = '';
5918 if (strpos($type, ':')) {
5919 $uqType = substr($type, strrpos($type, ':') + 1);
5920 $ns = substr($type, 0, strrpos($type, ':'));
5921 $this->debug("in serializeType: got a prefixed type: $uqType, $ns");
5922 if ($this->getNamespaceFromPrefix($ns)) {
5923 $ns = $this->getNamespaceFromPrefix($ns);
5924 $this->debug("in serializeType: expanded prefixed type: $uqType, $ns");
5925 }
5926
5927 if ($ns == $this->XMLSchemaVersion || $ns == 'http://schemas.xmlsoap.org/soap/encoding/') {
5928 $this->debug('in serializeType: type namespace indicates XML Schema or SOAP Encoding type');
5929 if ($unqualified && $use == 'literal') {
5930 $elementNS = " xmlns=\"\"";
5931 } else {
5932 $elementNS = '';
5933 }
5934 if (is_null($value)) {
5935 if ($use == 'literal') {
5936 // TODO: depends on minOccurs
5937 $xml = "<$name$elementNS/>";
5938 } else {
5939 // TODO: depends on nillable, which should be checked before calling this method
5940 $xml = "<$name$elementNS xsi:nil=\"true\" xsi:type=\"" . $this->getPrefixFromNamespace($ns) . ":$uqType\"/>";
5941 }
5942 $this->debug("in serializeType: returning: $xml");
5943 return $xml;
5944 }
5945 if ($uqType == 'Array') {
5946 // JBoss/Axis does this sometimes
5947 return $this->serialize_val($value, $name, false, false, false, false, $use);
5948 }
5949 if ($uqType == 'boolean') {
5950 if ((is_string($value) && $value == 'false') || (! $value)) {
5951 $value = 'false';
5952 } else {
5953 $value = 'true';
5954 }
5955 }
5956 if ($uqType == 'string' && gettype($value) == 'string') {
5957 $value = $this->expandEntities($value);
5958 }
5959 if (($uqType == 'long' || $uqType == 'unsignedLong') && gettype($value) == 'double') {
5960 $value = sprintf("%.0lf", $value);
5961 }
5962 // it's a scalar
5963 // TODO: what about null/nil values?
5964 // check type isn't a custom type extending xmlschema namespace
5965 if (!$this->getTypeDef($uqType, $ns)) {
5966 if ($use == 'literal') {
5967 if ($forceType) {
5968 $xml = "<$name$elementNS xsi:type=\"" . $this->getPrefixFromNamespace($ns) . ":$uqType\">$value</$name>";
5969 } else {
5970 $xml = "<$name$elementNS>$value</$name>";
5971 }
5972 } else {
5973 $xml = "<$name$elementNS xsi:type=\"" . $this->getPrefixFromNamespace($ns) . ":$uqType\"$encodingStyle>$value</$name>";
5974 }
5975 $this->debug("in serializeType: returning: $xml");
5976 return $xml;
5977 }
5978 $this->debug('custom type extends XML Schema or SOAP Encoding namespace (yuck)');
5979 } elseif ($ns == 'http://xml.apache.org/xml-soap') {
5980 $this->debug('in serializeType: appears to be Apache SOAP type');
5981 if ($uqType == 'Map') {
5982 $tt_prefix = $this->getPrefixFromNamespace('http://xml.apache.org/xml-soap');
5983 if (! $tt_prefix) {
5984 $this->debug('in serializeType: Add namespace for Apache SOAP type');
5985 $tt_prefix = 'ns' . rand(1000, 9999);
5986 $this->namespaces[$tt_prefix] = 'http://xml.apache.org/xml-soap';
5987 // force this to be added to usedNamespaces
5988 $tt_prefix = $this->getPrefixFromNamespace('http://xml.apache.org/xml-soap');
5989 }
5990 $contents = '';
5991 foreach ($value as $k => $v) {
5992 $this->debug("serializing map element: key $k, value $v");
5993 $contents .= '<item>';
5994 $contents .= $this->serialize_val($k, 'key', false, false, false, false, $use);
5995 $contents .= $this->serialize_val($v, 'value', false, false, false, false, $use);
5996 $contents .= '</item>';
5997 }
5998 if ($use == 'literal') {
5999 if ($forceType) {
6000 $xml = "<$name xsi:type=\"" . $tt_prefix . ":$uqType\">$contents</$name>";
6001 } else {
6002 $xml = "<$name>$contents</$name>";
6003 }
6004 } else {
6005 $xml = "<$name xsi:type=\"" . $tt_prefix . ":$uqType\"$encodingStyle>$contents</$name>";
6006 }
6007 $this->debug("in serializeType: returning: $xml");
6008 return $xml;
6009 }
6010 $this->debug('in serializeType: Apache SOAP type, but only support Map');
6011 }
6012 } else {
6013 // TODO: should the type be compared to types in XSD, and the namespace
6014 // set to XSD if the type matches?
6015 $this->debug("in serializeType: No namespace for type $type");
6016 $ns = '';
6017 $uqType = $type;
6018 }
6019 if (!$typeDef = $this->getTypeDef($uqType, $ns)) {
6020 $this->setError("$type ($uqType) is not a supported type.");
6021 $this->debug("in serializeType: $type ($uqType) is not a supported type.");
6022 return false;
6023 } else {
6024 $this->debug("in serializeType: found typeDef");
6025 $this->appendDebug('typeDef=' . $this->varDump($typeDef));
6026 if (substr($uqType, -1) == '^') {
6027 $uqType = substr($uqType, 0, -1);
6028 }
6029 }
6030 $phpType = $typeDef['phpType'];
6031 $this->debug("in serializeType: uqType: $uqType, ns: $ns, phptype: $phpType, arrayType: " . (isset($typeDef['arrayType']) ? $typeDef['arrayType'] : ''));
6032 // if php type == struct, map value to the <all> element names
6033 if ($phpType == 'struct') {
6034 if (isset($typeDef['typeClass']) && $typeDef['typeClass'] == 'element') {
6035 $elementName = $uqType;
6036 if (isset($typeDef['form']) && ($typeDef['form'] == 'qualified')) {
6037 $elementNS = " xmlns=\"$ns\"";
6038 } else {
6039 $elementNS = " xmlns=\"\"";
6040 }
6041 } else {
6042 $elementName = $name;
6043 if ($unqualified) {
6044 $elementNS = " xmlns=\"\"";
6045 } else {
6046 $elementNS = '';
6047 }
6048 }
6049 if (is_null($value)) {
6050 if ($use == 'literal') {
6051 // TODO: depends on minOccurs
6052 $xml = "<$elementName$elementNS/>";
6053 } else {
6054 $xml = "<$elementName$elementNS xsi:nil=\"true\" xsi:type=\"" . $this->getPrefixFromNamespace($ns) . ":$uqType\"/>";
6055 }
6056 $this->debug("in serializeType: returning: $xml");
6057 return $xml;
6058 }
6059 if (is_object($value)) {
6060 $value = get_object_vars($value);
6061 }
6062 if (is_array($value)) {
6063 $elementAttrs = $this->serializeComplexTypeAttributes($typeDef, $value, $ns, $uqType);
6064 if ($use == 'literal') {
6065 if ($forceType) {
6066 $xml = "<$elementName$elementNS$elementAttrs xsi:type=\"" . $this->getPrefixFromNamespace($ns) . ":$uqType\">";
6067 } else {
6068 $xml = "<$elementName$elementNS$elementAttrs>";
6069 }
6070 } else {
6071 $xml = "<$elementName$elementNS$elementAttrs xsi:type=\"" . $this->getPrefixFromNamespace($ns) . ":$uqType\"$encodingStyle>";
6072 }
6073
6074 $xml .= $this->serializeComplexTypeElements($typeDef, $value, $ns, $uqType, $use, $encodingStyle);
6075 $xml .= "</$elementName>";
6076 } else {
6077 $this->debug("in serializeType: phpType is struct, but value is not an array");
6078 $this->setError("phpType is struct, but value is not an array: see debug output for details");
6079 $xml = '';
6080 }
6081 } elseif ($phpType == 'array') {
6082 if (isset($typeDef['form']) && ($typeDef['form'] == 'qualified')) {
6083 $elementNS = " xmlns=\"$ns\"";
6084 } else {
6085 if ($unqualified) {
6086 $elementNS = " xmlns=\"\"";
6087 } else {
6088 $elementNS = '';
6089 }
6090 }
6091 if (is_null($value)) {
6092 if ($use == 'literal') {
6093 // TODO: depends on minOccurs
6094 $xml = "<$name$elementNS/>";
6095 } else {
6096 $xml = "<$name$elementNS xsi:nil=\"true\" xsi:type=\"" .
6097 $this->getPrefixFromNamespace('http://schemas.xmlsoap.org/soap/encoding/') .
6098 ":Array\" " .
6099 $this->getPrefixFromNamespace('http://schemas.xmlsoap.org/soap/encoding/') .
6100 ':arrayType="' .
6101 $this->getPrefixFromNamespace($this->getPrefix($typeDef['arrayType'])) .
6102 ':' .
6103 $this->getLocalPart($typeDef['arrayType']) . "[0]\"/>";
6104 }
6105 $this->debug("in serializeType: returning: $xml");
6106 return $xml;
6107 }
6108 if (isset($typeDef['multidimensional'])) {
6109 $nv = array();
6110 foreach ($value as $v) {
6111 $cols = ',' . sizeof($v);
6112 $nv = array_merge($nv, $v);
6113 }
6114 $value = $nv;
6115 } else {
6116 $cols = '';
6117 }
6118 if (is_array($value) && sizeof($value) >= 1) {
6119 $rows = sizeof($value);
6120 $contents = '';
6121 foreach ($value as $k => $v) {
6122 $this->debug("serializing array element: $k, $v of type: $typeDef[arrayType]");
6123 //if (strpos($typeDef['arrayType'], ':') ) {
6124 if (!in_array($typeDef['arrayType'], $this->typemap['http://www.w3.org/2001/XMLSchema'])) {
6125 $contents .= $this->serializeType('item', $typeDef['arrayType'], $v, $use);
6126 } else {
6127 $contents .= $this->serialize_val($v, 'item', $typeDef['arrayType'], null, $this->XMLSchemaVersion, false, $use);
6128 }
6129 }
6130 } else {
6131 $rows = 0;
6132 $contents = null;
6133 }
6134 // TODO: for now, an empty value will be serialized as a zero element
6135 // array. Revisit this when coding the handling of null/nil values.
6136 if ($use == 'literal') {
6137 $xml = "<$name$elementNS>"
6138 . $contents
6139 . "</$name>";
6140 } else {
6141 $xml = "<$name$elementNS xsi:type=\"" . $this->getPrefixFromNamespace('http://schemas.xmlsoap.org/soap/encoding/') . ':Array" ' .
6142 $this->getPrefixFromNamespace('http://schemas.xmlsoap.org/soap/encoding/')
6143 . ':arrayType="'
6144 . $this->getPrefixFromNamespace($this->getPrefix($typeDef['arrayType']))
6145 . ":" . $this->getLocalPart($typeDef['arrayType']) . "[$rows$cols]\">"
6146 . $contents
6147 . "</$name>";
6148 }
6149 } elseif ($phpType == 'scalar') {
6150 if (isset($typeDef['form']) && ($typeDef['form'] == 'qualified')) {
6151 $elementNS = " xmlns=\"$ns\"";
6152 } else {
6153 if ($unqualified) {
6154 $elementNS = " xmlns=\"\"";
6155 } else {
6156 $elementNS = '';
6157 }
6158 }
6159 if ($use == 'literal') {
6160 if ($forceType) {
6161 $xml = "<$name$elementNS xsi:type=\"" . $this->getPrefixFromNamespace($ns) . ":$uqType\">$value</$name>";
6162 } else {
6163 $xml = "<$name$elementNS>$value</$name>";
6164 }
6165 } else {
6166 $xml = "<$name$elementNS xsi:type=\"" . $this->getPrefixFromNamespace($ns) . ":$uqType\"$encodingStyle>$value</$name>";
6167 }
6168 }
6169 $this->debug("in serializeType: returning: $xml");
6170 return $xml;
6171 }
6172
6183 public function serializeComplexTypeAttributes($typeDef, $value, $ns, $uqType)
6184 {
6185 $xml = '';
6186 if (isset($typeDef['attrs']) && is_array($typeDef['attrs'])) {
6187 $this->debug("serialize attributes for XML Schema type $ns:$uqType");
6188 if (is_array($value)) {
6189 $xvalue = $value;
6190 } elseif (is_object($value)) {
6191 $xvalue = get_object_vars($value);
6192 } else {
6193 $this->debug("value is neither an array nor an object for XML Schema type $ns:$uqType");
6194 $xvalue = array();
6195 }
6196 foreach ($typeDef['attrs'] as $aName => $attrs) {
6197 if (isset($xvalue['!' . $aName])) {
6198 $xname = '!' . $aName;
6199 $this->debug("value provided for attribute $aName with key $xname");
6200 } elseif (isset($xvalue[$aName])) {
6201 $xname = $aName;
6202 $this->debug("value provided for attribute $aName with key $xname");
6203 } elseif (isset($attrs['default'])) {
6204 $xname = '!' . $aName;
6205 $xvalue[$xname] = $attrs['default'];
6206 $this->debug('use default value of ' . $xvalue[$aName] . ' for attribute ' . $aName);
6207 } else {
6208 $xname = '';
6209 $this->debug("no value provided for attribute $aName");
6210 }
6211 if ($xname) {
6212 $xml .= " $aName=\"" . $this->expandEntities($xvalue[$xname]) . "\"";
6213 }
6214 }
6215 } else {
6216 $this->debug("no attributes to serialize for XML Schema type $ns:$uqType");
6217 }
6218 if (isset($typeDef['extensionBase'])) {
6219 $ns = $this->getPrefix($typeDef['extensionBase']);
6220 $uqType = $this->getLocalPart($typeDef['extensionBase']);
6221 if ($this->getNamespaceFromPrefix($ns)) {
6222 $ns = $this->getNamespaceFromPrefix($ns);
6223 }
6224 if ($typeDef = $this->getTypeDef($uqType, $ns)) {
6225 $this->debug("serialize attributes for extension base $ns:$uqType");
6226 $xml .= $this->serializeComplexTypeAttributes($typeDef, $value, $ns, $uqType);
6227 } else {
6228 $this->debug("extension base $ns:$uqType is not a supported type");
6229 }
6230 }
6231 return $xml;
6232 }
6233
6246 public function serializeComplexTypeElements($typeDef, $value, $ns, $uqType, $use = 'encoded', $encodingStyle = false)
6247 {
6248 $xml = '';
6249 if (isset($typeDef['elements']) && is_array($typeDef['elements'])) {
6250 $this->debug("in serializeComplexTypeElements, serialize elements for XML Schema type $ns:$uqType");
6251 if (is_array($value)) {
6252 $xvalue = $value;
6253 } elseif (is_object($value)) {
6254 $xvalue = get_object_vars($value);
6255 } else {
6256 $this->debug("value is neither an array nor an object for XML Schema type $ns:$uqType");
6257 $xvalue = array();
6258 }
6259 // toggle whether all elements are present - ideally should validate against schema
6260 if (count($typeDef['elements']) != count($xvalue)) {
6261 $optionals = true;
6262 }
6263 foreach ($typeDef['elements'] as $eName => $attrs) {
6264 if (!isset($xvalue[$eName])) {
6265 if (isset($attrs['default'])) {
6266 $xvalue[$eName] = $attrs['default'];
6267 $this->debug('use default value of ' . $xvalue[$eName] . ' for element ' . $eName);
6268 }
6269 }
6270 // if user took advantage of a minOccurs=0, then only serialize named parameters
6271 if (isset($optionals)
6272 && (!isset($xvalue[$eName]))
6273 && ((!isset($attrs['nillable'])) || $attrs['nillable'] != 'true')
6274 ) {
6275 if (isset($attrs['minOccurs']) && $attrs['minOccurs'] <> '0') {
6276 $this->debug("apparent error: no value provided for element $eName with minOccurs=" . $attrs['minOccurs']);
6277 }
6278 // do nothing
6279 $this->debug("no value provided for complexType element $eName and element is not nillable, so serialize nothing");
6280 } else {
6281 // get value
6282 if (isset($xvalue[$eName])) {
6283 $v = $xvalue[$eName];
6284 } else {
6285 $v = null;
6286 }
6287 if (isset($attrs['form'])) {
6288 $unqualified = ($attrs['form'] == 'unqualified');
6289 } else {
6290 $unqualified = false;
6291 }
6292 if (isset($attrs['maxOccurs']) && ($attrs['maxOccurs'] == 'unbounded' || $attrs['maxOccurs'] > 1) && isset($v) && is_array($v) && $this->isArraySimpleOrStruct($v) == 'arraySimple') {
6293 $vv = $v;
6294 foreach ($vv as $k => $v) {
6295 if (isset($attrs['type']) || isset($attrs['ref'])) {
6296 // serialize schema-defined type
6297 $xml .= $this->serializeType($eName, isset($attrs['type']) ? $attrs['type'] : $attrs['ref'], $v, $use, $encodingStyle, $unqualified);
6298 } else {
6299 // serialize generic type (can this ever really happen?)
6300 $this->debug("calling serialize_val() for $v, $eName, false, false, false, false, $use");
6301 $xml .= $this->serialize_val($v, $eName, false, false, false, false, $use);
6302 }
6303 }
6304 } else {
6305 if (isset($attrs['type']) || isset($attrs['ref'])) {
6306 // serialize schema-defined type
6307 $xml .= $this->serializeType($eName, isset($attrs['type']) ? $attrs['type'] : $attrs['ref'], $v, $use, $encodingStyle, $unqualified);
6308 } else {
6309 // serialize generic type (can this ever really happen?)
6310 $this->debug("calling serialize_val() for $v, $eName, false, false, false, false, $use");
6311 $xml .= $this->serialize_val($v, $eName, false, false, false, false, $use);
6312 }
6313 }
6314 }
6315 }
6316 } else {
6317 $this->debug("no elements to serialize for XML Schema type $ns:$uqType");
6318 }
6319 if (isset($typeDef['extensionBase'])) {
6320 $ns = $this->getPrefix($typeDef['extensionBase']);
6321 $uqType = $this->getLocalPart($typeDef['extensionBase']);
6322 if ($this->getNamespaceFromPrefix($ns)) {
6323 $ns = $this->getNamespaceFromPrefix($ns);
6324 }
6325 if ($typeDef = $this->getTypeDef($uqType, $ns)) {
6326 $this->debug("serialize elements for extension base $ns:$uqType");
6327 $xml .= $this->serializeComplexTypeElements($typeDef, $value, $ns, $uqType, $use, $encodingStyle);
6328 } else {
6329 $this->debug("extension base $ns:$uqType is not a supported type");
6330 }
6331 }
6332 return $xml;
6333 }
6334
6349 public function addComplexType($name, $typeClass = 'complexType', $phpType = 'array', $compositor = '', $restrictionBase = '', $elements = array(), $attrs = array(), $arrayType = '')
6350 {
6351 if (count($elements) > 0) {
6352 $eElements = array();
6353 foreach ($elements as $n => $e) {
6354 // expand each element
6355 $ee = array();
6356 foreach ($e as $k => $v) {
6357 $k = strpos($k, ':') ? $this->expandQname($k) : $k;
6358 $v = strpos($v, ':') ? $this->expandQname($v) : $v;
6359 $ee[$k] = $v;
6360 }
6361 $eElements[$n] = $ee;
6362 }
6363 $elements = $eElements;
6364 }
6365
6366 if (count($attrs) > 0) {
6367 foreach ($attrs as $n => $a) {
6368 // expand each attribute
6369 foreach ($a as $k => $v) {
6370 $k = strpos($k, ':') ? $this->expandQname($k) : $k;
6371 $v = strpos($v, ':') ? $this->expandQname($v) : $v;
6372 $aa[$k] = $v;
6373 }
6374 $eAttrs[$n] = $aa;
6375 }
6376 $attrs = $eAttrs;
6377 }
6378
6379 $restrictionBase = strpos($restrictionBase, ':') ? $this->expandQname($restrictionBase) : $restrictionBase;
6380 $arrayType = strpos($arrayType, ':') ? $this->expandQname($arrayType) : $arrayType;
6381
6382 $typens = isset($this->namespaces['types']) ? $this->namespaces['types'] : $this->namespaces['tns'];
6383 $this->schemas[$typens][0]->addComplexType($name, $typeClass, $phpType, $compositor, $restrictionBase, $elements, $attrs, $arrayType);
6384 }
6385
6397 public function addSimpleType($name, $restrictionBase = '', $typeClass = 'simpleType', $phpType = 'scalar', $enumeration = array())
6398 {
6399 $restrictionBase = strpos($restrictionBase, ':') ? $this->expandQname($restrictionBase) : $restrictionBase;
6400
6401 $typens = isset($this->namespaces['types']) ? $this->namespaces['types'] : $this->namespaces['tns'];
6402 $this->schemas[$typens][0]->addSimpleType($name, $restrictionBase, $typeClass, $phpType, $enumeration);
6403 }
6404
6412 public function addElement($attrs)
6413 {
6414 $typens = isset($this->namespaces['types']) ? $this->namespaces['types'] : $this->namespaces['tns'];
6415 $this->schemas[$typens][0]->addElement($attrs);
6416 }
6417
6432 public function addOperation($name, $in = false, $out = false, $namespace = false, $soapaction = false, $style = 'rpc', $use = 'encoded', $documentation = '', $encodingStyle = '')
6433 {
6434 if ($use == 'encoded' && $encodingStyle == '') {
6435 $encodingStyle = 'http://schemas.xmlsoap.org/soap/encoding/';
6436 }
6437
6438 if ($style == 'document') {
6439 $elements = array();
6440 foreach ($in as $n => $t) {
6441 $elements[$n] = array('name' => $n, 'type' => $t);
6442 }
6443 $this->addComplexType($name . 'RequestType', 'complexType', 'struct', 'all', '', $elements);
6444 $this->addElement(array('name' => $name, 'type' => $name . 'RequestType'));
6445 $in = array('parameters' => 'tns:' . $name . '^');
6446
6447 $elements = array();
6448 foreach ($out as $n => $t) {
6449 $elements[$n] = array('name' => $n, 'type' => $t);
6450 }
6451 $this->addComplexType($name . 'ResponseType', 'complexType', 'struct', 'all', '', $elements);
6452 $this->addElement(array('name' => $name . 'Response', 'type' => $name . 'ResponseType', 'form' => 'qualified'));
6453 $out = array('parameters' => 'tns:' . $name . 'Response' . '^');
6454 }
6455
6456 // get binding
6457 $this->bindings[ $this->serviceName . 'Binding' ]['operations'][$name] =
6458 array(
6459 'name' => $name,
6460 'binding' => $this->serviceName . 'Binding',
6461 'endpoint' => $this->endpoint,
6462 'soapAction' => $soapaction,
6463 'style' => $style,
6464 'input' => array(
6465 'use' => $use,
6466 'namespace' => $namespace,
6467 'encodingStyle' => $encodingStyle,
6468 'message' => $name . 'Request',
6469 'parts' => $in),
6470 'output' => array(
6471 'use' => $use,
6472 'namespace' => $namespace,
6473 'encodingStyle' => $encodingStyle,
6474 'message' => $name . 'Response',
6475 'parts' => $out),
6476 'namespace' => $namespace,
6477 'transport' => 'http://schemas.xmlsoap.org/soap/http',
6478 'documentation' => $documentation);
6479 // add portTypes
6480 // add messages
6481 if ($in) {
6482 foreach ($in as $pName => $pType) {
6483 if (strpos($pType, ':')) {
6484 $pType = $this->getNamespaceFromPrefix($this->getPrefix($pType)) . ":" . $this->getLocalPart($pType);
6485 }
6486 $this->messages[$name . 'Request'][$pName] = $pType;
6487 }
6488 } else {
6489 $this->messages[$name . 'Request'] = '0';
6490 }
6491 if ($out) {
6492 foreach ($out as $pName => $pType) {
6493 if (strpos($pType, ':')) {
6494 $pType = $this->getNamespaceFromPrefix($this->getPrefix($pType)) . ":" . $this->getLocalPart($pType);
6495 }
6496 $this->messages[$name . 'Response'][$pName] = $pType;
6497 }
6498 } else {
6499 $this->messages[$name . 'Response'] = '0';
6500 }
6501 return true;
6502 }
6503}
6504?><?php
6505
6506
6507
6518{
6520 public $parser;
6521 public $xml = '';
6522 public $xml_encoding = '';
6523 public $method = '';
6524 public $root_struct = '';
6527 public $root_header = '';
6528 public $document = ''; // incoming SOAP body (text)
6529 // determines where in the message we are (envelope,header,body,method)
6530 public $status = '';
6531 public $position = 0;
6532 public $depth = 0;
6534 public $namespaces = array();
6535 public $message = array();
6536 public $parent = '';
6537 public $fault = false;
6538 public $fault_code = '';
6539 public $fault_str = '';
6540 public $fault_detail = '';
6541 public $depth_array = array();
6542 public $debug_flag = true;
6543 public $soapresponse = null; // parsed SOAP Body
6544 public $soapheader = null; // parsed SOAP Header
6545 public $responseHeaders = ''; // incoming SOAP headers (text)
6546 public $body_position = 0;
6547 // for multiref parsing:
6548 // array of id => pos
6549 public $ids = array();
6550 // array of id => hrefs => pos
6551 public $multirefs = array();
6552 // toggle for auto-decoding element content
6553 public $decode_utf8 = true;
6554
6564 public function __construct($xml, $encoding = 'UTF-8', $method = '', $decode_utf8 = true)
6565 {
6567 $this->xml = $xml;
6568 $this->xml_encoding = $encoding;
6569 $this->method = $method;
6570 $this->decode_utf8 = $decode_utf8;
6571
6572 // Check whether content has been read.
6573 if (!empty($xml)) {
6574 // Check XML encoding
6575 $pos_xml = strpos($xml, '<?xml');
6576 if ($pos_xml !== false) {
6577 $xml_decl = substr($xml, $pos_xml, strpos($xml, '?>', $pos_xml + 2) - $pos_xml + 1);
6578 if (preg_match("/encoding=[\"']([^\"']*)[\"']/", $xml_decl, $res)) {
6579 $xml_encoding = $res[1];
6580 if (strtoupper($xml_encoding) != $encoding) {
6581 $err = "Charset from HTTP Content-Type '" . $encoding . "' does not match encoding from XML declaration '" . $xml_encoding . "'";
6582 $this->debug($err);
6583 if ($encoding != 'ISO-8859-1' || strtoupper($xml_encoding) != 'UTF-8') {
6584 $this->setError($err);
6585 return;
6586 }
6587 // when HTTP says ISO-8859-1 (the default) and XML says UTF-8 (the typical), assume the other endpoint is just sloppy and proceed
6588 } else {
6589 $this->debug('Charset from HTTP Content-Type matches encoding from XML declaration');
6590 }
6591 } else {
6592 $this->debug('No encoding specified in XML declaration');
6593 }
6594 } else {
6595 $this->debug('No XML declaration');
6596 }
6597 $this->debug('Entering nusoap_parser(), length=' . strlen($xml) . ', encoding=' . $encoding);
6598 // Create an XML parser - why not xml_parser_create_ns?
6599 $this->parser = xml_parser_create($this->xml_encoding);
6600 // Set the options for parsing the XML data.
6601 //xml_parser_set_option($parser, XML_OPTION_SKIP_WHITE, 1);
6602 xml_parser_set_option($this->parser, XML_OPTION_CASE_FOLDING, 0);
6603 xml_parser_set_option($this->parser, XML_OPTION_TARGET_ENCODING, $this->xml_encoding);
6604 // Set the object for the parser.
6605 // Set the element handlers for the parser.
6606 xml_set_element_handler($this->parser, $this->start_element(...), $this->end_element(...));
6607 xml_set_character_data_handler($this->parser, $this->character_data(...));
6608
6609 // Parse the XML file.
6610 if (!xml_parse($this->parser, $xml, true)) {
6611 // Display an error message.
6612 $err = sprintf(
6613 'XML error parsing SOAP payload on line %d: %s',
6614 xml_get_current_line_number($this->parser),
6615 xml_error_string(xml_get_error_code($this->parser))
6616 );
6617 $this->debug($err);
6618 $this->debug("XML payload:\n" . $xml);
6619 $this->setError($err);
6620 } else {
6621 $this->debug('parsed successfully, found root struct: ' . $this->root_struct . ' of name ' . $this->root_struct_name);
6622 // get final value
6623 $this->soapresponse = $this->message[$this->root_struct]['result'];
6624 // get header value
6625 if ($this->root_header != '' && isset($this->message[$this->root_header]['result'])) {
6626 $this->soapheader = $this->message[$this->root_header]['result'];
6627 }
6628 // resolve hrefs/ids
6629 if (sizeof($this->multirefs) > 0) {
6630 foreach ($this->multirefs as $id => $hrefs) {
6631 $this->debug('resolving multirefs for id: ' . $id);
6632 $idVal = $this->buildVal($this->ids[$id]);
6633 if (is_array($idVal) && isset($idVal['!id'])) {
6634 unset($idVal['!id']);
6635 }
6636 foreach ($hrefs as $refPos => $ref) {
6637 $this->debug('resolving href at pos ' . $refPos);
6638 $this->multirefs[$id][$refPos] = $idVal;
6639 }
6640 }
6641 }
6642 }
6643 xml_parser_free($this->parser);
6644 } else {
6645 $this->debug('xml was empty, didn\'t parse!');
6646 $this->setError('xml was empty, didn\'t parse!');
6647 }
6648 }
6649
6658 public function start_element($parser, $name, $attrs)
6659 {
6660 // position in a total number of elements, starting from 0
6661 // update class level pos
6662 $pos = $this->position++;
6663 // and set mine
6664 $this->message[$pos] = array('pos' => $pos,'children' => '','cdata' => '');
6665 // depth = how many levels removed from root?
6666 // set mine as current global depth and increment global depth value
6667 $this->message[$pos]['depth'] = $this->depth++;
6668
6669 // else add self as child to whoever the current parent is
6670 if ($pos != 0) {
6671 $this->message[$this->parent]['children'] .= '|' . $pos;
6672 }
6673 // set my parent
6674 $this->message[$pos]['parent'] = $this->parent;
6675 // set self as current parent
6676 $this->parent = $pos;
6677 // set self as current value for this depth
6678 $this->depth_array[$this->depth] = $pos;
6679 // get element prefix
6680 if (strpos($name, ':')) {
6681 // get ns prefix
6682 $prefix = substr($name, 0, strpos($name, ':'));
6683 // get unqualified name
6684 $name = substr(strstr($name, ':'), 1);
6685 }
6686 // set status
6687 if ($name == 'Envelope') {
6688 $this->status = 'envelope';
6689 } elseif ($name == 'Header' && $this->status = 'envelope') {
6690 $this->root_header = $pos;
6691 $this->status = 'header';
6692 } elseif ($name == 'Body' && $this->status = 'envelope') {
6693 $this->status = 'body';
6694 $this->body_position = $pos;
6695 // set method
6696 } elseif ($this->status == 'body' && $pos == ($this->body_position + 1)) {
6697 $this->status = 'method';
6698 $this->root_struct_name = $name;
6699 $this->root_struct = $pos;
6700 $this->message[$pos]['type'] = 'struct';
6701 $this->debug("found root struct $this->root_struct_name, pos $this->root_struct");
6702 }
6703 // set my status
6704 $this->message[$pos]['status'] = $this->status;
6705 // set name
6706 $this->message[$pos]['name'] = htmlspecialchars($name);
6707 // set attrs
6708 $this->message[$pos]['attrs'] = $attrs;
6709
6710 // loop through atts, logging ns and type declarations
6711 $attstr = '';
6712 foreach ($attrs as $key => $value) {
6713 $key_prefix = $this->getPrefix($key);
6714 $key_localpart = $this->getLocalPart($key);
6715 // if ns declarations, add to class level array of valid namespaces
6716 if ($key_prefix == 'xmlns') {
6717 if (preg_match('/^http:\/\/www.w3.org\/[0-9]{4}\/XMLSchema$/', $value)) {
6718 $this->XMLSchemaVersion = $value;
6719 $this->namespaces['xsd'] = $this->XMLSchemaVersion;
6720 $this->namespaces['xsi'] = $this->XMLSchemaVersion . '-instance';
6721 }
6722 $this->namespaces[$key_localpart] = $value;
6723 // set method namespace
6724 if ($name == $this->root_struct_name) {
6725 $this->methodNamespace = $value;
6726 }
6727 // if it's a type declaration, set type
6728 } elseif ($key_localpart == 'type') {
6729 if (isset($this->message[$pos]['type']) && $this->message[$pos]['type'] == 'array') {
6730 // do nothing: already processed arrayType
6731 } else {
6732 $value_prefix = $this->getPrefix($value);
6733 $value_localpart = $this->getLocalPart($value);
6734 $this->message[$pos]['type'] = $value_localpart;
6735 $this->message[$pos]['typePrefix'] = $value_prefix;
6736 if (isset($this->namespaces[$value_prefix])) {
6737 $this->message[$pos]['type_namespace'] = $this->namespaces[$value_prefix];
6738 } elseif (isset($attrs['xmlns:' . $value_prefix])) {
6739 $this->message[$pos]['type_namespace'] = $attrs['xmlns:' . $value_prefix];
6740 }
6741 // should do something here with the namespace of specified type?
6742 }
6743 } elseif ($key_localpart == 'arrayType') {
6744 $this->message[$pos]['type'] = 'array';
6745 /* do arrayType ereg here
6746 [1] arrayTypeValue ::= atype asize
6747 [2] atype ::= QName rank*
6748 [3] rank ::= '[' (',')* ']'
6749 [4] asize ::= '[' length~ ']'
6750 [5] length ::= nextDimension* Digit+
6751 [6] nextDimension ::= Digit+ ','
6752 */
6753 $expr = '/([A-Za-z0-9_]+):([A-Za-z]+[A-Za-z0-9_]+)\[([0-9]+),?([0-9]*)\]/';
6754 if (preg_match($expr, $value, $regs)) {
6755 $this->message[$pos]['typePrefix'] = $regs[1];
6756 $this->message[$pos]['arrayTypePrefix'] = $regs[1];
6757 if (isset($this->namespaces[$regs[1]])) {
6758 $this->message[$pos]['arrayTypeNamespace'] = $this->namespaces[$regs[1]];
6759 } elseif (isset($attrs['xmlns:' . $regs[1]])) {
6760 $this->message[$pos]['arrayTypeNamespace'] = $attrs['xmlns:' . $regs[1]];
6761 }
6762 $this->message[$pos]['arrayType'] = $regs[2];
6763 $this->message[$pos]['arraySize'] = $regs[3];
6764 $this->message[$pos]['arrayCols'] = $regs[4];
6765 }
6766 // specifies nil value (or not)
6767 } elseif ($key_localpart == 'nil') {
6768 $this->message[$pos]['nil'] = ($value == 'true' || $value == '1');
6769 // some other attribute
6770 } elseif ($key != 'href' && $key != 'xmlns' && $key_localpart != 'encodingStyle' && $key_localpart != 'root') {
6771 $this->message[$pos]['xattrs']['!' . $key] = $value;
6772 }
6773
6774 if ($key == 'xmlns') {
6775 $this->default_namespace = $value;
6776 }
6777 // log id
6778 if ($key == 'id') {
6779 $this->ids[$value] = $pos;
6780 }
6781 // root
6782 if ($key_localpart == 'root' && $value == 1) {
6783 $this->status = 'method';
6784 $this->root_struct_name = $name;
6785 $this->root_struct = $pos;
6786 $this->debug("found root struct $this->root_struct_name, pos $pos");
6787 }
6788 // for doclit
6789 $attstr .= " $key=\"$value\"";
6790 }
6791 // get namespace - must be done after namespace atts are processed
6792 if (isset($prefix)) {
6793 $this->message[$pos]['namespace'] = $this->namespaces[$prefix];
6794 $this->default_namespace = $this->namespaces[$prefix];
6795 } else {
6796 $this->message[$pos]['namespace'] = $this->default_namespace;
6797 }
6798 if ($this->status == 'header') {
6799 if ($this->root_header != $pos) {
6800 $this->responseHeaders .= "<" . (isset($prefix) ? $prefix . ':' : '') . "$name$attstr>";
6801 }
6802 } elseif ($this->root_struct_name != '') {
6803 $this->document .= "<" . (isset($prefix) ? $prefix . ':' : '') . "$name$attstr>";
6804 }
6805 }
6806
6814 public function end_element($parser, $name)
6815 {
6816 // position of current element is equal to the last value left in depth_array for my depth
6817 $pos = $this->depth_array[$this->depth--];
6818
6819 // get element prefix
6820 if (strpos($name, ':')) {
6821 // get ns prefix
6822 $prefix = substr($name, 0, strpos($name, ':'));
6823 // get unqualified name
6824 $name = substr(strstr($name, ':'), 1);
6825 }
6826
6827 // build to native type
6828 if (isset($this->body_position) && $pos > $this->body_position) {
6829 // deal w/ multirefs
6830 if (isset($this->message[$pos]['attrs']['href'])) {
6831 // get id
6832 $id = substr($this->message[$pos]['attrs']['href'], 1);
6833 // add placeholder to href array
6834 $this->multirefs[$id][$pos] = 'placeholder';
6835 // add set a reference to it as the result value
6836 $this->message[$pos]['result'] = & $this->multirefs[$id][$pos];
6837 // build complexType values
6838 } elseif ($this->message[$pos]['children'] != '') {
6839 // if result has already been generated (struct/array)
6840 if (!isset($this->message[$pos]['result'])) {
6841 $this->message[$pos]['result'] = $this->buildVal($pos);
6842 }
6843 // build complexType values of attributes and possibly simpleContent
6844 } elseif (isset($this->message[$pos]['xattrs'])) {
6845 if (isset($this->message[$pos]['nil']) && $this->message[$pos]['nil']) {
6846 $this->message[$pos]['xattrs']['!'] = null;
6847 } elseif (isset($this->message[$pos]['cdata']) && trim($this->message[$pos]['cdata']) != '') {
6848 if (isset($this->message[$pos]['type'])) {
6849 $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'] : '');
6850 } else {
6851 $parent = $this->message[$pos]['parent'];
6852 if (isset($this->message[$parent]['type']) && ($this->message[$parent]['type'] == 'array') && isset($this->message[$parent]['arrayType'])) {
6853 $this->message[$pos]['xattrs']['!'] = $this->decodeSimple($this->message[$pos]['cdata'], $this->message[$parent]['arrayType'], isset($this->message[$parent]['arrayTypeNamespace']) ? $this->message[$parent]['arrayTypeNamespace'] : '');
6854 } else {
6855 $this->message[$pos]['xattrs']['!'] = $this->message[$pos]['cdata'];
6856 }
6857 }
6858 }
6859 $this->message[$pos]['result'] = $this->message[$pos]['xattrs'];
6860 // set value of simpleType (or nil complexType)
6861 } else {
6862 //$this->debug('adding data for scalar value '.$this->message[$pos]['name'].' of value '.$this->message[$pos]['cdata']);
6863 if (isset($this->message[$pos]['nil']) && $this->message[$pos]['nil']) {
6864 $this->message[$pos]['xattrs']['!'] = null;
6865 } elseif (isset($this->message[$pos]['type'])) {
6866 $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'] : '');
6867 } else {
6868 $parent = $this->message[$pos]['parent'];
6869 if (isset($this->message[$parent]['type']) && ($this->message[$parent]['type'] == 'array') && isset($this->message[$parent]['arrayType'])) {
6870 $this->message[$pos]['result'] = $this->decodeSimple($this->message[$pos]['cdata'], $this->message[$parent]['arrayType'], isset($this->message[$parent]['arrayTypeNamespace']) ? $this->message[$parent]['arrayTypeNamespace'] : '');
6871 } else {
6872 $this->message[$pos]['result'] = $this->message[$pos]['cdata'];
6873 }
6874 }
6875
6876 /* add value to parent's result, if parent is struct/array
6877 $parent = $this->message[$pos]['parent'];
6878 if($this->message[$parent]['type'] != 'map'){
6879 if(strtolower($this->message[$parent]['type']) == 'array'){
6880 $this->message[$parent]['result'][] = $this->message[$pos]['result'];
6881 } else {
6882 $this->message[$parent]['result'][$this->message[$pos]['name']] = $this->message[$pos]['result'];
6883 }
6884 }
6885 */
6886 }
6887 }
6888
6889 // for doclit
6890 if ($this->status == 'header') {
6891 if ($this->root_header != $pos) {
6892 $this->responseHeaders .= "</" . (isset($prefix) ? $prefix . ':' : '') . "$name>";
6893 }
6894 } elseif ($pos >= $this->root_struct) {
6895 $this->document .= "</" . (isset($prefix) ? $prefix . ':' : '') . "$name>";
6896 }
6897 // switch status
6898 if ($pos == $this->root_struct) {
6899 $this->status = 'body';
6900 $this->root_struct_namespace = $this->message[$pos]['namespace'];
6901 } elseif ($name == 'Body') {
6902 $this->status = 'envelope';
6903 } elseif ($name == 'Header') {
6904 $this->status = 'envelope';
6905 } elseif ($name == 'Envelope') {
6906 //
6907 }
6908 // set parent back to my parent
6909 $this->parent = $this->message[$pos]['parent'];
6910 }
6911
6919 public function character_data($parser, $data)
6920 {
6921 $pos = $this->depth_array[$this->depth];
6922 if ($this->xml_encoding == 'UTF-8') {
6923 // TODO: add an option to disable this for folks who want
6924 // raw UTF-8 that, e.g., might not map to iso-8859-1
6925 // TODO: this can also be handled with xml_parser_set_option($this->parser, XML_OPTION_TARGET_ENCODING, "ISO-8859-1");
6926 if ($this->decode_utf8) {
6927 $data = utf8_decode($data);
6928 }
6929 }
6930 $this->message[$pos]['cdata'] .= $data;
6931 // for doclit
6932 if ($this->status == 'header') {
6933 $this->responseHeaders .= $data;
6934 } else {
6935 $this->document .= $data;
6936 }
6937 }
6938
6946 public function get_response()
6947 {
6948 return $this->soapresponse;
6949 }
6950
6957 public function get_soapbody()
6958 {
6959 return $this->soapresponse;
6960 }
6961
6968 public function get_soapheader()
6969 {
6970 return $this->soapheader;
6971 }
6972
6979 public function getHeaders()
6980 {
6982 }
6983
6993 public function decodeSimple($value, $type, $typens)
6994 {
6995 // TODO: use the namespace!
6996 if ((!isset($type)) || $type == 'string' || $type == 'long' || $type == 'unsignedLong') {
6997 return (string) $value;
6998 }
6999 if ($type == 'int' || $type == 'integer' || $type == 'short' || $type == 'byte') {
7000 return (int) $value;
7001 }
7002 if ($type == 'float' || $type == 'double' || $type == 'decimal') {
7003 return (float) $value;
7004 }
7005 if ($type == 'boolean') {
7006 if (strtolower($value) == 'false' || strtolower($value) == 'f') {
7007 return false;
7008 }
7009 return (bool) $value;
7010 }
7011 if ($type == 'base64' || $type == 'base64Binary') {
7012 $this->debug('Decode base64 value');
7013 return base64_decode($value);
7014 }
7015 // obscure numeric types
7016 if ($type == 'nonPositiveInteger' || $type == 'negativeInteger'
7017 || $type == 'nonNegativeInteger' || $type == 'positiveInteger'
7018 || $type == 'unsignedInt'
7019 || $type == 'unsignedShort' || $type == 'unsignedByte') {
7020 return (int) $value;
7021 }
7022 // bogus: parser treats array with no elements as a simple type
7023 if ($type == 'array') {
7024 return array();
7025 }
7026 // everything else
7027 return (string) $value;
7028 }
7029
7038 public function buildVal($pos)
7039 {
7040 if (!isset($this->message[$pos]['type'])) {
7041 $this->message[$pos]['type'] = '';
7042 }
7043 $this->debug('in buildVal() for ' . $this->message[$pos]['name'] . "(pos $pos) of type " . $this->message[$pos]['type']);
7044 // if there are children...
7045 if ($this->message[$pos]['children'] != '') {
7046 $this->debug('in buildVal, there are children');
7047 $children = explode('|', $this->message[$pos]['children']);
7048 array_shift($children); // knock off empty
7049 // md array
7050 if (isset($this->message[$pos]['arrayCols']) && $this->message[$pos]['arrayCols'] != '') {
7051 $r = 0; // rowcount
7052 $c = 0; // colcount
7053 foreach ($children as $child_pos) {
7054 $this->debug("in buildVal, got an MD array element: $r, $c");
7055 $params[$r][] = $this->message[$child_pos]['result'];
7056 $c++;
7057 if ($c == $this->message[$pos]['arrayCols']) {
7058 $c = 0;
7059 $r++;
7060 }
7061 }
7062 // array
7063 } elseif ($this->message[$pos]['type'] == 'array' || $this->message[$pos]['type'] == 'Array') {
7064 $this->debug('in buildVal, adding array ' . $this->message[$pos]['name']);
7065 foreach ($children as $child_pos) {
7066 $params[] = &$this->message[$child_pos]['result'];
7067 }
7068 // apache Map type: java hashtable
7069 } elseif ($this->message[$pos]['type'] == 'Map' && $this->message[$pos]['type_namespace'] == 'http://xml.apache.org/xml-soap') {
7070 $this->debug('in buildVal, Java Map ' . $this->message[$pos]['name']);
7071 foreach ($children as $child_pos) {
7072 $kv = explode("|", $this->message[$child_pos]['children']);
7073 $params[$this->message[$kv[1]]['result']] = &$this->message[$kv[2]]['result'];
7074 }
7075 // generic compound type
7076 //} elseif($this->message[$pos]['type'] == 'SOAPStruct' || $this->message[$pos]['type'] == 'struct') {
7077 } else {
7078 // Apache Vector type: treat as an array
7079 $this->debug('in buildVal, adding Java Vector or generic compound type ' . $this->message[$pos]['name']);
7080 if ($this->message[$pos]['type'] == 'Vector' && $this->message[$pos]['type_namespace'] == 'http://xml.apache.org/xml-soap') {
7081 $notstruct = 1;
7082 } else {
7083 $notstruct = 0;
7084 }
7085 //
7086 foreach ($children as $child_pos) {
7087 if ($notstruct) {
7088 $params[] = &$this->message[$child_pos]['result'];
7089 } else {
7090 if (isset($params[$this->message[$child_pos]['name']])) {
7091 // de-serialize repeated element name into an array
7092 if ((!is_array($params[$this->message[$child_pos]['name']])) || (!isset($params[$this->message[$child_pos]['name']][0]))) {
7093 $params[$this->message[$child_pos]['name']] = array($params[$this->message[$child_pos]['name']]);
7094 }
7095 $params[$this->message[$child_pos]['name']][] = &$this->message[$child_pos]['result'];
7096 } else {
7097 $params[$this->message[$child_pos]['name']] = &$this->message[$child_pos]['result'];
7098 }
7099 }
7100 }
7101 }
7102 if (isset($this->message[$pos]['xattrs'])) {
7103 $this->debug('in buildVal, handling attributes');
7104 foreach ($this->message[$pos]['xattrs'] as $n => $v) {
7105 $params[$n] = $v;
7106 }
7107 }
7108 // handle simpleContent
7109 if (isset($this->message[$pos]['cdata']) && trim($this->message[$pos]['cdata']) != '') {
7110 $this->debug('in buildVal, handling simpleContent');
7111 if (isset($this->message[$pos]['type'])) {
7112 $params['!'] = $this->decodeSimple($this->message[$pos]['cdata'], $this->message[$pos]['type'], isset($this->message[$pos]['type_namespace']) ? $this->message[$pos]['type_namespace'] : '');
7113 } else {
7114 $parent = $this->message[$pos]['parent'];
7115 if (isset($this->message[$parent]['type']) && ($this->message[$parent]['type'] == 'array') && isset($this->message[$parent]['arrayType'])) {
7116 $params['!'] = $this->decodeSimple($this->message[$pos]['cdata'], $this->message[$parent]['arrayType'], isset($this->message[$parent]['arrayTypeNamespace']) ? $this->message[$parent]['arrayTypeNamespace'] : '');
7117 } else {
7118 $params['!'] = $this->message[$pos]['cdata'];
7119 }
7120 }
7121 }
7122 $ret = is_array($params) ? $params : array();
7123 $this->debug('in buildVal, return:');
7124 $this->appendDebug($this->varDump($ret));
7125 return $ret;
7126 } else {
7127 $this->debug('in buildVal, no children, building scalar');
7128 $cdata = isset($this->message[$pos]['cdata']) ? $this->message[$pos]['cdata'] : '';
7129 if (isset($this->message[$pos]['type'])) {
7130 $ret = $this->decodeSimple($cdata, $this->message[$pos]['type'], isset($this->message[$pos]['type_namespace']) ? $this->message[$pos]['type_namespace'] : '');
7131 $this->debug("in buildVal, return: $ret");
7132 return $ret;
7133 }
7134 $parent = $this->message[$pos]['parent'];
7135 if (isset($this->message[$parent]['type']) && ($this->message[$parent]['type'] == 'array') && isset($this->message[$parent]['arrayType'])) {
7136 $ret = $this->decodeSimple($cdata, $this->message[$parent]['arrayType'], isset($this->message[$parent]['arrayTypeNamespace']) ? $this->message[$parent]['arrayTypeNamespace'] : '');
7137 $this->debug("in buildVal, return: $ret");
7138 return $ret;
7139 }
7140 $ret = $this->message[$pos]['cdata'];
7141 $this->debug("in buildVal, return: $ret");
7142 return $ret;
7143 }
7144 }
7145}
7146
7151{
7152}
7153
7154?><?php
7155
7156
7157
7179{
7180 public $return;
7181 public $wsdl;
7183 public $opData;
7185 public $username = ''; // Username for HTTP authentication
7186 public $password = ''; // Password for HTTP authentication
7187 public $authtype = ''; // Type of HTTP authentication
7188 public $certRequest = array(); // Certificate for HTTP SSL authentication
7189 public $requestHeaders = false; // SOAP headers in request (text)
7190 public $responseHeaders = ''; // SOAP headers from response (incomplete namespace resolution) (text)
7191 public $responseHeader = null; // SOAP Header from response (parsed)
7192 public $document = ''; // SOAP body response portion (incomplete namespace resolution) (text)
7194 public $forceEndpoint = ''; // overrides WSDL endpoint
7195 public $proxyhost = '';
7196 public $proxyport = '';
7197 public $proxyusername = '';
7198 public $proxypassword = '';
7199 public $xml_encoding = ''; // character set encoding of incoming (response) messages
7200 public $http_encoding = false;
7201 public $timeout = 0; // HTTP connection timeout
7202 public $response_timeout = 30; // HTTP response timeout
7203 public $endpointType = ''; // soap|wsdl, empty for WSDL initialization error
7205 public $defaultRpcParams = false; // This is no longer used
7206 public $request = ''; // HTTP request
7207 public $response = ''; // HTTP response
7208 public $responseData = ''; // SOAP payload of response
7209 public $cookies = array(); // Cookies from response or for request
7210 public $decode_utf8 = true; // toggles whether the parser decodes element content w/ utf8_decode()
7211 public $operations = array(); // WSDL operations, empty for WSDL initialization error
7212 public $curl_options = array(); // User-specified cURL options
7213 public $bindingType = ''; // WSDL operation binding type
7214 public $use_curl = false; // whether to always try to use cURL
7215
7216 /*
7217 * fault related variables
7218 */
7223 public $fault;
7239
7254 public function __construct($endpoint, $wsdl = false, $proxyhost = false, $proxyport = false, $proxyusername = false, $proxypassword = false, $timeout = 0, $response_timeout = 30)
7255 {
7257 $this->endpoint = $endpoint;
7258 $this->proxyhost = $proxyhost;
7259 $this->proxyport = $proxyport;
7260 $this->proxyusername = $proxyusername;
7261 $this->proxypassword = $proxypassword;
7262 $this->timeout = $timeout;
7263 $this->response_timeout = $response_timeout;
7264
7265 $this->debug("ctor wsdl=$wsdl timeout=$timeout response_timeout=$response_timeout");
7266 $this->appendDebug('endpoint=' . $this->varDump($endpoint));
7267
7268 // make values
7269 if ($wsdl) {
7270 if (is_object($endpoint) && (get_class($endpoint) == 'wsdl')) {
7271 $this->wsdl = $endpoint;
7272 $this->endpoint = $this->wsdl->wsdl;
7273 $this->wsdlFile = $this->endpoint;
7274 $this->debug('existing wsdl instance created from ' . $this->endpoint);
7275 $this->checkWSDL();
7276 } else {
7277 $this->wsdlFile = $this->endpoint;
7278 $this->wsdl = null;
7279 $this->debug('will use lazy evaluation of wsdl from ' . $this->endpoint);
7280 }
7281 $this->endpointType = 'wsdl';
7282 } else {
7283 $this->debug("instantiate SOAP with endpoint at $endpoint");
7284 $this->endpointType = 'soap';
7285 }
7286 }
7287
7313 public function call($operation, $params = array(), $namespace = 'http://tempuri.org', $soapAction = '', $headers = false, $rpcParams = null, $style = 'rpc', $use = 'encoded')
7314 {
7315 $this->operation = $operation;
7316 $this->fault = false;
7317 $this->setError('');
7318 $this->request = '';
7319 $this->response = '';
7320 $this->responseData = '';
7321 $this->faultstring = '';
7322 $this->faultcode = '';
7323 $this->opData = array();
7324
7325 $this->debug("call: operation=$operation, namespace=$namespace, soapAction=$soapAction, rpcParams=$rpcParams, style=$style, use=$use, endpointType=$this->endpointType");
7326 $this->appendDebug('params=' . $this->varDump($params));
7327 $this->appendDebug('headers=' . $this->varDump($headers));
7328 if ($headers) {
7329 $this->requestHeaders = $headers;
7330 }
7331 if ($this->endpointType == 'wsdl' && is_null($this->wsdl)) {
7332 $this->loadWSDL();
7333 if ($this->getError()) {
7334 return false;
7335 }
7336 }
7337 // serialize parameters
7338 if ($this->endpointType == 'wsdl' && $opData = $this->getOperationData($operation)) {
7339 // use WSDL for operation
7340 $this->opData = $opData;
7341 $this->debug("found operation");
7342 $this->appendDebug('opData=' . $this->varDump($opData));
7343 if (isset($opData['soapAction'])) {
7344 $soapAction = $opData['soapAction'];
7345 }
7346 if (! $this->forceEndpoint) {
7347 $this->endpoint = $opData['endpoint'];
7348 } else {
7349 $this->endpoint = $this->forceEndpoint;
7350 }
7351 $namespace = isset($opData['input']['namespace']) ? $opData['input']['namespace'] : $namespace;
7352 $style = $opData['style'];
7353 $use = $opData['input']['use'];
7354 // add ns to ns array
7355 if ($namespace != '' && !isset($this->wsdl->namespaces[$namespace])) {
7356 $nsPrefix = 'ns' . rand(1000, 9999);
7357 $this->wsdl->namespaces[$nsPrefix] = $namespace;
7358 }
7359 $nsPrefix = $this->wsdl->getPrefixFromNamespace($namespace);
7360 // serialize payload
7361 if (is_string($params)) {
7362 $this->debug("serializing param string for WSDL operation $operation");
7363 $payload = $params;
7364 } elseif (is_array($params)) {
7365 $this->debug("serializing param array for WSDL operation $operation");
7366 $payload = $this->wsdl->serializeRPCParameters($operation, 'input', $params, $this->bindingType);
7367 } else {
7368 $this->debug('params must be array or string');
7369 $this->setError('params must be array or string');
7370 return false;
7371 }
7372 $usedNamespaces = $this->wsdl->usedNamespaces;
7373 if (isset($opData['input']['encodingStyle'])) {
7374 $encodingStyle = $opData['input']['encodingStyle'];
7375 } else {
7376 $encodingStyle = '';
7377 }
7378 $this->appendDebug($this->wsdl->getDebug());
7379 $this->wsdl->clearDebug();
7380 if ($errstr = $this->wsdl->getError()) {
7381 $this->debug('got wsdl error: ' . $errstr);
7382 $this->setError('wsdl error: ' . $errstr);
7383 return false;
7384 }
7385 } elseif ($this->endpointType == 'wsdl') {
7386 // operation not in WSDL
7387 $this->appendDebug($this->wsdl->getDebug());
7388 $this->wsdl->clearDebug();
7389 $this->setError('operation ' . $operation . ' not present.');
7390 $this->debug("operation '$operation' not present.");
7391 return false;
7392 } else {
7393 // no WSDL
7394 //$this->namespaces['ns1'] = $namespace;
7395 $nsPrefix = 'ns' . rand(1000, 9999);
7396 // serialize
7397 $payload = '';
7398 if (is_string($params)) {
7399 $this->debug("serializing param string for operation $operation");
7400 $payload = $params;
7401 } elseif (is_array($params)) {
7402 $this->debug("serializing param array for operation $operation");
7403 foreach ($params as $k => $v) {
7404 $payload .= $this->serialize_val($v, $k, false, false, false, false, $use);
7405 }
7406 } else {
7407 $this->debug('params must be array or string');
7408 $this->setError('params must be array or string');
7409 return false;
7410 }
7411 $usedNamespaces = array();
7412 if ($use == 'encoded') {
7413 $encodingStyle = 'http://schemas.xmlsoap.org/soap/encoding/';
7414 } else {
7415 $encodingStyle = '';
7416 }
7417 }
7418 // wrap RPC calls with method element
7419 if ($style == 'rpc') {
7420 if ($use == 'literal') {
7421 $this->debug("wrapping RPC request with literal method element");
7422 if ($namespace) {
7423 // 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
7424 $payload = "<$nsPrefix:$operation xmlns:$nsPrefix=\"$namespace\">" .
7425 $payload .
7426 "</$nsPrefix:$operation>";
7427 } else {
7428 $payload = "<$operation>" . $payload . "</$operation>";
7429 }
7430 } else {
7431 $this->debug("wrapping RPC request with encoded method element");
7432 if ($namespace) {
7433 $payload = "<$nsPrefix:$operation xmlns:$nsPrefix=\"$namespace\">" .
7434 $payload .
7435 "</$nsPrefix:$operation>";
7436 } else {
7437 $payload = "<$operation>" .
7438 $payload .
7439 "</$operation>";
7440 }
7441 }
7442 }
7443 // serialize envelope
7444 $soapmsg = $this->serializeEnvelope($payload, $this->requestHeaders, $usedNamespaces, $style, $use, $encodingStyle);
7445 $this->debug("endpoint=$this->endpoint, soapAction=$soapAction, namespace=$namespace, style=$style, use=$use, encodingStyle=$encodingStyle");
7446 $this->debug('SOAP message length=' . strlen($soapmsg) . ' contents (max 1000 bytes)=' . substr($soapmsg, 0, 1000));
7447 // send
7448 $return = $this->send($this->getHTTPBody($soapmsg), $soapAction, $this->timeout, $this->response_timeout);
7449 if ($errstr = $this->getError()) {
7450 $this->debug('Error: ' . $errstr);
7451 return false;
7452 } else {
7453 $this->return = $return;
7454 $this->debug('sent message successfully and got a(n) ' . gettype($return));
7455 $this->appendDebug('return=' . $this->varDump($return));
7456
7457 // fault?
7458 if (is_array($return) && isset($return['faultcode'])) {
7459 $this->debug('got fault');
7460 $this->setError($return['faultcode'] . ': ' . $return['faultstring']);
7461 $this->fault = true;
7462 foreach ($return as $k => $v) {
7463 $this->$k = $v;
7464 $this->debug("$k = $v<br>");
7465 }
7466 return $return;
7467 } elseif ($style == 'document') {
7468 // NOTE: if the response is defined to have multiple parts (i.e. unwrapped),
7469 // we are only going to return the first part here...sorry about that
7470 return $return;
7471 } else {
7472 // array of return values
7473 if (is_array($return)) {
7474 // multiple 'out' parameters, which we return wrapped up
7475 // in the array
7476 if (sizeof($return) > 1) {
7477 return $return;
7478 }
7479 // single 'out' parameter (normally the return value)
7480 $return = array_shift($return);
7481 $this->debug('return shifted value: ');
7482 $this->appendDebug($this->varDump($return));
7483 return $return;
7484 // nothing returned (ie, echoVoid)
7485 } else {
7486 return "";
7487 }
7488 }
7489 }
7490 }
7491
7497 public function checkWSDL()
7498 {
7499 $this->appendDebug($this->wsdl->getDebug());
7500 $this->wsdl->clearDebug();
7501 $this->debug('checkWSDL');
7502 // catch errors
7503 if ($errstr = $this->wsdl->getError()) {
7504 $this->debug('got wsdl error: ' . $errstr);
7505 $this->setError('wsdl error: ' . $errstr);
7506 } elseif ($this->operations = $this->wsdl->getOperations('soap')) {
7507 $this->bindingType = 'soap';
7508 $this->debug('got ' . count($this->operations) . ' operations from wsdl ' . $this->wsdlFile . ' for binding type ' . $this->bindingType);
7509 } elseif ($this->operations = $this->wsdl->getOperations('soap12')) {
7510 $this->bindingType = 'soap12';
7511 $this->debug('got ' . count($this->operations) . ' operations from wsdl ' . $this->wsdlFile . ' for binding type ' . $this->bindingType);
7512 $this->debug('**************** WARNING: SOAP 1.2 BINDING *****************');
7513 } else {
7514 $this->debug('getOperations returned false');
7515 $this->setError('no operations defined in the WSDL document!');
7516 }
7517 }
7518
7524 public function loadWSDL()
7525 {
7526 $this->debug('instantiating wsdl class with doc: ' . $this->wsdlFile);
7527 $this->wsdl = new wsdl('', $this->proxyhost, $this->proxyport, $this->proxyusername, $this->proxypassword, $this->timeout, $this->response_timeout, $this->curl_options, $this->use_curl);
7528 $this->wsdl->setCredentials($this->username, $this->password, $this->authtype, $this->certRequest);
7529 $this->wsdl->fetchWSDL($this->wsdlFile);
7530 $this->checkWSDL();
7531 }
7532
7541 {
7542 if ($this->endpointType == 'wsdl' && is_null($this->wsdl)) {
7543 $this->loadWSDL();
7544 if ($this->getError()) {
7545 return false;
7546 }
7547 }
7548 if (isset($this->operations[$operation])) {
7549 return $this->operations[$operation];
7550 }
7551 $this->debug("No data for operation: $operation");
7552 }
7553
7568 public function send($msg, $soapaction = '', $timeout = 0, $response_timeout = 30)
7569 {
7570 $this->checkCookies();
7571 // detect transport
7572 switch (true) {
7573 // http(s)
7574 case preg_match('/^http/', $this->endpoint):
7575 $this->debug('transporting via HTTP');
7576 if ($this->persistentConnection == true && is_object($this->persistentConnection)) {
7578 } else {
7579 $http = new soap_transport_http($this->endpoint, $this->curl_options, $this->use_curl);
7580 if ($this->persistentConnection) {
7581 $http->usePersistentConnection();
7582 }
7583 }
7584 $http->setContentType($this->getHTTPContentType(), $this->getHTTPContentTypeCharset());
7585 $http->setSOAPAction($soapaction);
7586 if ($this->proxyhost && $this->proxyport) {
7587 $http->setProxy($this->proxyhost, $this->proxyport, $this->proxyusername, $this->proxypassword);
7588 }
7589 if ($this->authtype != '') {
7590 $http->setCredentials($this->username, $this->password, $this->authtype, array(), $this->certRequest);
7591 }
7592 if ($this->http_encoding != '') {
7593 $http->setEncoding($this->http_encoding);
7594 }
7595 $this->debug('sending message, length=' . strlen($msg));
7596 if (preg_match('/^http:/', $this->endpoint)) {
7597 //if(strpos($this->endpoint,'http:')){
7598 $this->responseData = $http->send($msg, $timeout, $response_timeout, $this->cookies);
7599 } elseif (preg_match('/^https/', $this->endpoint)) {
7600 //} elseif(strpos($this->endpoint,'https:')){
7601 //if(phpversion() == '4.3.0-dev'){
7602 //$response = $http->send($msg,$timeout,$response_timeout);
7603 //$this->request = $http->outgoing_payload;
7604 //$this->response = $http->incoming_payload;
7605 //} else
7606 $this->responseData = $http->sendHTTPS($msg, $timeout, $response_timeout, $this->cookies);
7607 } else {
7608 $this->setError('no http/s in endpoint url');
7609 }
7610 $this->request = $http->outgoing_payload;
7611 $this->response = $http->incoming_payload;
7612 $this->appendDebug($http->getDebug());
7613 $this->UpdateCookies($http->incoming_cookies);
7614
7615 // save transport object if using persistent connections
7616 if ($this->persistentConnection) {
7617 $http->clearDebug();
7618 if (!is_object($this->persistentConnection)) {
7619 $this->persistentConnection = $http;
7620 }
7621 }
7622
7623 if ($err = $http->getError()) {
7624 $this->setError('HTTP Error: ' . $err);
7625 return false;
7626 } elseif ($this->getError()) {
7627 return false;
7628 } else {
7629 $this->debug('got response, length=' . strlen($this->responseData) . ' type=' . $http->incoming_headers['content-type']);
7630 return $this->parseResponse($http->incoming_headers, $this->responseData);
7631 }
7632 break;
7633 default:
7634 $this->setError('no transport found, or selected transport is not yet supported!');
7635 return false;
7636 break;
7637 }
7638 }
7639
7648 public function parseResponse($headers, $data)
7649 {
7650 $this->debug('Entering parseResponse() for data of length ' . strlen($data) . ' headers:');
7651 $this->appendDebug($this->varDump($headers));
7652 if (!strstr($headers['content-type'], 'text/xml')) {
7653 $this->setError('Response not of type text/xml: ' . $headers['content-type']);
7654 return false;
7655 }
7656 if (strpos($headers['content-type'], '=')) {
7657 $enc = str_replace('"', '', substr(strstr($headers["content-type"], '='), 1));
7658 $this->debug('Got response encoding: ' . $enc);
7659 if (preg_match('/^(ISO-8859-1|US-ASCII|UTF-8)$/i', $enc)) {
7660 $this->xml_encoding = strtoupper($enc);
7661 } else {
7662 $this->xml_encoding = 'US-ASCII';
7663 }
7664 } else {
7665 // should be US-ASCII for HTTP 1.0 or ISO-8859-1 for HTTP 1.1
7666 $this->xml_encoding = 'ISO-8859-1';
7667 }
7668 $this->debug('Use encoding: ' . $this->xml_encoding . ' when creating nusoap_parser');
7669 $parser = new nusoap_parser($data, $this->xml_encoding, $this->operation, $this->decode_utf8);
7670 // add parser debug data to our debug
7671 $this->appendDebug($parser->getDebug());
7672 // if parse errors
7673 if ($errstr = $parser->getError()) {
7674 $this->setError($errstr);
7675 // destroy the parser object
7676 unset($parser);
7677 return false;
7678 } else {
7679 // get SOAP headers
7680 $this->responseHeaders = $parser->getHeaders();
7681 // get SOAP headers
7682 $this->responseHeader = $parser->get_soapheader();
7683 // get decoded message
7684 $return = $parser->get_soapbody();
7685 // add document for doclit support
7686 $this->document = $parser->document;
7687 // destroy the parser object
7688 unset($parser);
7689 // return decode message
7690 return $return;
7691 }
7692 }
7693
7701 public function setCurlOption($option, $value)
7702 {
7703 $this->debug("setCurlOption option=$option, value=");
7704 $this->appendDebug($this->varDump($value));
7705 $this->curl_options[$option] = $value;
7706 }
7707
7714 public function setEndpoint($endpoint)
7715 {
7716 $this->debug("setEndpoint(\"$endpoint\")");
7717 $this->forceEndpoint = $endpoint;
7718 }
7719
7726 public function setHeaders($headers)
7727 {
7728 $this->debug("setHeaders headers=");
7729 $this->appendDebug($this->varDump($headers));
7730 $this->requestHeaders = $headers;
7731 }
7732
7739 public function getHeaders()
7740 {
7742 }
7743
7750 public function getHeader()
7751 {
7752 return $this->responseHeader;
7753 }
7754
7765 {
7766 $this->proxyhost = $proxyhost;
7767 $this->proxyport = $proxyport;
7768 $this->proxyusername = $proxyusername;
7769 $this->proxypassword = $proxypassword;
7770 }
7771
7781 public function setCredentials($username, $password, $authtype = 'basic', $certRequest = array())
7782 {
7783 $this->debug("setCredentials username=$username authtype=$authtype certRequest=");
7784 $this->appendDebug($this->varDump($certRequest));
7785 $this->username = $username;
7786 $this->password = $password;
7787 $this->authtype = $authtype;
7788 $this->certRequest = $certRequest;
7789 }
7790
7797 public function setHTTPEncoding($enc = 'gzip, deflate')
7798 {
7799 $this->debug("setHTTPEncoding(\"$enc\")");
7800 $this->http_encoding = $enc;
7801 }
7802
7809 public function setUseCURL($use)
7810 {
7811 $this->debug("setUseCURL($use)");
7812 $this->use_curl = $use;
7813 }
7814
7821 {
7822 $this->debug("useHTTPPersistentConnection");
7823 $this->persistentConnection = true;
7824 }
7825
7837 public function getDefaultRpcParams()
7838 {
7840 }
7841
7853 public function setDefaultRpcParams($rpcParams)
7854 {
7855 $this->defaultRpcParams = $rpcParams;
7856 }
7857
7865 public function getProxy()
7866 {
7867 $r = rand();
7868 $evalStr = $this->_getProxyClassCode($r);
7869 //$this->debug("proxy class: $evalStr");
7870 if ($this->getError()) {
7871 $this->debug("Error from _getProxyClassCode, so return NULL");
7872 return null;
7873 }
7874 // eval the class
7875 eval($evalStr);
7876 // instantiate proxy object
7877 eval("\$proxy = new nusoap_proxy_$r('');");
7878 // transfer current wsdl data to the proxy thereby avoiding parsing the wsdl twice
7879 $proxy->endpointType = 'wsdl';
7880 $proxy->wsdlFile = $this->wsdlFile;
7881 $proxy->wsdl = $this->wsdl;
7882 $proxy->operations = $this->operations;
7883 $proxy->defaultRpcParams = $this->defaultRpcParams;
7884 // transfer other state
7885 $proxy->soap_defencoding = $this->soap_defencoding;
7886 $proxy->username = $this->username;
7887 $proxy->password = $this->password;
7888 $proxy->authtype = $this->authtype;
7889 $proxy->certRequest = $this->certRequest;
7890 $proxy->requestHeaders = $this->requestHeaders;
7891 $proxy->endpoint = $this->endpoint;
7892 $proxy->forceEndpoint = $this->forceEndpoint;
7893 $proxy->proxyhost = $this->proxyhost;
7894 $proxy->proxyport = $this->proxyport;
7895 $proxy->proxyusername = $this->proxyusername;
7896 $proxy->proxypassword = $this->proxypassword;
7897 $proxy->http_encoding = $this->http_encoding;
7898 $proxy->timeout = $this->timeout;
7899 $proxy->response_timeout = $this->response_timeout;
7900 $proxy->persistentConnection = &$this->persistentConnection;
7901 $proxy->decode_utf8 = $this->decode_utf8;
7902 $proxy->curl_options = $this->curl_options;
7903 $proxy->bindingType = $this->bindingType;
7904 $proxy->use_curl = $this->use_curl;
7905 return $proxy;
7906 }
7907
7914 public function _getProxyClassCode($r)
7915 {
7916 $this->debug("in getProxy endpointType=$this->endpointType");
7917 $this->appendDebug("wsdl=" . $this->varDump($this->wsdl));
7918 if ($this->endpointType != 'wsdl') {
7919 $evalStr = 'A proxy can only be created for a WSDL client';
7920 $this->setError($evalStr);
7921 $evalStr = "echo \"$evalStr\";";
7922 return $evalStr;
7923 }
7924 if ($this->endpointType == 'wsdl' && is_null($this->wsdl)) {
7925 $this->loadWSDL();
7926 if ($this->getError()) {
7927 return "echo \"" . $this->getError() . "\";";
7928 }
7929 }
7930 $evalStr = '';
7931 foreach ($this->operations as $operation => $opData) {
7932 if ($operation != '') {
7933 // create param string and param comment string
7934 if (sizeof($opData['input']['parts']) > 0) {
7935 $paramStr = '';
7936 $paramArrayStr = '';
7937 $paramCommentStr = '';
7938 foreach ($opData['input']['parts'] as $name => $type) {
7939 $paramStr .= "\$$name, ";
7940 $paramArrayStr .= "'$name' => \$$name, ";
7941 $paramCommentStr .= "$type \$$name, ";
7942 }
7943 $paramStr = substr($paramStr, 0, strlen($paramStr) - 2);
7944 $paramArrayStr = substr($paramArrayStr, 0, strlen($paramArrayStr) - 2);
7945 $paramCommentStr = substr($paramCommentStr, 0, strlen($paramCommentStr) - 2);
7946 } else {
7947 $paramStr = '';
7948 $paramArrayStr = '';
7949 $paramCommentStr = 'void';
7950 }
7951 $opData['namespace'] = !isset($opData['namespace']) ? 'http://testuri.com' : $opData['namespace'];
7952 $evalStr .= "// $paramCommentStr
7953 function " . str_replace('.', '__', $operation) . "($paramStr) {
7954 \$params = array($paramArrayStr);
7955 return \$this->call('$operation', \$params, '" . $opData['namespace'] . "', '" . (isset($opData['soapAction']) ? $opData['soapAction'] : '') . "');
7956 }
7957 ";
7958 unset($paramStr);
7959 unset($paramCommentStr);
7960 }
7961 }
7962 $evalStr = 'class nusoap_proxy_' . $r . ' extends nusoap_client {
7963 ' . $evalStr . '
7964}';
7965 return $evalStr;
7966 }
7967
7974 public function getProxyClassCode()
7975 {
7976 $r = rand();
7977 return $this->_getProxyClassCode($r);
7978 }
7979
7987 public function getHTTPBody($soapmsg)
7988 {
7989 return $soapmsg;
7990 }
7991
8000 public function getHTTPContentType()
8001 {
8002 return 'text/xml';
8003 }
8004
8015 {
8017 }
8018
8019 /*
8020 * whether or not parser should decode utf8 element content
8021 *
8022 * @return always returns true
8023 * @access public
8024 */
8025 public function decodeUTF8($bool)
8026 {
8027 $this->decode_utf8 = $bool;
8028 return true;
8029 }
8030
8039 public function setCookie($name, $value)
8040 {
8041 if (strlen($name) == 0) {
8042 return false;
8043 }
8044 $this->cookies[] = array('name' => $name, 'value' => $value);
8045 return true;
8046 }
8047
8054 public function getCookies()
8055 {
8056 return $this->cookies;
8057 }
8058
8065 public function checkCookies()
8066 {
8067 if (sizeof($this->cookies) == 0) {
8068 return true;
8069 }
8070 $this->debug('checkCookie: check ' . sizeof($this->cookies) . ' cookies');
8071 $curr_cookies = $this->cookies;
8072 $this->cookies = array();
8073 foreach ($curr_cookies as $cookie) {
8074 if (! is_array($cookie)) {
8075 $this->debug('Remove cookie that is not an array');
8076 continue;
8077 }
8078 if ((isset($cookie['expires'])) && (! empty($cookie['expires']))) {
8079 if (strtotime($cookie['expires']) > time()) {
8080 $this->cookies[] = $cookie;
8081 } else {
8082 $this->debug('Remove expired cookie ' . $cookie['name']);
8083 }
8084 } else {
8085 $this->cookies[] = $cookie;
8086 }
8087 }
8088 $this->debug('checkCookie: ' . sizeof($this->cookies) . ' cookies left in array');
8089 return true;
8090 }
8091
8099 public function UpdateCookies($cookies)
8100 {
8101 if (sizeof($this->cookies) == 0) {
8102 // no existing cookies: take whatever is new
8103 if (sizeof($cookies) > 0) {
8104 $this->debug('Setting new cookie(s)');
8105 $this->cookies = $cookies;
8106 }
8107 return true;
8108 }
8109 if (sizeof($cookies) == 0) {
8110 // no new cookies: keep what we've got
8111 return true;
8112 }
8113 // merge
8114 foreach ($cookies as $newCookie) {
8115 if (!is_array($newCookie)) {
8116 continue;
8117 }
8118 if ((!isset($newCookie['name'])) || (!isset($newCookie['value']))) {
8119 continue;
8120 }
8121 $newName = $newCookie['name'];
8122
8123 $found = false;
8124 for ($i = 0; $i < count($this->cookies); $i++) {
8125 $cookie = $this->cookies[$i];
8126 if (!is_array($cookie)) {
8127 continue;
8128 }
8129 if (!isset($cookie['name'])) {
8130 continue;
8131 }
8132 if ($newName != $cookie['name']) {
8133 continue;
8134 }
8135 $newDomain = isset($newCookie['domain']) ? $newCookie['domain'] : 'NODOMAIN';
8136 $domain = isset($cookie['domain']) ? $cookie['domain'] : 'NODOMAIN';
8137 if ($newDomain != $domain) {
8138 continue;
8139 }
8140 $newPath = isset($newCookie['path']) ? $newCookie['path'] : 'NOPATH';
8141 $path = isset($cookie['path']) ? $cookie['path'] : 'NOPATH';
8142 if ($newPath != $path) {
8143 continue;
8144 }
8145 $this->cookies[$i] = $newCookie;
8146 $found = true;
8147 $this->debug('Update cookie ' . $newName . '=' . $newCookie['value']);
8148 break;
8149 }
8150 if (! $found) {
8151 $this->debug('Add cookie ' . $newName . '=' . $newCookie['value']);
8152 $this->cookies[] = $newCookie;
8153 }
8154 }
8155 return true;
8156 }
8157}
8158
8159if (!extension_loaded('soap')) {
8163 class soapclient extends nusoap_client
8164 {
8165 }
8166}
8167?>
$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:2016
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:7179
setCurlOption($option, $value)
sets user-specified cURL options
Definition: nusoap.php:7701
setCredentials($username, $password, $authtype='basic', $certRequest=array())
if authenticating, set user credentials here
Definition: nusoap.php:7781
setHTTPProxy($proxyhost, $proxyport, $proxyusername='', $proxypassword='')
set proxy info here
Definition: nusoap.php:7764
getProxy()
dynamically creates an instance of a proxy class, allowing user to directly call methods from wsdl
Definition: nusoap.php:7865
send($msg, $soapaction='', $timeout=0, $response_timeout=30)
send the SOAP message
Definition: nusoap.php:7568
setUseCURL($use)
Set whether to try to use cURL connections if possible.
Definition: nusoap.php:7809
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:7313
getProxyClassCode()
dynamically creates proxy class code
Definition: nusoap.php:7974
checkCookies()
checks all Cookies and delete those which are expired
Definition: nusoap.php:8065
getHTTPContentType()
gets the HTTP content type for the current request.
Definition: nusoap.php:8000
setHTTPEncoding($enc='gzip, deflate')
use HTTP encoding
Definition: nusoap.php:7797
getHeader()
get the SOAP response Header (parsed)
Definition: nusoap.php:7750
decodeUTF8($bool)
Definition: nusoap.php:8025
useHTTPPersistentConnection()
use HTTP persistent connections if possible
Definition: nusoap.php:7820
setCookie($name, $value)
adds a new Cookie into $this->cookies array
Definition: nusoap.php:8039
getHTTPContentTypeCharset()
gets the HTTP content type charset for the current request.
Definition: nusoap.php:8014
getOperationData($operation)
get available data pertaining to an operation
Definition: nusoap.php:7540
getDefaultRpcParams()
gets the default RPC parameter setting.
Definition: nusoap.php:7837
checkWSDL()
check WSDL passed as an instance or pulled from an endpoint
Definition: nusoap.php:7497
setHeaders($headers)
set the SOAP headers
Definition: nusoap.php:7726
loadWSDL()
instantiate wsdl object and parse wsdl file
Definition: nusoap.php:7524
getHTTPBody($soapmsg)
gets the HTTP body for the current request.
Definition: nusoap.php:7987
setDefaultRpcParams($rpcParams)
sets the default RPC parameter setting.
Definition: nusoap.php:7853
__construct($endpoint, $wsdl=false, $proxyhost=false, $proxyport=false, $proxyusername=false, $proxypassword=false, $timeout=0, $response_timeout=30)
constructor
Definition: nusoap.php:7254
setEndpoint($endpoint)
sets the SOAP endpoint, which can override WSDL
Definition: nusoap.php:7714
UpdateCookies($cookies)
updates the current cookies with a new set
Definition: nusoap.php:8099
getHeaders()
get the SOAP response headers (namespace resolution incomplete)
Definition: nusoap.php:7739
_getProxyClassCode($r)
dynamically creates proxy class code
Definition: nusoap.php:7914
getCookies()
gets all Cookies
Definition: nusoap.php:8054
parseResponse($headers, $data)
processes SOAP message returned from server
Definition: nusoap.php:7648
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:6518
$root_struct_namespace
Definition: nusoap.php:6526
character_data($parser, $data)
element content handler
Definition: nusoap.php:6919
get_soapbody()
get the parsed SOAP Body (NULL if there was none)
Definition: nusoap.php:6957
end_element($parser, $name)
end-element handler
Definition: nusoap.php:6814
getHeaders()
get the unparsed SOAP Header
Definition: nusoap.php:6979
get_response()
get the parsed message (SOAP Body)
Definition: nusoap.php:6946
decodeSimple($value, $type, $typens)
decodes simple types into PHP variables
Definition: nusoap.php:6993
get_soapheader()
get the parsed SOAP Header (NULL if there was none)
Definition: nusoap.php:6968
start_element($parser, $name, $attrs)
start-element handler
Definition: nusoap.php:6658
buildVal($pos)
builds response structures for compound values (arrays/structs) and scalars
Definition: nusoap.php:7038
__construct($xml, $encoding='UTF-8', $method='', $decode_utf8=true)
constructor that actually does the parsing
Definition: nusoap.php:6564
nusoap_server allows the user to create a SOAP server that is capable of receiving messages and retur...
Definition: nusoap.php:3478
verify_method($operation, $request)
takes the value that was created by parsing the request and compares to the method's signature,...
Definition: nusoap.php:4260
$methodreturnisliteralxml
Definition: nusoap.php:3589
getHTTPBody($soapmsg)
gets the HTTP body for the current response.
Definition: nusoap.php:4332
invoke_method()
invokes a PHP function for the requested SOAP method
Definition: nusoap.php:3941
add_to_map($methodname, $in, $out)
add a method to the dispatch map (this has been replaced by the register method)
Definition: nusoap.php:4373
getHTTPContentType()
gets the HTTP content type for the current response.
Definition: nusoap.php:4345
__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:3637
addInternalPort(string $serviceName, string $url)
Definition: nusoap.php:4553
parse_request($data='')
parses a request
Definition: nusoap.php:3893
getHTTPContentTypeCharset()
gets the HTTP content type charset for the current response.
Definition: nusoap.php:4359
serialize_return()
serializes the return value from a PHP function into a full SOAP Envelope
Definition: nusoap.php:4087
send_response()
sends an HTTP response
Definition: nusoap.php:4180
fault($faultcode, $faultstring, $faultactor='', $faultdetail='')
Specify a fault to be returned to the client.
Definition: nusoap.php:4462
parse_http_headers()
parses HTTP request headers.
Definition: nusoap.php:3764
service($data)
processes request and returns response
Definition: nusoap.php:3701
parseRequest($headers, $data)
processes SOAP message received from client
Definition: nusoap.php:4280
configureWSDL($serviceName, $namespace=false, $endpoint=false, $style='rpc', $transport='http://schemas.xmlsoap.org/soap/http', $schemaTargetNamespace=false)
Sets up wsdl object.
Definition: nusoap.php:4482
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:1582
getTypeDef($type)
returns an associative array of information about a given type returns false if no type exists by the...
Definition: nusoap.php:1762
addComplexType($name, $typeClass='complexType', $phpType='array', $compositor='', $restrictionBase='', $elements=array(), $attrs=array(), $arrayType='')
adds a complex type to the schema
Definition: nusoap.php:1949
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:1876
addElement($attrs)
adds an element to the schema
Definition: nusoap.php:1999
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:1728
xdebug($string)
adds debug data to the clas level debug string
Definition: nusoap.php:1711
addSimpleType($name, $restrictionBase='', $typeClass='simpleType', $phpType='scalar', $enumeration=array())
adds a simple type to the schema
Definition: nusoap.php:1978
serializeSchema()
serialize the schema
Definition: nusoap.php:1593
__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:1544
schemaStartElement($parser, $name, $attrs)
start-element handler
Definition: nusoap.php:1246
serializeTypeDef($type)
returns a sample serialization of a given type, or false if no type by the given name
Definition: nusoap.php:1839
parseFile($xml, $type)
parse an XML file
Definition: nusoap.php:1157
CreateTypeName($ename)
gets a type name for an unnamed type
Definition: nusoap.php:1229
Backward compatibility.
Definition: nusoap.php:1069
Backward compatibility.
Definition: nusoap.php:7151
Backward compatibility.
Definition: nusoap.php:4567
transport class for sending/receiving data via HTTP and HTTPS NOTE: PHP must be compiled with the CUR...
Definition: nusoap.php:2141
sendRequest($data, $cookies=null)
sends the SOAP request via HTTP[S]
Definition: nusoap.php:2888
setCurlOption($option, $value)
sets a cURL option
Definition: nusoap.php:2209
getCookiesForRequest($cookies, $secure=false)
sort out cookies for the current request
Definition: nusoap.php:3422
send($data, $timeout=0, $response_timeout=30, $cookies=null)
sends the SOAP request and gets the SOAP response via HTTP[S]
Definition: nusoap.php:2556
parseCookie($cookie_str)
parse an incoming Cookie into it's parts
Definition: nusoap.php:3355
setURL($url)
sets the URL to which to connect
Definition: nusoap.php:2249
getResponse()
gets the SOAP response via HTTP[S]
Definition: nusoap.php:2946
setContentType($type, $charset=false)
sets the content-type for the SOAP message to be sent
Definition: nusoap.php:3323
unsetHeader($name)
unsets an HTTP header
Definition: nusoap.php:2235
isSkippableCurlHeader(&$data)
Test if the given string starts with a header that is to be skipped.
Definition: nusoap.php:2752
setSOAPAction($soapaction)
set the soapaction value
Definition: nusoap.php:2687
setEncoding($enc='gzip, deflate')
use http encoding
Definition: nusoap.php:2698
usePersistentConnection()
specifies that an HTTP persistent connection should be used
Definition: nusoap.php:3334
setCredentials($username, $password, $authtype='basic', $digestRequest=array(), $certRequest=array())
if authenticating, set user credentials here
Definition: nusoap.php:2612
buildPayload($data, $cookie_str='')
Writes the payload, including HTTP headers, to $this->outgoing_payload.
Definition: nusoap.php:2840
connect($connection_timeout=0, $response_timeout=30)
establish an HTTP connection
Definition: nusoap.php:2313
setHeader($name, $value)
sets an HTTP header
Definition: nusoap.php:2223
io_method()
gets the I/O method to use
Definition: nusoap.php:2294
decodeChunked($buffer, $lb)
decode a string that is encoded w/ "chunked' transfer encoding as defined in RFC2068 19....
Definition: nusoap.php:2782
setProxy($proxyhost, $proxyport, $proxyusername='', $proxypassword='', $proxyauthtype='basic')
set proxy info here
Definition: nusoap.php:2723
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:2597
__construct($url, $curl_options=null, $use_curl=false)
constructor
Definition: nusoap.php:2187
For creating serializable abstractions of native PHP types.
Definition: nusoap.php:2035
serialize($use='encoded')
return serialized value
Definition: nusoap.php:2108
$element_ns
Definition: nusoap.php:2063
__construct($name='soapval', $type=false, $value=-1, $element_ns=false, $type_ns=false, $attributes=false)
constructor
Definition: nusoap.php:2090
decode()
decodes a soapval object into a PHP native type
Definition: nusoap.php:2119
$attributes
Definition: nusoap.php:2077
parses a WSDL file, allows access to it's data, other utility methods.
Definition: nusoap.php:4584
$currentMessage
Definition: nusoap.php:4596
$import
Definition: nusoap.php:4609
$username
Definition: nusoap.php:4625
$ports
Definition: nusoap.php:4602
$proxyhost
Definition: nusoap.php:4616
character_data($parser, $data)
element content handler
Definition: nusoap.php:5118
serializeComplexTypeAttributes($typeDef, $value, $ns, $uqType)
serializes the attributes for a complexType
Definition: nusoap.php:6183
$opData
Definition: nusoap.php:4604
$currentSchema
Definition: nusoap.php:4592
getBindingData($binding)
Definition: nusoap.php:5148
serializeRPCParameters($operation, $direction, $parameters, $bindingType='soap')
serialize PHP values according to a WSDL message definition contrary to the method name,...
Definition: nusoap.php:5706
$currentPortType
Definition: nusoap.php:4599
addElement($attrs)
adds an element to the WSDL types
Definition: nusoap.php:6412
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:5265
$status
Definition: nusoap.php:4605
getOperations($bindingType='soap')
returns an assoc array of operation names => operation data
Definition: nusoap.php:5162
setCredentials($username, $password, $authtype='basic', $certRequest=array())
if authenticating, set user credentials here
Definition: nusoap.php:5138
$serviceName
Definition: nusoap.php:4586
$proxypassword
Definition: nusoap.php:4619
$certRequest
Definition: nusoap.php:4628
getOperationData($operation, $bindingType='soap')
returns an associative array of data necessary for calling an operation
Definition: nusoap.php:5194
$currentPortOperation
Definition: nusoap.php:4588
$portTypes
Definition: nusoap.php:4598
$currentOperation
Definition: nusoap.php:4597
$messages
Definition: nusoap.php:4595
serializeParameters($operation, $direction, $parameters)
serialize a PHP value according to a WSDL message definition
Definition: nusoap.php:5801
fetchWSDL($wsdl)
fetches the WSDL document and parses it
Definition: nusoap.php:4666
$password
Definition: nusoap.php:4626
addSimpleType($name, $restrictionBase='', $typeClass='simpleType', $phpType='scalar', $enumeration=array())
adds an XML Schema simple type to the WSDL types
Definition: nusoap.php:6397
$depth
Definition: nusoap.php:4613
$bindings
Definition: nusoap.php:4600
serialize($debug=0)
serialize the parsed wsdl
Definition: nusoap.php:5464
$wsdl
Definition: nusoap.php:4589
$timeout
Definition: nusoap.php:4620
$endpoint
Definition: nusoap.php:4607
$use_curl
Definition: nusoap.php:4623
$proxyusername
Definition: nusoap.php:4618
getOperationDataForSoapAction($soapAction, $bindingType='soap')
returns an associative array of data necessary for calling an operation
Definition: nusoap.php:5226
$documentation
Definition: nusoap.php:4606
webDescription()
prints html description of services
Definition: nusoap.php:5322
serializeType($name, $type, $value, $use='encoded', $encodingStyle=false, $unqualified=false)
serializes a PHP value according a given type definition
Definition: nusoap.php:5879
parseWSDL($wsdl='')
parses the wsdl document
Definition: nusoap.php:4770
$message
Definition: nusoap.php:4593
parametersMatchWrapped($type, &$parameters)
determine whether a set of parameters are unwrapped when they are expect to be wrapped,...
Definition: nusoap.php:5612
start_element($parser, $name, $attrs)
start-element handler
Definition: nusoap.php:4874
$proxyport
Definition: nusoap.php:4617
$authtype
Definition: nusoap.php:4627
end_element($parser, $name)
end-element handler
Definition: nusoap.php:5087
$parser
Definition: nusoap.php:4611
$depth_array
Definition: nusoap.php:4614
serializeComplexTypeElements($typeDef, $value, $ns, $uqType, $use='encoded', $encodingStyle=false)
serializes the elements for a complexType
Definition: nusoap.php:6246
$position
Definition: nusoap.php:4612
$schemas
Definition: nusoap.php:4591
$currentPort
Definition: nusoap.php:4603
$complexTypes
Definition: nusoap.php:4594
$curl_options
Definition: nusoap.php:4622
__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:4644
$response_timeout
Definition: nusoap.php:4621
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:6349
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:6432
$currentBinding
Definition: nusoap.php:4601
$opStatus
Definition: nusoap.php:4587
$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:91
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:68
$GLOBALS["DIC"]
Definition: wac.php:54
$param
Definition: xapitoken.php:46