ILIAS  release_8 Revision v8.24
nusoap.php
Go to the documentation of this file.
1<?php
2
3/*
4$Id$
5
6NuSOAP - Web Services Toolkit for PHP
7
8Copyright (c) 2002 NuSphere Corporation
9
10This library is free software; you can redistribute it and/or
11modify it under the terms of the GNU Lesser General Public
12License as published by the Free Software Foundation; either
13version 2.1 of the License, or (at your option) any later version.
14
15This library is distributed in the hope that it will be useful,
16but WITHOUT ANY WARRANTY; without even the implied warranty of
17MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18Lesser General Public License for more details.
19
20You should have received a copy of the GNU Lesser General Public
21License along with this library; if not, write to the Free Software
22Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23
24The NuSOAP project home is:
25http://sourceforge.net/projects/nusoap/
26
27The primary support for NuSOAP is the mailing list:
28nusoap-general@lists.sourceforge.net
29
30If you have any questions or comments, please email:
31
32Dietrich Ayala
33dietrich@ganx4.com
34http://dietrich.ganx4.com/nusoap
35
36NuSphere Corporation
37http://www.nusphere.com
38
39*/
40
41/*
42 * Some of the standards implmented in whole or part by NuSOAP:
43 *
44 * SOAP 1.1 (http://www.w3.org/TR/2000/NOTE-SOAP-20000508/)
45 * WSDL 1.1 (http://www.w3.org/TR/2001/NOTE-wsdl-20010315)
46 * SOAP Messages With Attachments (http://www.w3.org/TR/SOAP-attachments)
47 * XML 1.0 (http://www.w3.org/TR/2006/REC-xml-20060816/)
48 * Namespaces in XML 1.0 (http://www.w3.org/TR/2006/REC-xml-names-20060816/)
49 * XML Schema 1.0 (http://www.w3.org/TR/xmlschema-0/)
50 * RFC 2045 Multipurpose Internet Mail Extensions (MIME) Part One: Format of Internet Message Bodies
51 * RFC 2068 Hypertext Transfer Protocol -- HTTP/1.1
52 * RFC 2617 HTTP Authentication: Basic and Digest Access Authentication
53 */
54
55/* load classes
56
57// necessary classes
58require_once('class.soapclient.php');
59require_once('class.soap_val.php');
60require_once('class.soap_parser.php');
61require_once('class.soap_fault.php');
62
63// transport classes
64require_once('class.soap_transport_http.php');
65
66// optional add-on classes
67require_once('class.xmlschema.php');
68require_once('class.wsdl.php');
69
70// server class
71require_once('class.soap_server.php');*/
72
73// class variable emulation
74// cf. http://www.webkreator.com/php/techniques/php-static-class-variables.html
75
76// alex patch: we need an object here, otherwise we will get a warning in php 5.4
77if (
78 !isset($GLOBALS['_transient']) ||
79 !isset($GLOBALS['_transient']['static']) ||
80 !isset($GLOBALS['_transient']['static']['nusoap_base']) ||
81 !is_object($GLOBALS['_transient']['static']['nusoap_base'])
82) {
83 $GLOBALS['_transient']['static']['nusoap_base'] = new stdClass();
84}
85$GLOBALS['_transient']['static']['nusoap_base']->globalDebugLevel = 0;
86
97{
104 public $title = 'NuSOAP';
111 public $version = '0.7.3';
118 public $revision = '$Revision$';
125 public $error_str = '';
132 public $debug_str = '';
140 public $charencoding = true;
148
155 public $XMLSchemaVersion = 'http://www.w3.org/2001/XMLSchema';
156
163 //var $soap_defencoding = 'ISO-8859-1';
164 public $soap_defencoding = 'UTF-8';
165
174 public $namespaces = array(
175 'SOAP-ENV' => 'http://schemas.xmlsoap.org/soap/envelope/',
176 'xsd' => 'http://www.w3.org/2001/XMLSchema',
177 'xsi' => 'http://www.w3.org/2001/XMLSchema-instance',
178 'SOAP-ENC' => 'http://schemas.xmlsoap.org/soap/encoding/'
179 );
180
187 public $usedNamespaces = array();
188
196 public $typemap = array(
197 'http://www.w3.org/2001/XMLSchema' => array(
198 'string'=>'string','boolean'=>'boolean','float'=>'double','double'=>'double','decimal'=>'double',
199 'duration'=>'','dateTime'=>'string','time'=>'string','date'=>'string','gYearMonth'=>'',
200 'gYear'=>'','gMonthDay'=>'','gDay'=>'','gMonth'=>'','hexBinary'=>'string','base64Binary'=>'string',
201 // abstract "any" types
202 'anyType'=>'string','anySimpleType'=>'string',
203 // derived datatypes
204 'normalizedString'=>'string','token'=>'string','language'=>'','NMTOKEN'=>'','NMTOKENS'=>'','Name'=>'','NCName'=>'','ID'=>'',
205 'IDREF'=>'','IDREFS'=>'','ENTITY'=>'','ENTITIES'=>'','integer'=>'integer','nonPositiveInteger'=>'integer',
206 'negativeInteger'=>'integer','long'=>'integer','int'=>'integer','short'=>'integer','byte'=>'integer','nonNegativeInteger'=>'integer',
207 'unsignedLong'=>'','unsignedInt'=>'','unsignedShort'=>'','unsignedByte'=>'','positiveInteger'=>''),
208 'http://www.w3.org/2000/10/XMLSchema' => array(
209 'i4'=>'','int'=>'integer','boolean'=>'boolean','string'=>'string','double'=>'double',
210 'float'=>'double','dateTime'=>'string',
211 'timeInstant'=>'string','base64Binary'=>'string','base64'=>'string','ur-type'=>'array'),
212 'http://www.w3.org/1999/XMLSchema' => array(
213 'i4'=>'','int'=>'integer','boolean'=>'boolean','string'=>'string','double'=>'double',
214 'float'=>'double','dateTime'=>'string',
215 'timeInstant'=>'string','base64Binary'=>'string','base64'=>'string','ur-type'=>'array'),
216 'http://soapinterop.org/xsd' => array('SOAPStruct'=>'struct'),
217 'http://schemas.xmlsoap.org/soap/encoding/' => array('base64'=>'string','array'=>'array','Array'=>'array'),
218 'http://xml.apache.org/xml-soap' => array('Map')
219 );
220
229 public $xmlEntities = array('quot' => '"','amp' => '&',
230 'lt' => '<','gt' => '>','apos' => "'");
231
237 public function __construct()
238 {
239 $this->debugLevel = $GLOBALS['_transient']['static']['nusoap_base']->globalDebugLevel;
240 }
241
248 public function getGlobalDebugLevel()
249 {
250 return $GLOBALS['_transient']['static']['nusoap_base']->globalDebugLevel;
251 }
252
259 public function setGlobalDebugLevel($level)
260 {
261 $GLOBALS['_transient']['static']['nusoap_base']->globalDebugLevel = $level;
262 }
263
270 public function getDebugLevel()
271 {
272 return $this->debugLevel;
273 }
274
281 public function setDebugLevel($level)
282 {
283 $this->debugLevel = $level;
284 }
285
292 public function debug($string)
293 {
294 if ($this->debugLevel > 0) {
295 $this->appendDebug($this->getmicrotime() . ' ' . get_class($this) . ": $string\n");
296 }
297 }
298
305 public function appendDebug($string)
306 {
307 if ($this->debugLevel > 0) {
308 // it would be nice to use a memory stream here to use
309 // memory more efficiently
310 $this->debug_str .= $string;
311 }
312 }
313
319 public function clearDebug()
320 {
321 // it would be nice to use a memory stream here to use
322 // memory more efficiently
323 $this->debug_str = '';
324 }
325
332 public function &getDebug()
333 {
334 // it would be nice to use a memory stream here to use
335 // memory more efficiently
336 return $this->debug_str;
337 }
338
346 public function &getDebugAsXMLComment()
347 {
348 // it would be nice to use a memory stream here to use
349 // memory more efficiently
350 while (strpos($this->debug_str, '--')) {
351 $this->debug_str = str_replace('--', '- -', $this->debug_str);
352 }
353 $ret = "<!--\n" . $this->debug_str . "\n-->";
354 return $ret;
355 }
356
363 public function expandEntities($val)
364 {
365 if ($this->charencoding) {
366 $val = str_replace('&', '&amp;', $val);
367 $val = str_replace("'", '&apos;', $val);
368 $val = str_replace('"', '&quot;', $val);
369 $val = str_replace('<', '&lt;', $val);
370 $val = str_replace('>', '&gt;', $val);
371 }
372 return $val;
373 }
374
381 public function getError()
382 {
383 if ($this->error_str != '') {
384 return $this->error_str;
385 }
386 return false;
387 }
388
395 public function setError($str)
396 {
397 $this->error_str = $str;
398 }
399
407 public function isArraySimpleOrStruct($val)
408 {
409 $keyList = array_keys($val);
410 foreach ($keyList as $keyListValue) {
411 if (!is_int($keyListValue)) {
412 return 'arrayStruct';
413 }
414 }
415 return 'arraySimple';
416 }
417
433 public function serialize_val($val, $name=false, $type=false, $name_ns=false, $type_ns=false, $attributes=false, $use='encoded', $soapval=false)
434 {
435 $this->debug("in serialize_val: name=$name, type=$type, name_ns=$name_ns, type_ns=$type_ns, use=$use, soapval=$soapval");
436 $this->appendDebug('value=' . $this->varDump($val));
437 $this->appendDebug('attributes=' . $this->varDump($attributes));
438
439 if (is_object($val) && get_class($val) == 'soapval' && (! $soapval)) {
440 $this->debug("serialize_val: serialize soapval");
441 $xml = $val->serialize($use);
442 $this->appendDebug($val->getDebug());
443 $val->clearDebug();
444 $this->debug("serialize_val of soapval returning $xml");
445 return $xml;
446 }
447 // force valid name if necessary
448 if (is_numeric($name)) {
449 $name = '__numeric_' . $name;
450 } elseif (! $name) {
451 $name = 'noname';
452 }
453 // if name has ns, add ns prefix to name
454 $xmlns = '';
455 if ($name_ns) {
456 $prefix = 'nu' . rand(1000, 9999);
457 $name = $prefix . ':' . $name;
458 $xmlns .= " xmlns:$prefix=\"$name_ns\"";
459 }
460 // if type is prefixed, create type prefix
461 if ($type_ns != '' && $type_ns == $this->namespaces['xsd']) {
462 // need to fix this. shouldn't default to xsd if no ns specified
463 // w/o checking against typemap
464 $type_prefix = 'xsd';
465 } elseif ($type_ns) {
466 $type_prefix = 'ns' . rand(1000, 9999);
467 $xmlns .= " xmlns:$type_prefix=\"$type_ns\"";
468 }
469 // serialize attributes if present
470 $atts = '';
471 if ($attributes) {
472 foreach ($attributes as $k => $v) {
473 $atts .= " $k=\"" . $this->expandEntities($v) . '"';
474 }
475 }
476 // serialize null value
477 if (is_null($val)) {
478 $this->debug("serialize_val: serialize null");
479 if ($use == 'literal') {
480 // TODO: depends on minOccurs
481 $xml = "<$name$xmlns$atts/>";
482 $this->debug("serialize_val returning $xml");
483 return $xml;
484 } else {
485 if (isset($type) && isset($type_prefix)) {
486 $type_str = " xsi:type=\"$type_prefix:$type\"";
487 } else {
488 $type_str = '';
489 }
490 $xml = "<$name$xmlns$type_str$atts xsi:nil=\"true\"/>";
491 $this->debug("serialize_val returning $xml");
492 return $xml;
493 }
494 }
495 // serialize if an xsd built-in primitive type
496 if ($type != '' && isset($this->typemap[$this->XMLSchemaVersion][$type])) {
497 $this->debug("serialize_val: serialize xsd built-in primitive type");
498 if (is_bool($val)) {
499 if ($type == 'boolean') {
500 $val = $val ? 'true' : 'false';
501 } elseif (! $val) {
502 $val = 0;
503 }
504 } elseif (is_string($val)) {
505 $val = $this->expandEntities($val);
506 }
507 if ($use == 'literal') {
508 $xml = "<$name$xmlns$atts>$val</$name>";
509 $this->debug("serialize_val returning $xml");
510 return $xml;
511 } else {
512 $xml = "<$name$xmlns xsi:type=\"xsd:$type\"$atts>$val</$name>";
513 $this->debug("serialize_val returning $xml");
514 return $xml;
515 }
516 }
517 // detect type and serialize
518 $xml = '';
519 switch (true) {
520 case (is_bool($val) || $type == 'boolean'):
521 $this->debug("serialize_val: serialize boolean");
522 if ($type == 'boolean') {
523 $val = $val ? 'true' : 'false';
524 } elseif (! $val) {
525 $val = 0;
526 }
527 if ($use == 'literal') {
528 $xml .= "<$name$xmlns$atts>$val</$name>";
529 } else {
530 $xml .= "<$name$xmlns xsi:type=\"xsd:boolean\"$atts>$val</$name>";
531 }
532 break;
533 case (is_int($val) || is_long($val) || $type == 'int'):
534 $this->debug("serialize_val: serialize int");
535 if ($use == 'literal') {
536 $xml .= "<$name$xmlns$atts>$val</$name>";
537 } else {
538 $xml .= "<$name$xmlns xsi:type=\"xsd:int\"$atts>$val</$name>";
539 }
540 break;
541 case (is_float($val)|| is_double($val) || $type == 'float'):
542 $this->debug("serialize_val: serialize float");
543 if ($use == 'literal') {
544 $xml .= "<$name$xmlns$atts>$val</$name>";
545 } else {
546 $xml .= "<$name$xmlns xsi:type=\"xsd:float\"$atts>$val</$name>";
547 }
548 break;
549 case (is_string($val) || $type == 'string'):
550 $this->debug("serialize_val: serialize string");
551 $val = $this->expandEntities($val);
552 if ($use == 'literal') {
553 $xml .= "<$name$xmlns$atts>$val</$name>";
554 } else {
555 $xml .= "<$name$xmlns xsi:type=\"xsd:string\"$atts>$val</$name>";
556 }
557 break;
558 case is_object($val):
559 $this->debug("serialize_val: serialize object");
560 if (get_class($val) == 'soapval') {
561 $this->debug("serialize_val: serialize soapval object");
562 $pXml = $val->serialize($use);
563 $this->appendDebug($val->getDebug());
564 $val->clearDebug();
565 } else {
566 if (! $name) {
567 $name = get_class($val);
568 $this->debug("In serialize_val, used class name $name as element name");
569 } else {
570 $this->debug("In serialize_val, do not override name $name for element name for class " . get_class($val));
571 }
572 foreach (get_object_vars($val) as $k => $v) {
573 $pXml = isset($pXml) ? $pXml . $this->serialize_val($v, $k, false, false, false, false, $use) : $this->serialize_val($v, $k, false, false, false, false, $use);
574 }
575 }
576 if (isset($type) && isset($type_prefix)) {
577 $type_str = " xsi:type=\"$type_prefix:$type\"";
578 } else {
579 $type_str = '';
580 }
581 if ($use == 'literal') {
582 $xml .= "<$name$xmlns$atts>$pXml</$name>";
583 } else {
584 $xml .= "<$name$xmlns$type_str$atts>$pXml</$name>";
585 }
586 break;
587 break;
588 case (is_array($val) || $type):
589 // detect if struct or array
590 $valueType = $this->isArraySimpleOrStruct($val);
591 if ($valueType=='arraySimple' || preg_match('/^ArrayOf/', $type)) {
592 $this->debug("serialize_val: serialize array");
593 $i = 0;
594 if (is_array($val) && count($val)> 0) {
595 foreach ($val as $v) {
596 if (is_object($v) && get_class($v) == 'soapval') {
597 $tt_ns = $v->type_ns;
598 $tt = $v->type;
599 } elseif (is_array($v)) {
600 $tt = $this->isArraySimpleOrStruct($v);
601 } else {
602 $tt = gettype($v);
603 }
604 $array_types[$tt] = 1;
605 // TODO: for literal, the name should be $name
606 $xml .= $this->serialize_val($v, 'item', false, false, false, false, $use);
607 ++$i;
608 }
609 if (count($array_types) > 1) {
610 $array_typename = 'xsd:anyType';
611 } elseif (isset($tt) && isset($this->typemap[$this->XMLSchemaVersion][$tt])) {
612 if ($tt == 'integer') {
613 $tt = 'int';
614 }
615 $array_typename = 'xsd:' . $tt;
616 } elseif (isset($tt) && $tt == 'arraySimple') {
617 $array_typename = 'SOAP-ENC:Array';
618 } elseif (isset($tt) && $tt == 'arrayStruct') {
619 $array_typename = 'unnamed_struct_use_soapval';
620 } else {
621 // if type is prefixed, create type prefix
622 if ($tt_ns != '' && $tt_ns == $this->namespaces['xsd']) {
623 $array_typename = 'xsd:' . $tt;
624 } elseif ($tt_ns) {
625 $tt_prefix = 'ns' . rand(1000, 9999);
626 $array_typename = "$tt_prefix:$tt";
627 $xmlns .= " xmlns:$tt_prefix=\"$tt_ns\"";
628 } else {
629 $array_typename = $tt;
630 }
631 }
632 $array_type = $i;
633 if ($use == 'literal') {
634 $type_str = '';
635 } elseif (isset($type) && isset($type_prefix)) {
636 $type_str = " xsi:type=\"$type_prefix:$type\"";
637 } else {
638 $type_str = " xsi:type=\"SOAP-ENC:Array\" SOAP-ENC:arrayType=\"" . $array_typename . "[$array_type]\"";
639 }
640 // empty array
641 } else {
642 if ($use == 'literal') {
643 $type_str = '';
644 } elseif (isset($type) && isset($type_prefix)) {
645 $type_str = " xsi:type=\"$type_prefix:$type\"";
646 } else {
647 $type_str = " xsi:type=\"SOAP-ENC:Array\" SOAP-ENC:arrayType=\"xsd:anyType[0]\"";
648 }
649 }
650 // TODO: for array in literal, there is no wrapper here
651 $xml = "<$name$xmlns$type_str$atts>" . $xml . "</$name>";
652 } else {
653 // got a struct
654 $this->debug("serialize_val: serialize struct");
655 if (isset($type) && isset($type_prefix)) {
656 $type_str = " xsi:type=\"$type_prefix:$type\"";
657 } else {
658 $type_str = '';
659 }
660 if ($use == 'literal') {
661 $xml .= "<$name$xmlns$atts>";
662 } else {
663 $xml .= "<$name$xmlns$type_str$atts>";
664 }
665 foreach ($val as $k => $v) {
666 // Apache Map
667 if ($type == 'Map' && $type_ns == 'http://xml.apache.org/xml-soap') {
668 $xml .= '<item>';
669 $xml .= $this->serialize_val($k, 'key', false, false, false, false, $use);
670 $xml .= $this->serialize_val($v, 'value', false, false, false, false, $use);
671 $xml .= '</item>';
672 } else {
673 $xml .= $this->serialize_val($v, $k, false, false, false, false, $use);
674 }
675 }
676 $xml .= "</$name>";
677 }
678 break;
679 default:
680 $this->debug("serialize_val: serialize unknown");
681 $xml .= 'not detected, got ' . gettype($val) . ' for ' . $val;
682 break;
683 }
684 $this->debug("serialize_val returning $xml");
685 return $xml;
686 }
687
700 public function serializeEnvelope($body, $headers=false, $namespaces=array(), $style='rpc', $use='encoded', $encodingStyle='http://schemas.xmlsoap.org/soap/encoding/')
701 {
702 // TODO: add an option to automatically run utf8_encode on $body and $headers
703 // if $this->soap_defencoding is UTF-8. Not doing this automatically allows
704 // one to send arbitrary UTF-8 characters, not just characters that map to ISO-8859-1
705
706 $this->debug("In serializeEnvelope length=" . strlen($body) . " body (max 1000 characters)=" . substr($body, 0, 1000) . " style=$style use=$use encodingStyle=$encodingStyle");
707 $this->debug("headers:");
708 $this->appendDebug($this->varDump($headers));
709 $this->debug("namespaces:");
710 $this->appendDebug($this->varDump($namespaces));
711
712 // serialize namespaces
713 $ns_string = '';
714 foreach (array_merge($this->namespaces, $namespaces) as $k => $v) {
715 $ns_string .= " xmlns:$k=\"$v\"";
716 }
717 if ($encodingStyle) {
718 $ns_string = " SOAP-ENV:encodingStyle=\"$encodingStyle\"$ns_string";
719 }
720
721 // serialize headers
722 if ($headers) {
723 if (is_array($headers)) {
724 $xml = '';
725 foreach ($headers as $k => $v) {
726 if (is_object($v) && get_class($v) == 'soapval') {
727 $xml .= $this->serialize_val($v, false, false, false, false, false, $use);
728 } else {
729 $xml .= $this->serialize_val($v, $k, false, false, false, false, $use);
730 }
731 }
732 $headers = $xml;
733 $this->debug("In serializeEnvelope, serialized array of headers to $headers");
734 }
735 $headers = "<SOAP-ENV:Header>" . $headers . "</SOAP-ENV:Header>";
736 }
737 // serialize envelope
738 return
739 '<?xml version="1.0" encoding="' . $this->soap_defencoding . '"?' . ">" .
740 '<SOAP-ENV:Envelope' . $ns_string . ">" .
741 $headers .
742 "<SOAP-ENV:Body>" .
743 $body .
744 "</SOAP-ENV:Body>" .
745 "</SOAP-ENV:Envelope>";
746 }
747
756 public function formatDump($str)
757 {
758 $str = htmlspecialchars($str);
759 return nl2br($str);
760 }
761
769 public function contractQname($qname)
770 {
771 // get element namespace
772 //$this->xdebug("Contract $qname");
773 if (strrpos($qname, ':')) {
774 // get unqualified name
775 $name = substr($qname, strrpos($qname, ':') + 1);
776 // get ns
777 $ns = substr($qname, 0, strrpos($qname, ':'));
778 $p = $this->getPrefixFromNamespace($ns);
779 if ($p) {
780 return $p . ':' . $name;
781 }
782 return $qname;
783 } else {
784 return $qname;
785 }
786 }
787
795 public function expandQname($qname)
796 {
797 // get element prefix
798 if (strpos($qname, ':') && !preg_match('/^http:\/\//', $qname)) {
799 // get unqualified name
800 $name = substr(strstr($qname, ':'), 1);
801 // get ns prefix
802 $prefix = substr($qname, 0, strpos($qname, ':'));
803 if (isset($this->namespaces[$prefix])) {
804 return $this->namespaces[$prefix] . ':' . $name;
805 } else {
806 return $qname;
807 }
808 } else {
809 return $qname;
810 }
811 }
812
821 public function getLocalPart($str)
822 {
823 if ($sstr = strrchr($str, ':')) {
824 // get unqualified name
825 return substr($sstr, 1);
826 } else {
827 return $str;
828 }
829 }
830
839 public function getPrefix($str)
840 {
841 if ($pos = strrpos($str, ':')) {
842 // get prefix
843 return substr($str, 0, $pos);
844 }
845 return false;
846 }
847
855 public function getNamespaceFromPrefix($prefix)
856 {
857 if (isset($this->namespaces[$prefix])) {
858 return $this->namespaces[$prefix];
859 }
860 //$this->setError("No namespace registered for prefix '$prefix'");
861 return false;
862 }
863
872 public function getPrefixFromNamespace($ns)
873 {
874 foreach ($this->namespaces as $p => $n) {
875 if ($ns == $n || $ns == $p) {
876 $this->usedNamespaces[$p] = $n;
877 return $p;
878 }
879 }
880 return false;
881 }
882
889 public function getmicrotime()
890 {
891 if (function_exists('gettimeofday')) {
892 $tod = gettimeofday();
893 $sec = $tod['sec'];
894 $usec = $tod['usec'];
895 } else {
896 $sec = time();
897 $usec = 0;
898 }
899 return strftime('%Y-%m-%d %H:%M:%S', $sec) . '.' . sprintf('%06d', $usec);
900 }
901
909 public function varDump($data)
910 {
911 ob_start();
912 var_dump($data);
913 $ret_val = ob_get_contents();
914 ob_end_clean();
915 return $ret_val;
916 }
917
924 public function __toString()
925 {
926 return $this->varDump($this);
927 }
928}
929
930// XML Schema Datatype Helper Functions
931
932//xsd:dateTime helpers
933
942{
943 $datestr = date('Y-m-d\TH:i:sO', $timestamp);
944 if ($utc) {
945 $pattern = '/' .
946 '([0-9]{4})-' . // centuries & years CCYY-
947 '([0-9]{2})-' . // months MM-
948 '([0-9]{2})' . // days DD
949 'T' . // separator T
950 '([0-9]{2}):' . // hours hh:
951 '([0-9]{2}):' . // minutes mm:
952 '([0-9]{2})(\.[0-9]*)?' . // seconds ss.ss...
953 '(Z|[+\-][0-9]{2}:?[0-9]{2})?' . // Z to indicate UTC, -/+HH:MM:SS.SS... for local tz's
954 '/';
955
956 if (preg_match($pattern, $datestr, $regs)) {
957 return sprintf('%04d-%02d-%02dT%02d:%02d:%02dZ', $regs[1], $regs[2], $regs[3], $regs[4], $regs[5], $regs[6]);
958 }
959 return false;
960 } else {
961 return $datestr;
962 }
963}
964
971function iso8601_to_timestamp($datestr)
972{
973 $pattern = '/' .
974 '([0-9]{4})-' . // centuries & years CCYY-
975 '([0-9]{2})-' . // months MM-
976 '([0-9]{2})' . // days DD
977 'T' . // separator T
978 '([0-9]{2}):' . // hours hh:
979 '([0-9]{2}):' . // minutes mm:
980 '([0-9]{2})(\.[0-9]+)?' . // seconds ss.ss...
981 '(Z|[+\-][0-9]{2}:?[0-9]{2})?' . // Z to indicate UTC, -/+HH:MM:SS.SS... for local tz's
982 '/';
983
984 if (preg_match($pattern, $datestr, $regs)) {
985 // not utc
986 if ($regs[8] != 'Z') {
987 $op = substr($regs[8], 0, 1);
988 $h = substr($regs[8], 1, 2);
989 $m = substr($regs[8], strlen($regs[8])-2, 2);
990 if ($op == '-') {
991 $regs[4] = $regs[4] + $h;
992 $regs[5] = $regs[5] + $m;
993 } elseif ($op == '+') {
994 $regs[4] = $regs[4] - $h;
995 $regs[5] = $regs[5] - $m;
996 }
997 }
998 return gmmktime($regs[4], $regs[5], $regs[6], $regs[2], $regs[3], $regs[1]);
999 // return strtotime("$regs[1]-$regs[2]-$regs[3] $regs[4]:$regs[5]:$regs[6]Z");
1000 } else {
1001 return false;
1002 }
1003}
1004
1012function usleepWindows($usec)
1013{
1014 $start = gettimeofday();
1015
1016 do {
1017 $stop = gettimeofday();
1018 $timePassed = 1000000 * ($stop['sec'] - $start['sec'])
1019 + $stop['usec'] - $start['usec'];
1020 } while ($timePassed < $usec);
1021}
1022
1023?><?php
1024
1025
1026
1036{
1061
1071 {
1073 $this->faultcode = $faultcode;
1074 $this->faultactor = $faultactor;
1075 $this->faultstring = $faultstring;
1076 $this->faultdetail = $faultdetail;
1077 }
1078
1085 public function serialize()
1086 {
1087 $ns_string = '';
1088 foreach ($this->namespaces as $k => $v) {
1089 $ns_string .= "\n xmlns:$k=\"$v\"";
1090 }
1091 $return_msg =
1092 '<?xml version="1.0" encoding="' . $this->soap_defencoding . '"?>' .
1093 '<SOAP-ENV:Envelope SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"' . $ns_string . ">\n" .
1094 '<SOAP-ENV:Body>' .
1095 '<SOAP-ENV:Fault>' .
1096 $this->serialize_val($this->faultcode, 'faultcode') .
1097 $this->serialize_val($this->faultstring, 'faultstring') .
1098 $this->serialize_val($this->faultactor, 'faultactor') .
1099 $this->serialize_val($this->faultdetail, 'detail') .
1100 '</SOAP-ENV:Fault>' .
1101 '</SOAP-ENV:Body>' .
1102 '</SOAP-ENV:Envelope>';
1103 return $return_msg;
1104 }
1105}
1106
1111{
1112}
1113
1114?><?php
1115
1116
1117
1128{
1129 // files
1130 public $schema = '';
1131 public $xml = '';
1132 // namespaces
1134 // schema info
1135 public $schemaInfo = array();
1137 // types, elements, attributes defined by the schema
1138 public $attributes = array();
1139 public $complexTypes = array();
1140 public $complexTypeStack = array();
1141 public $currentComplexType = null;
1142 public $elements = array();
1143 public $elementStack = array();
1144 public $currentElement = null;
1145 public $simpleTypes = array();
1146 public $simpleTypeStack = array();
1147 public $currentSimpleType = null;
1148 // imports
1149 public $imports = array();
1150 // parser vars
1151 public $parser;
1152 public $position = 0;
1153 public $depth = 0;
1154 public $depth_array = array();
1155 public $message = array();
1156 public $defaultNamespace = array();
1157
1166 public function __construct($schema='', $xml='', $namespaces=array())
1167 {
1169 $this->debug('nusoap_xmlschema class instantiated, inside constructor');
1170 // files
1171 $this->schema = $schema;
1172 $this->xml = $xml;
1173
1174 // namespaces
1175 $this->enclosingNamespaces = $namespaces;
1176 $this->namespaces = array_merge($this->namespaces, $namespaces);
1177
1178 // parse schema file
1179 if ($schema != '') {
1180 $this->debug('initial schema file: ' . $schema);
1181 $this->parseFile($schema, 'schema');
1182 }
1183
1184 // parse xml file
1185 if ($xml != '') {
1186 $this->debug('initial xml file: ' . $xml);
1187 $this->parseFile($xml, 'xml');
1188 }
1189 }
1190
1199 public function parseFile($xml, $type)
1200 {
1201 // parse xml file
1202 if ($xml != "") {
1203 $xmlStr = @join("", @file($xml));
1204 if ($xmlStr == "") {
1205 $msg = 'Error reading XML from ' . $xml;
1206 $this->setError($msg);
1207 $this->debug($msg);
1208 return false;
1209 } else {
1210 $this->debug("parsing $xml");
1211 $this->parseString($xmlStr, $type);
1212 $this->debug("done parsing $xml");
1213 return true;
1214 }
1215 }
1216 return false;
1217 }
1218
1226 public function parseString($xml, $type)
1227 {
1228 // parse xml string
1229 if ($xml != "") {
1230
1231 // Create an XML parser.
1232 $this->parser = xml_parser_create();
1233 // Set the options for parsing the XML data.
1234 xml_parser_set_option($this->parser, XML_OPTION_CASE_FOLDING, 0);
1235
1236 // Set the object for the parser.
1237 xml_set_object($this->parser, $this);
1238
1239 // Set the element handlers for the parser.
1240 if ($type == "schema") {
1241 xml_set_element_handler($this->parser, 'schemaStartElement', 'schemaEndElement');
1242 xml_set_character_data_handler($this->parser, 'schemaCharacterData');
1243 } elseif ($type == "xml") {
1244 xml_set_element_handler($this->parser, 'xmlStartElement', 'xmlEndElement');
1245 xml_set_character_data_handler($this->parser, 'xmlCharacterData');
1246 }
1247
1248 // Parse the XML file.
1249 if (!xml_parse($this->parser, $xml, true)) {
1250 // Display an error message.
1251 $errstr = sprintf(
1252 'XML error parsing XML schema on line %d: %s',
1253 xml_get_current_line_number($this->parser),
1254 xml_error_string(xml_get_error_code($this->parser))
1255 );
1256 $this->debug($errstr);
1257 $this->debug("XML payload:\n" . $xml);
1258 $this->setError($errstr);
1259 }
1260
1261 xml_parser_free($this->parser);
1262 } else {
1263 $this->debug('no xml passed to parseString()!!');
1264 $this->setError('no xml passed to parseString()!!');
1265 }
1266 }
1267
1275 public function CreateTypeName($ename)
1276 {
1277 $scope = '';
1278 for ($i = 0; $i < count($this->complexTypeStack); $i++) {
1279 $scope .= $this->complexTypeStack[$i] . '_';
1280 }
1281 return $scope . $ename . '_ContainedType';
1282 }
1283
1292 public function schemaStartElement($parser, $name, $attrs)
1293 {
1294
1295 // position in the total number of elements, starting from 0
1296 $pos = $this->position++;
1297 $depth = $this->depth++;
1298 // set self as current value for this depth
1299 $this->depth_array[$depth] = $pos;
1300 $this->message[$pos] = array('cdata' => '');
1301 if ($depth > 0) {
1302 $this->defaultNamespace[$pos] = $this->defaultNamespace[$this->depth_array[$depth - 1]];
1303 } else {
1304 $this->defaultNamespace[$pos] = false;
1305 }
1306
1307 // get element prefix
1308 if ($prefix = $this->getPrefix($name)) {
1309 // get unqualified name
1310 $name = $this->getLocalPart($name);
1311 } else {
1312 $prefix = '';
1313 }
1314
1315 // loop thru attributes, expanding, and registering namespace declarations
1316 if (count($attrs) > 0) {
1317 foreach ($attrs as $k => $v) {
1318 // if ns declarations, add to class level array of valid namespaces
1319 if (preg_match('/^xmlns/', $k)) {
1320 //$this->xdebug("$k: $v");
1321 //$this->xdebug('ns_prefix: '.$this->getPrefix($k));
1322 if ($ns_prefix = substr(strrchr($k, ':'), 1)) {
1323 //$this->xdebug("Add namespace[$ns_prefix] = $v");
1324 $this->namespaces[$ns_prefix] = $v;
1325 } else {
1326 $this->defaultNamespace[$pos] = $v;
1327 if (! $this->getPrefixFromNamespace($v)) {
1328 $this->namespaces['ns' . (count($this->namespaces)+1)] = $v;
1329 }
1330 }
1331 if ($v == 'http://www.w3.org/2001/XMLSchema' || $v == 'http://www.w3.org/1999/XMLSchema' || $v == 'http://www.w3.org/2000/10/XMLSchema') {
1332 $this->XMLSchemaVersion = $v;
1333 $this->namespaces['xsi'] = $v . '-instance';
1334 }
1335 }
1336 }
1337 foreach ($attrs as $k => $v) {
1338 // expand each attribute
1339 $k = strpos($k, ':') ? $this->expandQname($k) : $k;
1340 $v = strpos($v, ':') ? $this->expandQname($v) : $v;
1341 $eAttrs[$k] = $v;
1342 }
1343 $attrs = $eAttrs;
1344 } else {
1345 $attrs = array();
1346 }
1347 // find status, register data
1348 switch ($name) {
1349 case 'all': // (optional) compositor content for a complexType
1350 case 'choice':
1351 case 'group':
1352 case 'sequence':
1353 //$this->xdebug("compositor $name for currentComplexType: $this->currentComplexType and currentElement: $this->currentElement");
1354 $this->complexTypes[$this->currentComplexType]['compositor'] = $name;
1355 //if($name == 'all' || $name == 'sequence'){
1356 // $this->complexTypes[$this->currentComplexType]['phpType'] = 'struct';
1357 //}
1358 break;
1359 case 'attribute': // complexType attribute
1360 //$this->xdebug("parsing attribute $attrs[name] $attrs[ref] of value: ".$attrs['http://schemas.xmlsoap.org/wsdl/:arrayType']);
1361 $this->xdebug("parsing attribute:");
1362 $this->appendDebug($this->varDump($attrs));
1363 if (!isset($attrs['form'])) {
1364 $attrs['form'] = $this->schemaInfo['attributeFormDefault'];
1365 }
1366 if (isset($attrs['http://schemas.xmlsoap.org/wsdl/:arrayType'])) {
1367 $v = $attrs['http://schemas.xmlsoap.org/wsdl/:arrayType'];
1368 if (!strpos($v, ':')) {
1369 // no namespace in arrayType attribute value...
1370 if ($this->defaultNamespace[$pos]) {
1371 // ...so use the default
1372 $attrs['http://schemas.xmlsoap.org/wsdl/:arrayType'] = $this->defaultNamespace[$pos] . ':' . $attrs['http://schemas.xmlsoap.org/wsdl/:arrayType'];
1373 }
1374 }
1375 }
1376 if (isset($attrs['name'])) {
1377 $this->attributes[$attrs['name']] = $attrs;
1378 $aname = $attrs['name'];
1379 } elseif (isset($attrs['ref']) && $attrs['ref'] == 'http://schemas.xmlsoap.org/soap/encoding/:arrayType') {
1380 if (isset($attrs['http://schemas.xmlsoap.org/wsdl/:arrayType'])) {
1381 $aname = $attrs['http://schemas.xmlsoap.org/wsdl/:arrayType'];
1382 } else {
1383 $aname = '';
1384 }
1385 } elseif (isset($attrs['ref'])) {
1386 $aname = $attrs['ref'];
1387 $this->attributes[$attrs['ref']] = $attrs;
1388 }
1389
1390 if ($this->currentComplexType) { // This should *always* be
1391 $this->complexTypes[$this->currentComplexType]['attrs'][$aname] = $attrs;
1392 }
1393 // arrayType attribute
1394 if (isset($attrs['http://schemas.xmlsoap.org/wsdl/:arrayType']) || $this->getLocalPart($aname) == 'arrayType') {
1395 $this->complexTypes[$this->currentComplexType]['phpType'] = 'array';
1396 $prefix = $this->getPrefix($aname);
1397 if (isset($attrs['http://schemas.xmlsoap.org/wsdl/:arrayType'])) {
1398 $v = $attrs['http://schemas.xmlsoap.org/wsdl/:arrayType'];
1399 } else {
1400 $v = '';
1401 }
1402 if (strpos($v, '[,]')) {
1403 $this->complexTypes[$this->currentComplexType]['multidimensional'] = true;
1404 }
1405 $v = substr($v, 0, strpos($v, '[')); // clip the []
1406 if (!strpos($v, ':') && isset($this->typemap[$this->XMLSchemaVersion][$v])) {
1407 $v = $this->XMLSchemaVersion . ':' . $v;
1408 }
1409 $this->complexTypes[$this->currentComplexType]['arrayType'] = $v;
1410 }
1411 break;
1412 case 'complexContent': // (optional) content for a complexType
1413 break;
1414 case 'complexType':
1415 array_push($this->complexTypeStack, $this->currentComplexType);
1416 if (isset($attrs['name'])) {
1417 // TODO: what is the scope of named complexTypes that appear
1418 // nested within other c complexTypes?
1419 $this->xdebug('processing named complexType ' . $attrs['name']);
1420 //$this->currentElement = false;
1421 $this->currentComplexType = $attrs['name'];
1422 $this->complexTypes[$this->currentComplexType] = $attrs;
1423 $this->complexTypes[$this->currentComplexType]['typeClass'] = 'complexType';
1424 // This is for constructs like
1425 // <complexType name="ListOfString" base="soap:Array">
1426 // <sequence>
1427 // <element name="string" type="xsd:string"
1428 // minOccurs="0" maxOccurs="unbounded" />
1429 // </sequence>
1430 // </complexType>
1431 if (isset($attrs['base']) && preg_match('/:Array$/', $attrs['base'])) {
1432 $this->xdebug('complexType is unusual array');
1433 $this->complexTypes[$this->currentComplexType]['phpType'] = 'array';
1434 } else {
1435 $this->complexTypes[$this->currentComplexType]['phpType'] = 'struct';
1436 }
1437 } else {
1438 $name = $this->CreateTypeName($this->currentElement);
1439 $this->xdebug('processing unnamed complexType for element ' . $this->currentElement . ' named ' . $name);
1440 $this->currentComplexType = $name;
1441 //$this->currentElement = false;
1442 $this->complexTypes[$this->currentComplexType] = $attrs;
1443 $this->complexTypes[$this->currentComplexType]['typeClass'] = 'complexType';
1444 // This is for constructs like
1445 // <complexType name="ListOfString" base="soap:Array">
1446 // <sequence>
1447 // <element name="string" type="xsd:string"
1448 // minOccurs="0" maxOccurs="unbounded" />
1449 // </sequence>
1450 // </complexType>
1451 if (isset($attrs['base']) && preg_match('/:Array$/', $attrs['base'])) {
1452 $this->xdebug('complexType is unusual array');
1453 $this->complexTypes[$this->currentComplexType]['phpType'] = 'array';
1454 } else {
1455 $this->complexTypes[$this->currentComplexType]['phpType'] = 'struct';
1456 }
1457 }
1458 break;
1459 case 'element':
1460 array_push($this->elementStack, $this->currentElement);
1461 if (!isset($attrs['form'])) {
1462 $attrs['form'] = $this->schemaInfo['elementFormDefault'];
1463 }
1464 if (isset($attrs['type'])) {
1465 $this->xdebug("processing typed element " . $attrs['name'] . " of type " . $attrs['type']);
1466 if (! $this->getPrefix($attrs['type'])) {
1467 if ($this->defaultNamespace[$pos]) {
1468 $attrs['type'] = $this->defaultNamespace[$pos] . ':' . $attrs['type'];
1469 $this->xdebug('used default namespace to make type ' . $attrs['type']);
1470 }
1471 }
1472 // This is for constructs like
1473 // <complexType name="ListOfString" base="soap:Array">
1474 // <sequence>
1475 // <element name="string" type="xsd:string"
1476 // minOccurs="0" maxOccurs="unbounded" />
1477 // </sequence>
1478 // </complexType>
1479 if ($this->currentComplexType && $this->complexTypes[$this->currentComplexType]['phpType'] == 'array') {
1480 $this->xdebug('arrayType for unusual array is ' . $attrs['type']);
1481 $this->complexTypes[$this->currentComplexType]['arrayType'] = $attrs['type'];
1482 }
1483 $this->currentElement = $attrs['name'];
1484 $ename = $attrs['name'];
1485 } elseif (isset($attrs['ref'])) {
1486 $this->xdebug("processing element as ref to " . $attrs['ref']);
1487 $this->currentElement = "ref to " . $attrs['ref'];
1488 $ename = $this->getLocalPart($attrs['ref']);
1489 } else {
1490 $type = $this->CreateTypeName($this->currentComplexType . '_' . $attrs['name']);
1491 $this->xdebug("processing untyped element " . $attrs['name'] . ' type ' . $type);
1492 $this->currentElement = $attrs['name'];
1493 $attrs['type'] = $this->schemaTargetNamespace . ':' . $type;
1494 $ename = $attrs['name'];
1495 }
1496 if (isset($ename) && $this->currentComplexType) {
1497 $this->xdebug("add element $ename to complexType $this->currentComplexType");
1498 $this->complexTypes[$this->currentComplexType]['elements'][$ename] = $attrs;
1499 } elseif (!isset($attrs['ref'])) {
1500 $this->xdebug("add element $ename to elements array");
1501 $this->elements[ $attrs['name'] ] = $attrs;
1502 $this->elements[ $attrs['name'] ]['typeClass'] = 'element';
1503 }
1504 break;
1505 case 'enumeration': // restriction value list member
1506 $this->xdebug('enumeration ' . $attrs['value']);
1507 if ($this->currentSimpleType) {
1508 $this->simpleTypes[$this->currentSimpleType]['enumeration'][] = $attrs['value'];
1509 } elseif ($this->currentComplexType) {
1510 $this->complexTypes[$this->currentComplexType]['enumeration'][] = $attrs['value'];
1511 }
1512 break;
1513 case 'extension': // simpleContent or complexContent type extension
1514 $this->xdebug('extension ' . $attrs['base']);
1515 if ($this->currentComplexType) {
1516 $this->complexTypes[$this->currentComplexType]['extensionBase'] = $attrs['base'];
1517 }
1518 break;
1519 case 'import':
1520 if (isset($attrs['schemaLocation'])) {
1521 //$this->xdebug('import namespace ' . $attrs['namespace'] . ' from ' . $attrs['schemaLocation']);
1522 $this->imports[$attrs['namespace']][] = array('location' => $attrs['schemaLocation'], 'loaded' => false);
1523 } else {
1524 //$this->xdebug('import namespace ' . $attrs['namespace']);
1525 $this->imports[$attrs['namespace']][] = array('location' => '', 'loaded' => true);
1526 if (! $this->getPrefixFromNamespace($attrs['namespace'])) {
1527 $this->namespaces['ns' . (count($this->namespaces)+1)] = $attrs['namespace'];
1528 }
1529 }
1530 break;
1531 case 'list': // simpleType value list
1532 break;
1533 case 'restriction': // simpleType, simpleContent or complexContent value restriction
1534 $this->xdebug('restriction ' . $attrs['base']);
1535 if ($this->currentSimpleType) {
1536 $this->simpleTypes[$this->currentSimpleType]['type'] = $attrs['base'];
1537 } elseif ($this->currentComplexType) {
1538 $this->complexTypes[$this->currentComplexType]['restrictionBase'] = $attrs['base'];
1539 if (strstr($attrs['base'], ':') == ':Array') {
1540 $this->complexTypes[$this->currentComplexType]['phpType'] = 'array';
1541 }
1542 }
1543 break;
1544 case 'schema':
1545 $this->schemaInfo = $attrs;
1546 $this->schemaInfo['schemaVersion'] = $this->getNamespaceFromPrefix($prefix);
1547 if (isset($attrs['targetNamespace'])) {
1548 $this->schemaTargetNamespace = $attrs['targetNamespace'];
1549 }
1550 if (!isset($attrs['elementFormDefault'])) {
1551 $this->schemaInfo['elementFormDefault'] = 'unqualified';
1552 }
1553 if (!isset($attrs['attributeFormDefault'])) {
1554 $this->schemaInfo['attributeFormDefault'] = 'unqualified';
1555 }
1556 break;
1557 case 'simpleContent': // (optional) content for a complexType
1558 break;
1559 case 'simpleType':
1560 array_push($this->simpleTypeStack, $this->currentSimpleType);
1561 if (isset($attrs['name'])) {
1562 $this->xdebug("processing simpleType for name " . $attrs['name']);
1563 $this->currentSimpleType = $attrs['name'];
1564 $this->simpleTypes[ $attrs['name'] ] = $attrs;
1565 $this->simpleTypes[ $attrs['name'] ]['typeClass'] = 'simpleType';
1566 $this->simpleTypes[ $attrs['name'] ]['phpType'] = 'scalar';
1567 } else {
1568 $name = $this->CreateTypeName($this->currentComplexType . '_' . $this->currentElement);
1569 $this->xdebug('processing unnamed simpleType for element ' . $this->currentElement . ' named ' . $name);
1570 $this->currentSimpleType = $name;
1571 //$this->currentElement = false;
1572 $this->simpleTypes[$this->currentSimpleType] = $attrs;
1573 $this->simpleTypes[$this->currentSimpleType]['phpType'] = 'scalar';
1574 }
1575 break;
1576 case 'union': // simpleType type list
1577 break;
1578 default:
1579 //$this->xdebug("do not have anything to do for element $name");
1580 }
1581 }
1582
1591 {
1592 // bring depth down a notch
1593 $this->depth--;
1594 // position of current element is equal to the last value left in depth_array for my depth
1595 if (isset($this->depth_array[$this->depth])) {
1596 $pos = $this->depth_array[$this->depth];
1597 }
1598 // get element prefix
1599 if ($prefix = $this->getPrefix($name)) {
1600 // get unqualified name
1601 $name = $this->getLocalPart($name);
1602 } else {
1603 $prefix = '';
1604 }
1605 // move on...
1606 if ($name == 'complexType') {
1607 $this->xdebug('done processing complexType ' . ($this->currentComplexType ? $this->currentComplexType : '(unknown)'));
1608 $this->currentComplexType = array_pop($this->complexTypeStack);
1609 //$this->currentElement = false;
1610 }
1611 if ($name == 'element') {
1612 $this->xdebug('done processing element ' . ($this->currentElement ? $this->currentElement : '(unknown)'));
1613 $this->currentElement = array_pop($this->elementStack);
1614 }
1615 if ($name == 'simpleType') {
1616 $this->xdebug('done processing simpleType ' . ($this->currentSimpleType ? $this->currentSimpleType : '(unknown)'));
1617 $this->currentSimpleType = array_pop($this->simpleTypeStack);
1618 }
1619 }
1620
1629 {
1630 $pos = $this->depth_array[$this->depth - 1];
1631 $this->message[$pos]['cdata'] .= $data;
1632 }
1633
1639 public function serializeSchema()
1640 {
1641 $schemaPrefix = $this->getPrefixFromNamespace($this->XMLSchemaVersion);
1642 $xml = '';
1643 // imports
1644 if (sizeof($this->imports) > 0) {
1645 foreach ($this->imports as $ns => $list) {
1646 foreach ($list as $ii) {
1647 if ($ii['location'] != '') {
1648 $xml .= " <$schemaPrefix:import location=\"" . $ii['location'] . '" namespace="' . $ns . "\" />\n";
1649 } else {
1650 $xml .= " <$schemaPrefix:import namespace=\"" . $ns . "\" />\n";
1651 }
1652 }
1653 }
1654 }
1655 // complex types
1656 foreach ($this->complexTypes as $typeName => $attrs) {
1657 $contentStr = '';
1658 // serialize child elements
1659 if (isset($attrs['elements']) && (count($attrs['elements']) > 0)) {
1660 foreach ($attrs['elements'] as $element => $eParts) {
1661 if (isset($eParts['ref'])) {
1662 $contentStr .= " <$schemaPrefix:element ref=\"$element\"/>\n";
1663 } else {
1664 $contentStr .= " <$schemaPrefix:element name=\"$element\" type=\"" . $this->contractQName($eParts['type']) . "\"";
1665 foreach ($eParts as $aName => $aValue) {
1666 // handle, e.g., abstract, default, form, minOccurs, maxOccurs, nillable
1667 if ($aName != 'name' && $aName != 'type') {
1668 $contentStr .= " $aName=\"$aValue\"";
1669 }
1670 }
1671 $contentStr .= "/>\n";
1672 }
1673 }
1674 // compositor wraps elements
1675 if (isset($attrs['compositor']) && ($attrs['compositor'] != '')) {
1676 $contentStr = " <$schemaPrefix:$attrs[compositor]>\n" . $contentStr . " </$schemaPrefix:$attrs[compositor]>\n";
1677 }
1678 }
1679 // attributes
1680 if (isset($attrs['attrs']) && (count($attrs['attrs']) >= 1)) {
1681 foreach ($attrs['attrs'] as $attr => $aParts) {
1682 $contentStr .= " <$schemaPrefix:attribute";
1683 foreach ($aParts as $a => $v) {
1684 if ($a == 'ref' || $a == 'type') {
1685 $contentStr .= " $a=\"" . $this->contractQName($v) . '"';
1686 } elseif ($a == 'http://schemas.xmlsoap.org/wsdl/:arrayType') {
1687 $this->usedNamespaces['wsdl'] = $this->namespaces['wsdl'];
1688 $contentStr .= ' wsdl:arrayType="' . $this->contractQName($v) . '"';
1689 } else {
1690 $contentStr .= " $a=\"$v\"";
1691 }
1692 }
1693 $contentStr .= "/>\n";
1694 }
1695 }
1696 // if restriction
1697 if (isset($attrs['restrictionBase']) && $attrs['restrictionBase'] != '') {
1698 $contentStr = " <$schemaPrefix:restriction base=\"" . $this->contractQName($attrs['restrictionBase']) . "\">\n" . $contentStr . " </$schemaPrefix:restriction>\n";
1699 // complex or simple content
1700 if ((isset($attrs['elements']) && count($attrs['elements']) > 0) || (isset($attrs['attrs']) && count($attrs['attrs']) > 0)) {
1701 $contentStr = " <$schemaPrefix:complexContent>\n" . $contentStr . " </$schemaPrefix:complexContent>\n";
1702 }
1703 }
1704 // finalize complex type
1705 if ($contentStr != '') {
1706 $contentStr = " <$schemaPrefix:complexType name=\"$typeName\">\n" . $contentStr . " </$schemaPrefix:complexType>\n";
1707 } else {
1708 $contentStr = " <$schemaPrefix:complexType name=\"$typeName\"/>\n";
1709 }
1710 $xml .= $contentStr;
1711 }
1712 // simple types
1713 if (isset($this->simpleTypes) && count($this->simpleTypes) > 0) {
1714 foreach ($this->simpleTypes as $typeName => $eParts) {
1715 $xml .= " <$schemaPrefix:simpleType name=\"$typeName\">\n <$schemaPrefix:restriction base=\"" . $this->contractQName($eParts['type']) . "\">\n";
1716 if (isset($eParts['enumeration'])) {
1717 foreach ($eParts['enumeration'] as $e) {
1718 $xml .= " <$schemaPrefix:enumeration value=\"$e\"/>\n";
1719 }
1720 }
1721 $xml .= " </$schemaPrefix:restriction>\n </$schemaPrefix:simpleType>";
1722 }
1723 }
1724 // elements
1725 if (isset($this->elements) && count($this->elements) > 0) {
1726 foreach ($this->elements as $element => $eParts) {
1727 $xml .= " <$schemaPrefix:element name=\"$element\" type=\"" . $this->contractQName($eParts['type']) . "\"/>\n";
1728 }
1729 }
1730 // attributes
1731 if (isset($this->attributes) && count($this->attributes) > 0) {
1732 foreach ($this->attributes as $attr => $aParts) {
1733 $xml .= " <$schemaPrefix:attribute name=\"$attr\" type=\"" . $this->contractQName($aParts['type']) . "\"\n/>";
1734 }
1735 }
1736 // finish 'er up
1737 $attr = '';
1738 foreach ($this->schemaInfo as $k => $v) {
1739 if ($k == 'elementFormDefault' || $k == 'attributeFormDefault') {
1740 $attr .= " $k=\"$v\"";
1741 }
1742 }
1743 $el = "<$schemaPrefix:schema$attr targetNamespace=\"$this->schemaTargetNamespace\"\n";
1744 foreach (array_diff($this->usedNamespaces, $this->enclosingNamespaces) as $nsp => $ns) {
1745 $el .= " xmlns:$nsp=\"$ns\"";
1746 }
1747 $xml = $el . ">\n" . $xml . "</$schemaPrefix:schema>\n";
1748 return $xml;
1749 }
1750
1757 public function xdebug($string)
1758 {
1759 $this->debug('<' . $this->schemaTargetNamespace . '> ' . $string);
1760 }
1761
1774 public function getPHPType($type, $ns)
1775 {
1776 if (isset($this->typemap[$ns][$type])) {
1777 //print "found type '$type' and ns $ns in typemap<br>";
1778 return $this->typemap[$ns][$type];
1779 } elseif (isset($this->complexTypes[$type])) {
1780 //print "getting type '$type' and ns $ns from complexTypes array<br>";
1781 return $this->complexTypes[$type]['phpType'];
1782 }
1783 return false;
1784 }
1785
1808 public function getTypeDef($type)
1809 {
1810 //$this->debug("in getTypeDef for type $type");
1811 if (substr($type, -1) == '^') {
1812 $is_element = 1;
1813 $type = substr($type, 0, -1);
1814 } else {
1815 $is_element = 0;
1816 }
1817
1818 if ((! $is_element) && isset($this->complexTypes[$type])) {
1819 $this->xdebug("in getTypeDef, found complexType $type");
1820 return $this->complexTypes[$type];
1821 } elseif ((! $is_element) && isset($this->simpleTypes[$type])) {
1822 $this->xdebug("in getTypeDef, found simpleType $type");
1823 if (!isset($this->simpleTypes[$type]['phpType'])) {
1824 // get info for type to tack onto the simple type
1825 // TODO: can this ever really apply (i.e. what is a simpleType really?)
1826 $uqType = substr($this->simpleTypes[$type]['type'], strrpos($this->simpleTypes[$type]['type'], ':') + 1);
1827 $ns = substr($this->simpleTypes[$type]['type'], 0, strrpos($this->simpleTypes[$type]['type'], ':'));
1828 $etype = $this->getTypeDef($uqType);
1829 if ($etype) {
1830 $this->xdebug("in getTypeDef, found type for simpleType $type:");
1831 $this->xdebug($this->varDump($etype));
1832 if (isset($etype['phpType'])) {
1833 $this->simpleTypes[$type]['phpType'] = $etype['phpType'];
1834 }
1835 if (isset($etype['elements'])) {
1836 $this->simpleTypes[$type]['elements'] = $etype['elements'];
1837 }
1838 }
1839 }
1840 return $this->simpleTypes[$type];
1841 } elseif (isset($this->elements[$type])) {
1842 $this->xdebug("in getTypeDef, found element $type");
1843 if (!isset($this->elements[$type]['phpType'])) {
1844 // get info for type to tack onto the element
1845 $uqType = substr($this->elements[$type]['type'], strrpos($this->elements[$type]['type'], ':') + 1);
1846 $ns = substr($this->elements[$type]['type'], 0, strrpos($this->elements[$type]['type'], ':'));
1847 $etype = $this->getTypeDef($uqType);
1848 if ($etype) {
1849 $this->xdebug("in getTypeDef, found type for element $type:");
1850 $this->xdebug($this->varDump($etype));
1851 if (isset($etype['phpType'])) {
1852 $this->elements[$type]['phpType'] = $etype['phpType'];
1853 }
1854 if (isset($etype['elements'])) {
1855 $this->elements[$type]['elements'] = $etype['elements'];
1856 }
1857 } elseif ($ns == 'http://www.w3.org/2001/XMLSchema') {
1858 $this->xdebug("in getTypeDef, element $type is an XSD type");
1859 $this->elements[$type]['phpType'] = 'scalar';
1860 }
1861 }
1862 return $this->elements[$type];
1863 } elseif (isset($this->attributes[$type])) {
1864 $this->xdebug("in getTypeDef, found attribute $type");
1865 return $this->attributes[$type];
1866 } elseif (preg_match('/_ContainedType$/', $type)) {
1867 $this->xdebug("in getTypeDef, have an untyped element $type");
1868 $typeDef['typeClass'] = 'simpleType';
1869 $typeDef['phpType'] = 'scalar';
1870 $typeDef['type'] = 'http://www.w3.org/2001/XMLSchema:string';
1871 return $typeDef;
1872 }
1873 $this->xdebug("in getTypeDef, did not find $type");
1874 return false;
1875 }
1876
1885 public function serializeTypeDef($type)
1886 {
1887 //print "in sTD() for type $type<br>";
1888 if ($typeDef = $this->getTypeDef($type)) {
1889 $str .= '<' . $type;
1890 if (is_array($typeDef['attrs'])) {
1891 foreach ($typeDef['attrs'] as $attName => $data) {
1892 $str .= " $attName=\"{type = " . $data['type'] . "}\"";
1893 }
1894 }
1895 $str .= " xmlns=\"" . $this->schema['targetNamespace'] . "\"";
1896 if (count($typeDef['elements']) > 0) {
1897 $str .= ">";
1898 foreach ($typeDef['elements'] as $element => $eData) {
1899 $str .= $this->serializeTypeDef($element);
1900 }
1901 $str .= "</$type>";
1902 } elseif ($typeDef['typeClass'] == 'element') {
1903 $str .= "></$type>";
1904 } else {
1905 $str .= "/>";
1906 }
1907 return $str;
1908 }
1909 return false;
1910 }
1911
1922 public function typeToForm($name, $type)
1923 {
1924 // get typedef
1925 if ($typeDef = $this->getTypeDef($type)) {
1926 // if struct
1927 if ($typeDef['phpType'] == 'struct') {
1928 $buffer .= '<table>';
1929 foreach ($typeDef['elements'] as $child => $childDef) {
1930 $buffer .= "
1931 <tr><td align='right'>$childDef[name] (type: " . $this->getLocalPart($childDef['type']) . "):</td>
1932 <td><input type='text' name='parameters[" . $name . "][$childDef[name]]'></td></tr>";
1933 }
1934 $buffer .= '</table>';
1935 // if array
1936 } elseif ($typeDef['phpType'] == 'array') {
1937 $buffer .= '<table>';
1938 for ($i=0;$i < 3; $i++) {
1939 $buffer .= "
1940 <tr><td align='right'>array item (type: $typeDef[arrayType]):</td>
1941 <td><input type='text' name='parameters[" . $name . "][]'></td></tr>";
1942 }
1943 $buffer .= '</table>';
1944 // if scalar
1945 } else {
1946 $buffer .= "<input type='text' name='parameters[$name]'>";
1947 }
1948 } else {
1949 $buffer .= "<input type='text' name='parameters[$name]'>";
1950 }
1951 return $buffer;
1952 }
1953
1995 public function addComplexType($name, $typeClass='complexType', $phpType='array', $compositor='', $restrictionBase='', $elements=array(), $attrs=array(), $arrayType='')
1996 {
1997 $this->complexTypes[$name] = array(
1998 'name' => $name,
1999 'typeClass' => $typeClass,
2000 'phpType' => $phpType,
2001 'compositor'=> $compositor,
2002 'restrictionBase' => $restrictionBase,
2003 'elements' => $elements,
2004 'attrs' => $attrs,
2005 'arrayType' => $arrayType
2006 );
2007
2008 $this->xdebug("addComplexType $name:");
2009 $this->appendDebug($this->varDump($this->complexTypes[$name]));
2010 }
2011
2024 public function addSimpleType($name, $restrictionBase='', $typeClass='simpleType', $phpType='scalar', $enumeration=array())
2025 {
2026 $this->simpleTypes[$name] = array(
2027 'name' => $name,
2028 'typeClass' => $typeClass,
2029 'phpType' => $phpType,
2030 'type' => $restrictionBase,
2031 'enumeration' => $enumeration
2032 );
2033
2034 $this->xdebug("addSimpleType $name:");
2035 $this->appendDebug($this->varDump($this->simpleTypes[$name]));
2036 }
2037
2045 public function addElement($attrs)
2046 {
2047 if (! $this->getPrefix($attrs['type'])) {
2048 $attrs['type'] = $this->schemaTargetNamespace . ':' . $attrs['type'];
2049 }
2050 $this->elements[ $attrs['name'] ] = $attrs;
2051 $this->elements[ $attrs['name'] ]['typeClass'] = 'element';
2052
2053 $this->xdebug("addElement " . $attrs['name']);
2054 $this->appendDebug($this->varDump($this->elements[ $attrs['name'] ]));
2055 }
2056}
2057
2062{
2063}
2064
2065?><?php
2066
2067
2068
2081{
2088 public $name;
2095 public $type;
2102 public $value;
2116 public $type_ns;
2124
2136 public function __construct($name='soapval', $type=false, $value=-1, $element_ns=false, $type_ns=false, $attributes=false)
2137 {
2139 $this->name = $name;
2140 $this->type = $type;
2141 $this->value = $value;
2142 $this->element_ns = $element_ns;
2143 $this->type_ns = $type_ns;
2144 $this->attributes = $attributes;
2145 }
2146
2154 public function serialize($use='encoded')
2155 {
2156 return $this->serialize_val($this->value, $this->name, $this->type, $this->element_ns, $this->type_ns, $this->attributes, $use, true);
2157 }
2158
2165 public function decode()
2166 {
2167 return $this->value;
2168 }
2169}
2170
2171
2172
2173?><?php
2174
2175
2176
2187{
2188 public $url = '';
2189 public $uri = '';
2190 public $digest_uri = '';
2191 public $scheme = '';
2192 public $host = '';
2193 public $port = '';
2194 public $path = '';
2195 public $request_method = 'POST';
2196 public $protocol_version = '1.0';
2197 public $encoding = '';
2198 public $outgoing_headers = array();
2199 public $incoming_headers = array();
2200 public $incoming_cookies = array();
2203 public $response_status_line; // HTTP response status line
2204 public $useSOAPAction = true;
2206 public $ch = false; // cURL handle
2207 public $ch_options = array(); // cURL custom options
2208 public $use_curl = false; // force cURL use
2209 public $proxy = null; // proxy information (associative array)
2210 public $username = '';
2211 public $password = '';
2212 public $authtype = '';
2213 public $digestRequest = array();
2214 public $certRequest = array(); // keys must be cainfofile (optional), sslcertfile, sslkeyfile, passphrase, certpassword (optional), verifypeer (optional), verifyhost (optional)
2215 // cainfofile: certificate authority file, e.g. '$pathToPemFiles/rootca.pem'
2216 // sslcertfile: SSL certificate file, e.g. '$pathToPemFiles/mycert.pem'
2217 // sslkeyfile: SSL key file, e.g. '$pathToPemFiles/mykey.pem'
2218 // passphrase: SSL key password/passphrase
2219 // certpassword: SSL certificate password
2220 // verifypeer: default is 1
2221 // verifyhost: default is 1
2222
2231 public function __construct($url, $curl_options = null, $use_curl = false)
2232 {
2234 $this->debug("ctor url=$url use_curl=$use_curl curl_options:");
2235 $this->appendDebug($this->varDump($curl_options));
2236 $this->setURL($url);
2237 if (is_array($curl_options)) {
2238 $this->ch_options = $curl_options;
2239 }
2240 $this->use_curl = $use_curl;
2241 preg_match('/\$Revisio' . 'n: ([^ ]+)/', $this->revision, $rev);
2242 // begin-patch php8
2243 $this->setHeader('User-Agent', $this->title . '/' . $this->version . ' (' . ($rev[1] ?? '1.1') . ')');
2244 }
2245
2253 public function setCurlOption($option, $value)
2254 {
2255 $this->debug("setCurlOption option=$option, value=");
2256 $this->appendDebug($this->varDump($value));
2257 curl_setopt($this->ch, $option, $value);
2258 }
2259
2267 public function setHeader($name, $value)
2268 {
2269 $this->outgoing_headers[$name] = $value;
2270 $this->debug("set header $name: $value");
2271 }
2272
2279 public function unsetHeader($name)
2280 {
2281 if (isset($this->outgoing_headers[$name])) {
2282 $this->debug("unset header $name");
2283 unset($this->outgoing_headers[$name]);
2284 }
2285 }
2286
2293 public function setURL($url)
2294 {
2295 $this->url = $url;
2296
2297 $u = parse_url($url);
2298 foreach ($u as $k => $v) {
2299 $this->debug("parsed URL $k = $v");
2300 $this->$k = $v;
2301 }
2302
2303 // add any GET params to path
2304 if (isset($u['query']) && $u['query'] != '') {
2305 $this->path .= '?' . $u['query'];
2306 }
2307
2308 // set default port
2309 if (!isset($u['port'])) {
2310 if ($u['scheme'] == 'https') {
2311 $this->port = 443;
2312 } else {
2313 $this->port = 80;
2314 }
2315 }
2316
2317 $this->uri = $this->path;
2318 $this->digest_uri = $this->uri;
2319
2320 // build headers
2321 if (!isset($u['port'])) {
2322 $this->setHeader('Host', $this->host);
2323 } else {
2324 $this->setHeader('Host', $this->host . ':' . $this->port);
2325 }
2326
2327 if (isset($u['user']) && $u['user'] != '') {
2328 $this->setCredentials(urldecode($u['user']), isset($u['pass']) ? urldecode($u['pass']) : '');
2329 }
2330 }
2331
2338 public function io_method()
2339 {
2340 if ($this->use_curl || ($this->scheme == 'https') || ($this->scheme == 'http' && $this->authtype == 'ntlm') || ($this->scheme == 'http' && is_array($this->proxy) && $this->proxy['authtype'] == 'ntlm')) {
2341 return 'curl';
2342 }
2343 if (($this->scheme == 'http' || $this->scheme == 'ssl') && $this->authtype != 'ntlm' && (!is_array($this->proxy) || $this->proxy['authtype'] != 'ntlm')) {
2344 return 'socket';
2345 }
2346 return 'unknown';
2347 }
2348
2357 public function connect($connection_timeout=0, $response_timeout=30)
2358 {
2359 // For PHP 4.3 with OpenSSL, change https scheme to ssl, then treat like
2360 // "regular" socket.
2361 // TODO: disabled for now because OpenSSL must be *compiled* in (not just
2362 // loaded), and until PHP5 stream_get_wrappers is not available.
2363 // if ($this->scheme == 'https') {
2364 // if (version_compare(phpversion(), '4.3.0') >= 0) {
2365 // if (extension_loaded('openssl')) {
2366 // $this->scheme = 'ssl';
2367 // $this->debug('Using SSL over OpenSSL');
2368 // }
2369 // }
2370 // }
2371 $this->debug("connect connection_timeout $connection_timeout, response_timeout $response_timeout, scheme $this->scheme, host $this->host, port $this->port");
2372 if ($this->io_method() == 'socket') {
2373 if (!is_array($this->proxy)) {
2376 } else {
2377 $host = $this->proxy['host'];
2378 $port = $this->proxy['port'];
2379 }
2380
2381 // use persistent connection
2382 if ($this->persistentConnection && isset($this->fp) && is_resource($this->fp)) {
2383 if (!feof($this->fp)) {
2384 $this->debug('Re-use persistent connection');
2385 return true;
2386 }
2387 fclose($this->fp);
2388 $this->debug('Closed persistent connection at EOF');
2389 }
2390
2391 // munge host if using OpenSSL
2392 if ($this->scheme == 'ssl') {
2393 $host = 'ssl://' . $host;
2394 }
2395 $this->debug('calling fsockopen with host ' . $host . ' connection_timeout ' . $connection_timeout);
2396
2397 // open socket
2398 if ($connection_timeout > 0) {
2399 $this->fp = @fsockopen($host, $this->port, $this->errno, $this->error_str, $connection_timeout);
2400 } else {
2401 $this->fp = @fsockopen($host, $this->port, $this->errno, $this->error_str);
2402 }
2403
2404 // test pointer
2405 if (!$this->fp) {
2406 $msg = 'Couldn\'t open socket connection to server ' . $this->url;
2407 if ($this->errno) {
2408 $msg .= ', Error (' . $this->errno . '): ' . $this->error_str;
2409 } else {
2410 $msg .= ' prior to connect(). This is often a problem looking up the host name.';
2411 }
2412 $this->debug($msg);
2413 $this->setError($msg);
2414 return false;
2415 }
2416
2417 // set response timeout
2418 $this->debug('set response timeout to ' . $response_timeout);
2419 socket_set_timeout($this->fp, $response_timeout);
2420
2421 $this->debug('socket connected');
2422 return true;
2423 } elseif ($this->io_method() == 'curl') {
2424 if (!extension_loaded('curl')) {
2425 // $this->setError('cURL Extension, or OpenSSL extension w/ PHP version >= 4.3 is required for HTTPS');
2426 $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.');
2427 return false;
2428 }
2429 // Avoid warnings when PHP does not have these options
2430 if (defined('CURLOPT_CONNECTIONTIMEOUT')) {
2431 $CURLOPT_CONNECTIONTIMEOUT = CURLOPT_CONNECTIONTIMEOUT;
2432 } else {
2433 $CURLOPT_CONNECTIONTIMEOUT = 78;
2434 }
2435 if (defined('CURLOPT_HTTPAUTH')) {
2436 $CURLOPT_HTTPAUTH = CURLOPT_HTTPAUTH;
2437 } else {
2438 $CURLOPT_HTTPAUTH = 107;
2439 }
2440 if (defined('CURLOPT_PROXYAUTH')) {
2441 $CURLOPT_PROXYAUTH = CURLOPT_PROXYAUTH;
2442 } else {
2443 $CURLOPT_PROXYAUTH = 111;
2444 }
2445 if (defined('CURLAUTH_BASIC')) {
2446 $CURLAUTH_BASIC = CURLAUTH_BASIC;
2447 } else {
2448 $CURLAUTH_BASIC = 1;
2449 }
2450 if (defined('CURLAUTH_DIGEST')) {
2451 $CURLAUTH_DIGEST = CURLAUTH_DIGEST;
2452 } else {
2453 $CURLAUTH_DIGEST = 2;
2454 }
2455 if (defined('CURLAUTH_NTLM')) {
2456 $CURLAUTH_NTLM = CURLAUTH_NTLM;
2457 } else {
2458 $CURLAUTH_NTLM = 8;
2459 }
2460
2461 $this->debug('connect using cURL');
2462 // init CURL
2463 $this->ch = curl_init();
2464 // set url
2465 $hostURL = ($this->port != '') ? "$this->scheme://$this->host:$this->port" : "$this->scheme://$this->host";
2466 // add path
2467 $hostURL .= $this->path;
2468 $this->setCurlOption(CURLOPT_URL, $hostURL);
2469 // follow location headers (re-directs)
2470 if (ini_get('safe_mode') || ini_get('open_basedir')) {
2471 $this->debug('safe_mode or open_basedir set, so do not set CURLOPT_FOLLOWLOCATION');
2472 $this->debug('safe_mode = ');
2473 $this->appendDebug($this->varDump(ini_get('safe_mode')));
2474 $this->debug('open_basedir = ');
2475 $this->appendDebug($this->varDump(ini_get('open_basedir')));
2476 } else {
2477 $this->setCurlOption(CURLOPT_FOLLOWLOCATION, 1);
2478 }
2479 // ask for headers in the response output
2480 $this->setCurlOption(CURLOPT_HEADER, 1);
2481 // ask for the response output as the return value
2482 $this->setCurlOption(CURLOPT_RETURNTRANSFER, 1);
2483 // encode
2484 // We manage this ourselves through headers and encoding
2485 // if(function_exists('gzuncompress')){
2486 // $this->setCurlOption(CURLOPT_ENCODING, 'deflate');
2487 // }
2488 // persistent connection
2489 if ($this->persistentConnection) {
2490 // I believe the following comment is now bogus, having applied to
2491 // the code when it used CURLOPT_CUSTOMREQUEST to send the request.
2492 // The way we send data, we cannot use persistent connections, since
2493 // there will be some "junk" at the end of our request.
2494 //$this->setCurlOption(CURL_HTTP_VERSION_1_1, true);
2495 $this->persistentConnection = false;
2496 $this->setHeader('Connection', 'close');
2497 }
2498 // set timeouts
2499 if ($connection_timeout != 0) {
2500 $this->setCurlOption($CURLOPT_CONNECTIONTIMEOUT, $connection_timeout);
2501 }
2502 if ($response_timeout != 0) {
2503 $this->setCurlOption(CURLOPT_TIMEOUT, $response_timeout);
2504 }
2505
2506 if ($this->scheme == 'https') {
2507 $this->debug('set cURL SSL verify options');
2508 // recent versions of cURL turn on peer/host checking by default,
2509 // while PHP binaries are not compiled with a default location for the
2510 // CA cert bundle, so disable peer/host checking.
2511 //$this->setCurlOption(CURLOPT_CAINFO, 'f:\php-4.3.2-win32\extensions\curl-ca-bundle.crt');
2512 $this->setCurlOption(CURLOPT_SSL_VERIFYPEER, 0);
2513 $this->setCurlOption(CURLOPT_SSL_VERIFYHOST, 0);
2514
2515 // support client certificates (thanks Tobias Boes, Doug Anarino, Eryan Ariobowo)
2516 if ($this->authtype == 'certificate') {
2517 $this->debug('set cURL certificate options');
2518 if (isset($this->certRequest['cainfofile'])) {
2519 $this->setCurlOption(CURLOPT_CAINFO, $this->certRequest['cainfofile']);
2520 }
2521 if (isset($this->certRequest['verifypeer'])) {
2522 $this->setCurlOption(CURLOPT_SSL_VERIFYPEER, $this->certRequest['verifypeer']);
2523 } else {
2524 $this->setCurlOption(CURLOPT_SSL_VERIFYPEER, 1);
2525 }
2526 if (isset($this->certRequest['verifyhost'])) {
2527 $this->setCurlOption(CURLOPT_SSL_VERIFYHOST, $this->certRequest['verifyhost']);
2528 } else {
2529 $this->setCurlOption(CURLOPT_SSL_VERIFYHOST, 1);
2530 }
2531 if (isset($this->certRequest['sslcertfile'])) {
2532 $this->setCurlOption(CURLOPT_SSLCERT, $this->certRequest['sslcertfile']);
2533 }
2534 if (isset($this->certRequest['sslkeyfile'])) {
2535 $this->setCurlOption(CURLOPT_SSLKEY, $this->certRequest['sslkeyfile']);
2536 }
2537 if (isset($this->certRequest['passphrase'])) {
2538 $this->setCurlOption(CURLOPT_SSLKEYPASSWD, $this->certRequest['passphrase']);
2539 }
2540 if (isset($this->certRequest['certpassword'])) {
2541 $this->setCurlOption(CURLOPT_SSLCERTPASSWD, $this->certRequest['certpassword']);
2542 }
2543 }
2544 }
2545 if ($this->authtype && ($this->authtype != 'certificate')) {
2546 if ($this->username) {
2547 $this->debug('set cURL username/password');
2548 $this->setCurlOption(CURLOPT_USERPWD, "$this->username:$this->password");
2549 }
2550 if ($this->authtype == 'basic') {
2551 $this->debug('set cURL for Basic authentication');
2552 $this->setCurlOption($CURLOPT_HTTPAUTH, $CURLAUTH_BASIC);
2553 }
2554 if ($this->authtype == 'digest') {
2555 $this->debug('set cURL for digest authentication');
2556 $this->setCurlOption($CURLOPT_HTTPAUTH, $CURLAUTH_DIGEST);
2557 }
2558 if ($this->authtype == 'ntlm') {
2559 $this->debug('set cURL for NTLM authentication');
2560 $this->setCurlOption($CURLOPT_HTTPAUTH, $CURLAUTH_NTLM);
2561 }
2562 }
2563 if (is_array($this->proxy)) {
2564 $this->debug('set cURL proxy options');
2565 if ($this->proxy['port'] != '') {
2566 $this->setCurlOption(CURLOPT_PROXY, $this->proxy['host'] . ':' . $this->proxy['port']);
2567 } else {
2568 $this->setCurlOption(CURLOPT_PROXY, $this->proxy['host']);
2569 }
2570 if ($this->proxy['username'] || $this->proxy['password']) {
2571 $this->debug('set cURL proxy authentication options');
2572 $this->setCurlOption(CURLOPT_PROXYUSERPWD, $this->proxy['username'] . ':' . $this->proxy['password']);
2573 if ($this->proxy['authtype'] == 'basic') {
2574 $this->setCurlOption($CURLOPT_PROXYAUTH, $CURLAUTH_BASIC);
2575 }
2576 if ($this->proxy['authtype'] == 'ntlm') {
2577 $this->setCurlOption($CURLOPT_PROXYAUTH, $CURLAUTH_NTLM);
2578 }
2579 }
2580 }
2581 $this->debug('cURL connection set up');
2582 return true;
2583 } else {
2584 $this->setError('Unknown scheme ' . $this->scheme);
2585 $this->debug('Unknown scheme ' . $this->scheme);
2586 return false;
2587 }
2588 }
2589
2600 public function send($data, $timeout=0, $response_timeout=30, $cookies=null)
2601 {
2602 $this->debug('entered send() with data of length: ' . strlen($data));
2603
2604 $this->tryagain = true;
2605 $tries = 0;
2606 while ($this->tryagain) {
2607 $this->tryagain = false;
2608 if ($tries++ < 2) {
2609 // make connnection
2610 if (!$this->connect($timeout, $response_timeout)) {
2611 return false;
2612 }
2613
2614 // send request
2615 if (!$this->sendRequest($data, $cookies)) {
2616 return false;
2617 }
2618
2619 // get response
2620 $respdata = $this->getResponse();
2621 } else {
2622 $this->setError("Too many tries to get an OK response ($this->response_status_line)");
2623 }
2624 }
2625 $this->debug('end of send()');
2626 return $respdata;
2627 }
2628
2629
2641 public function sendHTTPS($data, $timeout=0, $response_timeout=30, $cookies=null)
2642 {
2643 return $this->send($data, $timeout, $response_timeout, $cookies);
2644 }
2645
2656 public function setCredentials($username, $password, $authtype = 'basic', $digestRequest = array(), $certRequest = array())
2657 {
2658 $this->debug("setCredentials username=$username authtype=$authtype digestRequest=");
2659 $this->appendDebug($this->varDump($digestRequest));
2660 $this->debug("certRequest=");
2661 $this->appendDebug($this->varDump($certRequest));
2662 // cf. RFC 2617
2663 if ($authtype == 'basic') {
2664 $this->setHeader('Authorization', 'Basic ' . base64_encode(str_replace(':', '', $username) . ':' . $password));
2665 } elseif ($authtype == 'digest') {
2666 if (isset($digestRequest['nonce'])) {
2667 $digestRequest['nc'] = isset($digestRequest['nc']) ? $digestRequest['nc']++ : 1;
2668
2669 // calculate the Digest hashes (calculate code based on digest implementation found at: http://www.rassoc.com/gregr/weblog/stories/2002/07/09/webServicesSecurityHttpDigestAuthenticationWithoutActiveDirectory.html)
2670
2671 // A1 = unq(username-value) ":" unq(realm-value) ":" passwd
2672 $A1 = $username . ':' . (isset($digestRequest['realm']) ? $digestRequest['realm'] : '') . ':' . $password;
2673
2674 // H(A1) = MD5(A1)
2675 $HA1 = md5($A1);
2676
2677 // A2 = Method ":" digest-uri-value
2678 $A2 = $this->request_method . ':' . $this->digest_uri;
2679
2680 // H(A2)
2681 $HA2 = md5($A2);
2682
2683 // KD(secret, data) = H(concat(secret, ":", data))
2684 // if qop == auth:
2685 // request-digest = <"> < KD ( H(A1), unq(nonce-value)
2686 // ":" nc-value
2687 // ":" unq(cnonce-value)
2688 // ":" unq(qop-value)
2689 // ":" H(A2)
2690 // ) <">
2691 // if qop is missing,
2692 // request-digest = <"> < KD ( H(A1), unq(nonce-value) ":" H(A2) ) > <">
2693
2694 $unhashedDigest = '';
2695 $nonce = isset($digestRequest['nonce']) ? $digestRequest['nonce'] : '';
2696 $cnonce = $nonce;
2697 if ($digestRequest['qop'] != '') {
2698 $unhashedDigest = $HA1 . ':' . $nonce . ':' . sprintf("%08d", $digestRequest['nc']) . ':' . $cnonce . ':' . $digestRequest['qop'] . ':' . $HA2;
2699 } else {
2700 $unhashedDigest = $HA1 . ':' . $nonce . ':' . $HA2;
2701 }
2702
2703 $hashedDigest = md5($unhashedDigest);
2704
2705 $opaque = '';
2706 if (isset($digestRequest['opaque'])) {
2707 $opaque = ', opaque="' . $digestRequest['opaque'] . '"';
2708 }
2709
2710 $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 . '"');
2711 }
2712 } elseif ($authtype == 'certificate') {
2713 $this->certRequest = $certRequest;
2714 $this->debug('Authorization header not set for certificate');
2715 } elseif ($authtype == 'ntlm') {
2716 // do nothing
2717 $this->debug('Authorization header not set for ntlm');
2718 }
2719 $this->username = $username;
2720 $this->password = $password;
2721 $this->authtype = $authtype;
2722 $this->digestRequest = $digestRequest;
2723 }
2724
2731 public function setSOAPAction($soapaction)
2732 {
2733 $this->setHeader('SOAPAction', '"' . $soapaction . '"');
2734 }
2735
2742 public function setEncoding($enc='gzip, deflate')
2743 {
2744 if (function_exists('gzdeflate')) {
2745 $this->protocol_version = '1.1';
2746 $this->setHeader('Accept-Encoding', $enc);
2747 if (!isset($this->outgoing_headers['Connection'])) {
2748 $this->setHeader('Connection', 'close');
2749 $this->persistentConnection = false;
2750 }
2751 #set_magic_quotes_runtime(0);
2752 // deprecated
2753 $this->encoding = $enc;
2754 }
2755 }
2756
2767 public function setProxy($proxyhost, $proxyport, $proxyusername = '', $proxypassword = '', $proxyauthtype = 'basic')
2768 {
2769 if ($proxyhost) {
2770 $this->proxy = array(
2771 'host' => $proxyhost,
2772 'port' => $proxyport,
2773 'username' => $proxyusername,
2774 'password' => $proxypassword,
2775 'authtype' => $proxyauthtype
2776 );
2777 if ($proxyusername != '' && $proxypassword != '' && $proxyauthtype = 'basic') {
2778 $this->setHeader('Proxy-Authorization', ' Basic ' . base64_encode($proxyusername . ':' . $proxypassword));
2779 }
2780 } else {
2781 $this->debug('remove proxy');
2782 $proxy = null;
2783 unsetHeader('Proxy-Authorization');
2784 }
2785 }
2786
2787
2797 {
2798 $skipHeaders = array( 'HTTP/1.1 100',
2799 'HTTP/1.0 301',
2800 'HTTP/1.1 301',
2801 'HTTP/1.0 302',
2802 'HTTP/1.1 302',
2803 'HTTP/1.0 401',
2804 'HTTP/1.1 401',
2805 'HTTP/1.0 200 Connection established');
2806 foreach ($skipHeaders as $hd) {
2807 $prefix = substr($data, 0, strlen($hd));
2808 if ($prefix == $hd) {
2809 return true;
2810 }
2811 }
2812
2813 return false;
2814 }
2815
2826 public function decodeChunked($buffer, $lb)
2827 {
2828 // length := 0
2829 $length = 0;
2830 $new = '';
2831
2832 // read chunk-size, chunk-extension (if any) and CRLF
2833 // get the position of the linebreak
2834 $chunkend = strpos($buffer, $lb);
2835 if ($chunkend == false) {
2836 $this->debug('no linebreak found in decodeChunked');
2837 return $new;
2838 }
2839 $temp = substr($buffer, 0, $chunkend);
2840 $chunk_size = hexdec(trim($temp));
2841 $chunkstart = $chunkend + strlen($lb);
2842 // while (chunk-size > 0) {
2843 while ($chunk_size > 0) {
2844 $this->debug("chunkstart: $chunkstart chunk_size: $chunk_size");
2845 $chunkend = strpos($buffer, $lb, $chunkstart + $chunk_size);
2846
2847 // Just in case we got a broken connection
2848 if ($chunkend == false) {
2849 $chunk = substr($buffer, $chunkstart);
2850 // append chunk-data to entity-body
2851 $new .= $chunk;
2852 $length += strlen($chunk);
2853 break;
2854 }
2855
2856 // read chunk-data and CRLF
2857 $chunk = substr($buffer, $chunkstart, $chunkend-$chunkstart);
2858 // append chunk-data to entity-body
2859 $new .= $chunk;
2860 // length := length + chunk-size
2861 $length += strlen($chunk);
2862 // read chunk-size and CRLF
2863 $chunkstart = $chunkend + strlen($lb);
2864
2865 $chunkend = strpos($buffer, $lb, $chunkstart) + strlen($lb);
2866 if ($chunkend == false) {
2867 break; //Just in case we got a broken connection
2868 }
2869 $temp = substr($buffer, $chunkstart, $chunkend-$chunkstart);
2870 $chunk_size = hexdec(trim($temp));
2871 $chunkstart = $chunkend;
2872 }
2873 return $new;
2874 }
2875
2884 public function buildPayload($data, $cookie_str = '')
2885 {
2886 // Note: for cURL connections, $this->outgoing_payload is ignored,
2887 // as is the Content-Length header, but these are still created as
2888 // debugging guides.
2889
2890 // add content-length header
2891 $this->setHeader('Content-Length', strlen($data));
2892
2893 // start building outgoing payload:
2894 if ($this->proxy) {
2895 $uri = $this->url;
2896 } else {
2897 $uri = $this->uri;
2898 }
2899 $req = "$this->request_method $uri HTTP/$this->protocol_version";
2900 $this->debug("HTTP request: $req");
2901 $this->outgoing_payload = "$req\r\n";
2902
2903 // loop thru headers, serializing
2904 foreach ($this->outgoing_headers as $k => $v) {
2905 $hdr = $k . ': ' . $v;
2906 $this->debug("HTTP header: $hdr");
2907 $this->outgoing_payload .= "$hdr\r\n";
2908 }
2909
2910 // add any cookies
2911 if ($cookie_str != '') {
2912 $hdr = 'Cookie: ' . $cookie_str;
2913 $this->debug("HTTP header: $hdr");
2914 $this->outgoing_payload .= "$hdr\r\n";
2915 }
2916
2917 // header/body separator
2918 $this->outgoing_payload .= "\r\n";
2919
2920 // add data
2921 $this->outgoing_payload .= $data;
2922 }
2923
2932 public function sendRequest($data, $cookies = null)
2933 {
2934 // build cookie string
2935 $cookie_str = $this->getCookiesForRequest($cookies, (($this->scheme == 'ssl') || ($this->scheme == 'https')));
2936
2937 // build payload
2938 $this->buildPayload($data, $cookie_str);
2939
2940 if ($this->io_method() == 'socket') {
2941 // send payload
2942 if (!fputs($this->fp, $this->outgoing_payload, strlen($this->outgoing_payload))) {
2943 $this->setError('couldn\'t write message data to socket');
2944 $this->debug('couldn\'t write message data to socket');
2945 return false;
2946 }
2947 $this->debug('wrote data to socket, length = ' . strlen($this->outgoing_payload));
2948 return true;
2949 } elseif ($this->io_method() == 'curl') {
2950 // set payload
2951 // cURL does say this should only be the verb, and in fact it
2952 // turns out that the URI and HTTP version are appended to this, which
2953 // some servers refuse to work with (so we no longer use this method!)
2954 //$this->setCurlOption(CURLOPT_CUSTOMREQUEST, $this->outgoing_payload);
2955 $curl_headers = array();
2956 foreach ($this->outgoing_headers as $k => $v) {
2957 if ($k == 'Connection' || $k == 'Content-Length' || $k == 'Host' || $k == 'Authorization' || $k == 'Proxy-Authorization') {
2958 $this->debug("Skip cURL header $k: $v");
2959 } else {
2960 $curl_headers[] = "$k: $v";
2961 }
2962 }
2963 if ($cookie_str != '') {
2964 $curl_headers[] = 'Cookie: ' . $cookie_str;
2965 }
2966 $this->setCurlOption(CURLOPT_HTTPHEADER, $curl_headers);
2967 $this->debug('set cURL HTTP headers');
2968 if ($this->request_method == "POST") {
2969 $this->setCurlOption(CURLOPT_POST, 1);
2970 $this->setCurlOption(CURLOPT_POSTFIELDS, $data);
2971 $this->debug('set cURL POST data');
2972 } else {
2973 }
2974 // insert custom user-set cURL options
2975 foreach ($this->ch_options as $key => $val) {
2976 $this->setCurlOption($key, $val);
2977 }
2978
2979 $this->debug('set cURL payload');
2980 return true;
2981 }
2982 }
2983
2990 public function getResponse()
2991 {
2992 $this->incoming_payload = '';
2993
2994 if ($this->io_method() == 'socket') {
2995 // loop until headers have been retrieved
2996 $data = '';
2997 while (!isset($lb)) {
2998
2999 // We might EOF during header read.
3000 if (feof($this->fp)) {
3001 $this->incoming_payload = $data;
3002 $this->debug('found no headers before EOF after length ' . strlen($data));
3003 $this->debug("received before EOF:\n" . $data);
3004 $this->setError('server failed to send headers');
3005 return false;
3006 }
3007
3008 $tmp = fgets($this->fp, 256);
3009 $tmplen = strlen($tmp);
3010 $this->debug("read line of $tmplen bytes: " . trim($tmp));
3011
3012 if ($tmplen == 0) {
3013 $this->incoming_payload = $data;
3014 $this->debug('socket read of headers timed out after length ' . strlen($data));
3015 $this->debug("read before timeout: " . $data);
3016 $this->setError('socket read of headers timed out');
3017 return false;
3018 }
3019
3020 $data .= $tmp;
3021 $pos = strpos($data, "\r\n\r\n");
3022 if ($pos > 1) {
3023 $lb = "\r\n";
3024 } else {
3025 $pos = strpos($data, "\n\n");
3026 if ($pos > 1) {
3027 $lb = "\n";
3028 }
3029 }
3030 // remove 100 headers
3031 if (isset($lb) && preg_match('/^HTTP\/1.1 100/', $data)) {
3032 unset($lb);
3033 $data = '';
3034 }//
3035 }
3036 // store header data
3037 $this->incoming_payload .= $data;
3038 $this->debug('found end of headers after length ' . strlen($data));
3039 // process headers
3040 $header_data = trim(substr($data, 0, $pos));
3041 $header_array = explode($lb, $header_data);
3042 $this->incoming_headers = array();
3043 $this->incoming_cookies = array();
3044 foreach ($header_array as $header_line) {
3045 $arr = explode(':', $header_line, 2);
3046 if (count($arr) > 1) {
3047 $header_name = strtolower(trim($arr[0]));
3048 $this->incoming_headers[$header_name] = trim($arr[1]);
3049 if ($header_name == 'set-cookie') {
3050 // TODO: allow multiple cookies from parseCookie
3051 $cookie = $this->parseCookie(trim($arr[1]));
3052 if ($cookie) {
3053 $this->incoming_cookies[] = $cookie;
3054 $this->debug('found cookie: ' . $cookie['name'] . ' = ' . $cookie['value']);
3055 } else {
3056 $this->debug('did not find cookie in ' . trim($arr[1]));
3057 }
3058 }
3059 } elseif (isset($header_name)) {
3060 // append continuation line to previous header
3061 $this->incoming_headers[$header_name] .= $lb . ' ' . $header_line;
3062 }
3063 }
3064
3065 // loop until msg has been received
3066 if (isset($this->incoming_headers['transfer-encoding']) && strtolower($this->incoming_headers['transfer-encoding']) == 'chunked') {
3067 $content_length = 2147483647; // ignore any content-length header
3068 $chunked = true;
3069 $this->debug("want to read chunked content");
3070 } elseif (isset($this->incoming_headers['content-length'])) {
3071 $content_length = $this->incoming_headers['content-length'];
3072 $chunked = false;
3073 $this->debug("want to read content of length $content_length");
3074 } else {
3075 $content_length = 2147483647;
3076 $chunked = false;
3077 $this->debug("want to read content to EOF");
3078 }
3079 $data = '';
3080 do {
3081 if ($chunked) {
3082 $tmp = fgets($this->fp, 256);
3083 $tmplen = strlen($tmp);
3084 $this->debug("read chunk line of $tmplen bytes");
3085 if ($tmplen == 0) {
3086 $this->incoming_payload = $data;
3087 $this->debug('socket read of chunk length timed out after length ' . strlen($data));
3088 $this->debug("read before timeout:\n" . $data);
3089 $this->setError('socket read of chunk length timed out');
3090 return false;
3091 }
3092 $content_length = hexdec(trim($tmp));
3093 $this->debug("chunk length $content_length");
3094 }
3095 $strlen = 0;
3096 while (($strlen < $content_length) && (!feof($this->fp))) {
3097 $readlen = min(8192, $content_length - $strlen);
3098 $tmp = fread($this->fp, $readlen);
3099 $tmplen = strlen($tmp);
3100 $this->debug("read buffer of $tmplen bytes");
3101 if (($tmplen == 0) && (!feof($this->fp))) {
3102 $this->incoming_payload = $data;
3103 $this->debug('socket read of body timed out after length ' . strlen($data));
3104 $this->debug("read before timeout:\n" . $data);
3105 $this->setError('socket read of body timed out');
3106 return false;
3107 }
3108 $strlen += $tmplen;
3109 $data .= $tmp;
3110 }
3111 if ($chunked && ($content_length > 0)) {
3112 $tmp = fgets($this->fp, 256);
3113 $tmplen = strlen($tmp);
3114 $this->debug("read chunk terminator of $tmplen bytes");
3115 if ($tmplen == 0) {
3116 $this->incoming_payload = $data;
3117 $this->debug('socket read of chunk terminator timed out after length ' . strlen($data));
3118 $this->debug("read before timeout:\n" . $data);
3119 $this->setError('socket read of chunk terminator timed out');
3120 return false;
3121 }
3122 }
3123 } while ($chunked && ($content_length > 0) && (!feof($this->fp)));
3124 if (feof($this->fp)) {
3125 $this->debug('read to EOF');
3126 }
3127 $this->debug('read body of length ' . strlen($data));
3128 $this->incoming_payload .= $data;
3129 $this->debug('received a total of ' . strlen($this->incoming_payload) . ' bytes of data from server');
3130
3131 // close filepointer
3132 if (
3133 (isset($this->incoming_headers['connection']) && strtolower($this->incoming_headers['connection']) == 'close') ||
3134 (! $this->persistentConnection) || feof($this->fp)) {
3135 fclose($this->fp);
3136 $this->fp = false;
3137 $this->debug('closed socket');
3138 }
3139
3140 // connection was closed unexpectedly
3141 if ($this->incoming_payload == '') {
3142 $this->setError('no response from server');
3143 return false;
3144 }
3145
3146 // decode transfer-encoding
3147// if(isset($this->incoming_headers['transfer-encoding']) && strtolower($this->incoming_headers['transfer-encoding']) == 'chunked'){
3148// if(!$data = $this->decodeChunked($data, $lb)){
3149// $this->setError('Decoding of chunked data failed');
3150// return false;
3151// }
3152 //print "<pre>\nde-chunked:\n---------------\n$data\n\n---------------\n</pre>";
3153 // set decoded payload
3154// $this->incoming_payload = $header_data.$lb.$lb.$data;
3155// }
3156 } elseif ($this->io_method() == 'curl') {
3157 // send and receive
3158 $this->debug('send and receive with cURL');
3159 $this->incoming_payload = curl_exec($this->ch);
3161
3162 $cErr = curl_error($this->ch);
3163 if ($cErr != '') {
3164 $err = 'cURL ERROR: ' . curl_errno($this->ch) . ': ' . $cErr . '<br>';
3165 // TODO: there is a PHP bug that can cause this to SEGV for CURLINFO_CONTENT_TYPE
3166 foreach (curl_getinfo($this->ch) as $k => $v) {
3167 $err .= "$k: $v<br>";
3168 }
3169 $this->debug($err);
3170 $this->setError($err);
3171 curl_close($this->ch);
3172 return false;
3173 } else {
3174 //echo '<pre>';
3175 //var_dump(curl_getinfo($this->ch));
3176 //echo '</pre>';
3177 }
3178 // close curl
3179 $this->debug('No cURL error, closing cURL');
3180 curl_close($this->ch);
3181
3182 // try removing skippable headers
3183 $savedata = $data;
3184 while ($this->isSkippableCurlHeader($data)) {
3185 $this->debug("Found HTTP header to skip");
3186 if ($pos = strpos($data, "\r\n\r\n")) {
3187 $data = ltrim(substr($data, $pos));
3188 } elseif ($pos = strpos($data, "\n\n")) {
3189 $data = ltrim(substr($data, $pos));
3190 }
3191 }
3192
3193 if ($data == '') {
3194 // have nothing left; just remove 100 header(s)
3195 $data = $savedata;
3196 while (preg_match('/^HTTP\/1.1 100/', $data)) {
3197 if ($pos = strpos($data, "\r\n\r\n")) {
3198 $data = ltrim(substr($data, $pos));
3199 } elseif ($pos = strpos($data, "\n\n")) {
3200 $data = ltrim(substr($data, $pos));
3201 }
3202 }
3203 }
3204
3205 // separate content from HTTP headers
3206 if ($pos = strpos($data, "\r\n\r\n")) {
3207 $lb = "\r\n";
3208 } elseif ($pos = strpos($data, "\n\n")) {
3209 $lb = "\n";
3210 } else {
3211 $this->debug('no proper separation of headers and document');
3212 $this->setError('no proper separation of headers and document');
3213 return false;
3214 }
3215 $header_data = trim(substr($data, 0, $pos));
3216 $header_array = explode($lb, $header_data);
3217 $data = ltrim(substr($data, $pos));
3218 $this->debug('found proper separation of headers and document');
3219 $this->debug('cleaned data, stringlen: ' . strlen($data));
3220 // clean headers
3221 foreach ($header_array as $header_line) {
3222 $arr = explode(':', $header_line, 2);
3223 if (count($arr) > 1) {
3224 $header_name = strtolower(trim($arr[0]));
3225 $this->incoming_headers[$header_name] = trim($arr[1]);
3226 if ($header_name == 'set-cookie') {
3227 // TODO: allow multiple cookies from parseCookie
3228 $cookie = $this->parseCookie(trim($arr[1]));
3229 if ($cookie) {
3230 $this->incoming_cookies[] = $cookie;
3231 $this->debug('found cookie: ' . $cookie['name'] . ' = ' . $cookie['value']);
3232 } else {
3233 $this->debug('did not find cookie in ' . trim($arr[1]));
3234 }
3235 }
3236 } elseif (isset($header_name)) {
3237 // append continuation line to previous header
3238 $this->incoming_headers[$header_name] .= $lb . ' ' . $header_line;
3239 }
3240 }
3241 }
3242
3243 $this->response_status_line = $header_array[0];
3244 $arr = explode(' ', $this->response_status_line, 3);
3245 $http_version = $arr[0];
3246 $http_status = intval($arr[1]);
3247 $http_reason = count($arr) > 2 ? $arr[2] : '';
3248
3249 // see if we need to resend the request with http digest authentication
3250 if (isset($this->incoming_headers['location']) && ($http_status == 301 || $http_status == 302)) {
3251 $this->debug("Got $http_status $http_reason with Location: " . $this->incoming_headers['location']);
3252 $this->setURL($this->incoming_headers['location']);
3253 $this->tryagain = true;
3254 return false;
3255 }
3256
3257 // see if we need to resend the request with http digest authentication
3258 if (isset($this->incoming_headers['www-authenticate']) && $http_status == 401) {
3259 $this->debug("Got 401 $http_reason with WWW-Authenticate: " . $this->incoming_headers['www-authenticate']);
3260 if (strstr($this->incoming_headers['www-authenticate'], "Digest ")) {
3261 $this->debug('Server wants digest authentication');
3262 // remove "Digest " from our elements
3263 $digestString = str_replace('Digest ', '', $this->incoming_headers['www-authenticate']);
3264
3265 // parse elements into array
3266 $digestElements = explode(',', $digestString);
3267 foreach ($digestElements as $val) {
3268 $tempElement = explode('=', trim($val), 2);
3269 $digestRequest[$tempElement[0]] = str_replace("\"", '', $tempElement[1]);
3270 }
3271
3272 // should have (at least) qop, realm, nonce
3273 if (isset($digestRequest['nonce'])) {
3274 $this->setCredentials($this->username, $this->password, 'digest', $digestRequest);
3275 $this->tryagain = true;
3276 return false;
3277 }
3278 }
3279 $this->debug('HTTP authentication failed');
3280 $this->setError('HTTP authentication failed');
3281 return false;
3282 }
3283
3284 if (
3285 ($http_status >= 300 && $http_status <= 307) ||
3286 ($http_status >= 400 && $http_status <= 417) ||
3287 ($http_status >= 501 && $http_status <= 505)
3288 ) {
3289 $this->setError("Unsupported HTTP response status $http_status $http_reason (soapclient->response has contents of the response)");
3290 return false;
3291 }
3292
3293 // decode content-encoding
3294 if (isset($this->incoming_headers['content-encoding']) && $this->incoming_headers['content-encoding'] != '') {
3295 if (strtolower($this->incoming_headers['content-encoding']) == 'deflate' || strtolower($this->incoming_headers['content-encoding']) == 'gzip') {
3296 // if decoding works, use it. else assume data wasn't gzencoded
3297 if (function_exists('gzinflate')) {
3298 //$timer->setMarker('starting decoding of gzip/deflated content');
3299 // IIS 5 requires gzinflate instead of gzuncompress (similar to IE 5 and gzdeflate v. gzcompress)
3300 // this means there are no Zlib headers, although there should be
3301 $this->debug('The gzinflate function exists');
3302 $datalen = strlen($data);
3303 if ($this->incoming_headers['content-encoding'] == 'deflate') {
3304 if ($degzdata = @gzinflate($data)) {
3305 $data = $degzdata;
3306 $this->debug('The payload has been inflated to ' . strlen($data) . ' bytes');
3307 if (strlen($data) < $datalen) {
3308 // test for the case that the payload has been compressed twice
3309 $this->debug('The inflated payload is smaller than the gzipped one; try again');
3310 if ($degzdata = @gzinflate($data)) {
3311 $data = $degzdata;
3312 $this->debug('The payload has been inflated again to ' . strlen($data) . ' bytes');
3313 }
3314 }
3315 } else {
3316 $this->debug('Error using gzinflate to inflate the payload');
3317 $this->setError('Error using gzinflate to inflate the payload');
3318 }
3319 } elseif ($this->incoming_headers['content-encoding'] == 'gzip') {
3320 if ($degzdata = @gzinflate(substr($data, 10))) { // do our best
3321 $data = $degzdata;
3322 $this->debug('The payload has been un-gzipped to ' . strlen($data) . ' bytes');
3323 if (strlen($data) < $datalen) {
3324 // test for the case that the payload has been compressed twice
3325 $this->debug('The un-gzipped payload is smaller than the gzipped one; try again');
3326 if ($degzdata = @gzinflate(substr($data, 10))) {
3327 $data = $degzdata;
3328 $this->debug('The payload has been un-gzipped again to ' . strlen($data) . ' bytes');
3329 }
3330 }
3331 } else {
3332 $this->debug('Error using gzinflate to un-gzip the payload');
3333 $this->setError('Error using gzinflate to un-gzip the payload');
3334 }
3335 }
3336 //$timer->setMarker('finished decoding of gzip/deflated content');
3337 //print "<xmp>\nde-inflated:\n---------------\n$data\n-------------\n</xmp>";
3338 // set decoded payload
3339 $this->incoming_payload = $header_data . $lb . $lb . $data;
3340 } else {
3341 $this->debug('The server sent compressed data. Your php install must have the Zlib extension compiled in to support this.');
3342 $this->setError('The server sent compressed data. Your php install must have the Zlib extension compiled in to support this.');
3343 }
3344 } else {
3345 $this->debug('Unsupported Content-Encoding ' . $this->incoming_headers['content-encoding']);
3346 $this->setError('Unsupported Content-Encoding ' . $this->incoming_headers['content-encoding']);
3347 }
3348 } else {
3349 $this->debug('No Content-Encoding header');
3350 }
3351
3352 if (strlen($data) == 0) {
3353 $this->debug('no data after headers!');
3354 $this->setError('no data present after HTTP headers');
3355 return false;
3356 }
3357
3358 return $data;
3359 }
3360
3368 public function setContentType($type, $charset = false)
3369 {
3370 $this->setHeader('Content-Type', $type . ($charset ? '; charset=' . $charset : ''));
3371 }
3372
3379 public function usePersistentConnection()
3380 {
3381 if (isset($this->outgoing_headers['Accept-Encoding'])) {
3382 return false;
3383 }
3384 $this->protocol_version = '1.1';
3385 $this->persistentConnection = true;
3386 $this->setHeader('Connection', 'Keep-Alive');
3387 return true;
3388 }
3389
3397 /*
3398 * TODO: allow a Set-Cookie string to be parsed into multiple cookies
3399 */
3400 public function parseCookie($cookie_str)
3401 {
3402 $cookie_str = str_replace('; ', ';', $cookie_str) . ';';
3403 // begin-patch php8
3404 //$data = split(';', $cookie_str);
3405 $data = explode(';', $cookie_str);
3406 $value_str = $data[0];
3407
3408 $cookie_param = 'domain=';
3409 $start = strpos($cookie_str, $cookie_param);
3410 if ($start > 0) {
3411 $domain = substr($cookie_str, $start + strlen($cookie_param));
3412 $domain = substr($domain, 0, strpos($domain, ';'));
3413 } else {
3414 $domain = '';
3415 }
3416
3417 $cookie_param = 'expires=';
3418 $start = strpos($cookie_str, $cookie_param);
3419 if ($start > 0) {
3420 $expires = substr($cookie_str, $start + strlen($cookie_param));
3421 $expires = substr($expires, 0, strpos($expires, ';'));
3422 } else {
3423 $expires = '';
3424 }
3425
3426 $cookie_param = 'path=';
3427 $start = strpos($cookie_str, $cookie_param);
3428 if ($start > 0) {
3429 $path = substr($cookie_str, $start + strlen($cookie_param));
3430 $path = substr($path, 0, strpos($path, ';'));
3431 } else {
3432 $path = '/';
3433 }
3434
3435 $cookie_param = ';secure;';
3436 if (strpos($cookie_str, $cookie_param) !== false) {
3437 $secure = true;
3438 } else {
3439 $secure = false;
3440 }
3441
3442 $sep_pos = strpos($value_str, '=');
3443
3444 if ($sep_pos) {
3445 $name = substr($value_str, 0, $sep_pos);
3446 $value = substr($value_str, $sep_pos + 1);
3447 $cookie= array( 'name' => $name,
3448 'value' => $value,
3449 'domain' => $domain,
3450 'path' => $path,
3451 'expires' => $expires,
3452 'secure' => $secure
3453 );
3454 return $cookie;
3455 }
3456 return false;
3457 }
3458
3467 public function getCookiesForRequest($cookies, $secure=false)
3468 {
3469 $cookie_str = '';
3470 if ((! is_null($cookies)) && (is_array($cookies))) {
3471 foreach ($cookies as $cookie) {
3472 if (! is_array($cookie)) {
3473 continue;
3474 }
3475 $this->debug("check cookie for validity: " . $cookie['name'] . '=' . $cookie['value']);
3476 if ((isset($cookie['expires'])) && (! empty($cookie['expires']))) {
3477 if (strtotime($cookie['expires']) <= time()) {
3478 $this->debug('cookie has expired');
3479 continue;
3480 }
3481 }
3482 if ((isset($cookie['domain'])) && (! empty($cookie['domain']))) {
3483 $domain = preg_quote($cookie['domain']);
3484 if (! preg_match("'.*$domain$'i", $this->host)) {
3485 $this->debug('cookie has different domain');
3486 continue;
3487 }
3488 }
3489 if ((isset($cookie['path'])) && (! empty($cookie['path']))) {
3490 $path = preg_quote($cookie['path']);
3491 if (! preg_match("'^$path.*'i", $this->path)) {
3492 $this->debug('cookie is for a different path');
3493 continue;
3494 }
3495 }
3496 if ((! $secure) && (isset($cookie['secure'])) && ($cookie['secure'])) {
3497 $this->debug('cookie is secure, transport is not');
3498 continue;
3499 }
3500 $cookie_str .= $cookie['name'] . '=' . $cookie['value'] . '; ';
3501 $this->debug('add cookie to Cookie-String: ' . $cookie['name'] . '=' . $cookie['value']);
3502 }
3503 }
3504 return $cookie_str;
3505 }
3506}
3507
3508?><?php
3509
3510
3511
3523{
3529 public $headers = array();
3535 public $request = '';
3541 public $requestHeaders = '';
3547 public $requestHeader = null;
3553 public $document = '';
3559 public $requestSOAP = '';
3565 public $methodURI = '';
3571 public $methodname = '';
3577 public $methodparams = array();
3583 public $SOAPAction = '';
3589 public $xml_encoding = '';
3595 public $decode_utf8 = true;
3596
3602 public $outgoing_headers = array();
3608 public $response = '';
3614 public $responseHeaders = '';
3620 public $responseSOAP = '';
3626 public $methodreturn = false;
3638 public $fault = false;
3644 public $result = 'successful';
3645
3652 public $operations = array();
3658 public $wsdl = false;
3664 public $externalWSDLURL = false;
3670 public $debug_flag = false;
3671
3672
3680 public function __construct($wsdl=false)
3681 {
3683 // turn on debugging?
3684 global $debug;
3685 global $HTTP_SERVER_VARS;
3686
3687 if (isset($_SERVER)) {
3688 $this->debug("_SERVER is defined:");
3689 $this->appendDebug($this->varDump($_SERVER));
3690 } elseif (isset($HTTP_SERVER_VARS)) {
3691 $this->debug("HTTP_SERVER_VARS is defined:");
3692 $this->appendDebug($this->varDump($HTTP_SERVER_VARS));
3693 } else {
3694 $this->debug("Neither _SERVER nor HTTP_SERVER_VARS is defined.");
3695 }
3696
3697 if (isset($debug)) {
3698 $this->debug("In nusoap_server, set debug_flag=$debug based on global flag");
3699 $this->debug_flag = $debug;
3700 } elseif (isset($_SERVER['QUERY_STRING'])) {
3701 $qs = explode('&', $_SERVER['QUERY_STRING']);
3702 foreach ($qs as $v) {
3703 if (substr($v, 0, 6) == 'debug=') {
3704 $this->debug("In nusoap_server, set debug_flag=" . substr($v, 6) . " based on query string #1");
3705 $this->debug_flag = substr($v, 6);
3706 }
3707 }
3708 } elseif (isset($HTTP_SERVER_VARS['QUERY_STRING'])) {
3709 $qs = explode('&', $HTTP_SERVER_VARS['QUERY_STRING']);
3710 foreach ($qs as $v) {
3711 if (substr($v, 0, 6) == 'debug=') {
3712 $this->debug("In nusoap_server, set debug_flag=" . substr($v, 6) . " based on query string #2");
3713 $this->debug_flag = substr($v, 6);
3714 }
3715 }
3716 }
3717
3718 // wsdl
3719 if ($wsdl) {
3720 $this->debug("In nusoap_server, WSDL is specified");
3721 if (is_object($wsdl) && (get_class($wsdl) == 'wsdl')) {
3722 $this->wsdl = $wsdl;
3723 $this->externalWSDLURL = $this->wsdl->wsdl;
3724 $this->debug('Use existing wsdl instance from ' . $this->externalWSDLURL);
3725 } else {
3726 $this->debug('Create wsdl from ' . $wsdl);
3727 $this->wsdl = new wsdl($wsdl);
3728 $this->externalWSDLURL = $wsdl;
3729 }
3730 $this->appendDebug($this->wsdl->getDebug());
3731 $this->wsdl->clearDebug();
3732 if ($err = $this->wsdl->getError()) {
3733 die('WSDL ERROR: ' . $err);
3734 }
3735 }
3736 }
3737
3744 public function service($data)
3745 {
3746 global $HTTP_SERVER_VARS;
3747
3748 if (isset($_SERVER['QUERY_STRING'])) {
3749 $qs = $_SERVER['QUERY_STRING'];
3750 } elseif (isset($HTTP_SERVER_VARS['QUERY_STRING'])) {
3751 $qs = $HTTP_SERVER_VARS['QUERY_STRING'];
3752 } else {
3753 $qs = '';
3754 }
3755 $this->debug("In service, query string=$qs");
3756
3757 if (preg_match('/wsdl/', $qs)) {
3758 $this->debug("In service, this is a request for WSDL");
3759 if ($this->externalWSDLURL) {
3760 if (strpos($this->externalWSDLURL, "://")!==false) { // assume URL
3761 header('Location: ' . $this->externalWSDLURL);
3762 } else { // assume file
3763 header("Content-Type: text/xml\r\n");
3764 $fp = fopen($this->externalWSDLURL, 'r');
3765 fpassthru($fp);
3766 }
3767 } elseif ($this->wsdl) {
3768 header("Content-Type: text/xml; charset=ISO-8859-1\r\n");
3769 print $this->wsdl->serialize($this->debug_flag);
3770 if ($this->debug_flag) {
3771 $this->debug('wsdl:');
3772 $this->appendDebug($this->varDump($this->wsdl));
3773 print $this->getDebugAsXMLComment();
3774 }
3775 } else {
3776 header("Content-Type: text/html; charset=ISO-8859-1\r\n");
3777 print "This service does not provide WSDL";
3778 }
3779 } elseif ($data == '' && $this->wsdl) {
3780 $this->debug("In service, there is no data, so return Web description");
3781 print $this->wsdl->webDescription();
3782 } else {
3783 $this->debug("In service, invoke the request");
3784 $this->parse_request($data);
3785 if (! $this->fault) {
3786 $this->invoke_method();
3787 }
3788 if (! $this->fault) {
3789 $this->serialize_return();
3790 }
3791 $this->send_response();
3792 }
3793 }
3794
3807 public function parse_http_headers()
3808 {
3809 global $HTTP_SERVER_VARS;
3810
3811 $this->request = '';
3812 $this->SOAPAction = '';
3813 if (function_exists('getallheaders')) {
3814 $this->debug("In parse_http_headers, use getallheaders");
3815 $headers = getallheaders();
3816 foreach ($headers as $k=>$v) {
3817 $k = strtolower($k);
3818 $this->headers[$k] = $v;
3819 $this->request .= "$k: $v\r\n";
3820 $this->debug("$k: $v");
3821 }
3822 // get SOAPAction header
3823 if (isset($this->headers['soapaction'])) {
3824 $this->SOAPAction = str_replace('"', '', $this->headers['soapaction']);
3825 }
3826 // get the character encoding of the incoming request
3827 if (isset($this->headers['content-type']) && strpos($this->headers['content-type'], '=')) {
3828 $enc = str_replace('"', '', substr(strstr($this->headers["content-type"], '='), 1));
3829 if (preg_match('/^(ISO-8859-1|US-ASCII|UTF-8)$/i', $enc)) {
3830 $this->xml_encoding = strtoupper($enc);
3831 } else {
3832 $this->xml_encoding = 'US-ASCII';
3833 }
3834 } else {
3835 // should be US-ASCII for HTTP 1.0 or ISO-8859-1 for HTTP 1.1
3836 $this->xml_encoding = 'ISO-8859-1';
3837 }
3838 } elseif (isset($_SERVER) && is_array($_SERVER)) {
3839 $this->debug("In parse_http_headers, use _SERVER");
3840 foreach ($_SERVER as $k => $v) {
3841 if (substr($k, 0, 5) == 'HTTP_') {
3842 $k = str_replace(' ', '-', strtolower(str_replace('_', ' ', substr($k, 5))));
3843 } else {
3844 $k = str_replace(' ', '-', strtolower(str_replace('_', ' ', $k)));
3845 }
3846 if ($k == 'soapaction') {
3847 // get SOAPAction header
3848 $k = 'SOAPAction';
3849 $v = str_replace('"', '', $v);
3850 $v = str_replace('\\', '', $v);
3851 $this->SOAPAction = $v;
3852 } elseif ($k == 'content-type') {
3853 // get the character encoding of the incoming request
3854 if (strpos($v, '=')) {
3855 $enc = substr(strstr($v, '='), 1);
3856 $enc = str_replace('"', '', $enc);
3857 $enc = str_replace('\\', '', $enc);
3858 if (preg_match('/^(ISO-8859-1|US-ASCII|UTF-8)$/i', $enc)) {
3859 $this->xml_encoding = strtoupper($enc);
3860 } else {
3861 $this->xml_encoding = 'US-ASCII';
3862 }
3863 } else {
3864 // should be US-ASCII for HTTP 1.0 or ISO-8859-1 for HTTP 1.1
3865 $this->xml_encoding = 'ISO-8859-1';
3866 }
3867 }
3868 $this->headers[$k] = $v;
3869 $this->request .= "$k: $v\r\n";
3870 $this->debug("$k: $v");
3871 }
3872 } elseif (is_array($HTTP_SERVER_VARS)) {
3873 $this->debug("In parse_http_headers, use HTTP_SERVER_VARS");
3874 foreach ($HTTP_SERVER_VARS as $k => $v) {
3875 if (substr($k, 0, 5) == 'HTTP_') {
3876 $k = str_replace(' ', '-', strtolower(str_replace('_', ' ', substr($k, 5))));
3877 $k = strtolower(substr($k, 5));
3878 } else {
3879 $k = str_replace(' ', '-', strtolower(str_replace('_', ' ', $k)));
3880 $k = strtolower($k);
3881 }
3882 if ($k == 'soapaction') {
3883 // get SOAPAction header
3884 $k = 'SOAPAction';
3885 $v = str_replace('"', '', $v);
3886 $v = str_replace('\\', '', $v);
3887 $this->SOAPAction = $v;
3888 } elseif ($k == 'content-type') {
3889 // get the character encoding of the incoming request
3890 if (strpos($v, '=')) {
3891 $enc = substr(strstr($v, '='), 1);
3892 $enc = str_replace('"', '', $enc);
3893 $enc = str_replace('\\', '', $enc);
3894 if (preg_match('/^(ISO-8859-1|US-ASCII|UTF-8)$/i', $enc)) {
3895 $this->xml_encoding = strtoupper($enc);
3896 } else {
3897 $this->xml_encoding = 'US-ASCII';
3898 }
3899 } else {
3900 // should be US-ASCII for HTTP 1.0 or ISO-8859-1 for HTTP 1.1
3901 $this->xml_encoding = 'ISO-8859-1';
3902 }
3903 }
3904 $this->headers[$k] = $v;
3905 $this->request .= "$k: $v\r\n";
3906 $this->debug("$k: $v");
3907 }
3908 } else {
3909 $this->debug("In parse_http_headers, HTTP headers not accessible");
3910 $this->setError("HTTP headers not accessible");
3911 }
3912 }
3913
3936 public function parse_request($data='')
3937 {
3938 $this->debug('entering parse_request()');
3939 $this->parse_http_headers();
3940 $this->debug('got character encoding: ' . $this->xml_encoding);
3941 // uncompress if necessary
3942 if (isset($this->headers['content-encoding']) && $this->headers['content-encoding'] != '') {
3943 $this->debug('got content encoding: ' . $this->headers['content-encoding']);
3944 if ($this->headers['content-encoding'] == 'deflate' || $this->headers['content-encoding'] == 'gzip') {
3945 // if decoding works, use it. else assume data wasn't gzencoded
3946 if (function_exists('gzuncompress')) {
3947 if ($this->headers['content-encoding'] == 'deflate' && $degzdata = @gzuncompress($data)) {
3948 $data = $degzdata;
3949 } elseif ($this->headers['content-encoding'] == 'gzip' && $degzdata = gzinflate(substr($data, 10))) {
3950 $data = $degzdata;
3951 } else {
3952 $this->fault('SOAP-ENV:Client', 'Errors occurred when trying to decode the data');
3953 return;
3954 }
3955 } else {
3956 $this->fault('SOAP-ENV:Client', 'This Server does not support compressed data');
3957 return;
3958 }
3959 }
3960 }
3961 $this->request .= "\r\n" . $data;
3962 $data = $this->parseRequest($this->headers, $data);
3963 $this->requestSOAP = $data;
3964 $this->debug('leaving parse_request');
3965 }
3966
3984 public function invoke_method()
3985 {
3986 $this->debug('in invoke_method, methodname=' . $this->methodname . ' methodURI=' . $this->methodURI . ' SOAPAction=' . $this->SOAPAction);
3987
3988 if ($this->wsdl) {
3989 if ($this->opData = $this->wsdl->getOperationData($this->methodname)) {
3990 $this->debug('in invoke_method, found WSDL operation=' . $this->methodname);
3991 $this->appendDebug('opData=' . $this->varDump($this->opData));
3992 } elseif ($this->opData = $this->wsdl->getOperationDataForSoapAction($this->SOAPAction)) {
3993 // Note: hopefully this case will only be used for doc/lit, since rpc services should have wrapper element
3994 $this->debug('in invoke_method, found WSDL soapAction=' . $this->SOAPAction . ' for operation=' . $this->opData['name']);
3995 $this->appendDebug('opData=' . $this->varDump($this->opData));
3996 $this->methodname = $this->opData['name'];
3997 } else {
3998 $this->debug('in invoke_method, no WSDL for operation=' . $this->methodname);
3999 $this->fault('SOAP-ENV:Client', "Operation '" . $this->methodname . "' is not defined in the WSDL for this service");
4000 return;
4001 }
4002 } else {
4003 $this->debug('in invoke_method, no WSDL to validate method');
4004 }
4005
4006 // if a . is present in $this->methodname, we see if there is a class in scope,
4007 // which could be referred to. We will also distinguish between two deliminators,
4008 // to allow methods to be called a the class or an instance
4009 $class = '';
4010 $method = '';
4011 if (strpos($this->methodname, '..') > 0) {
4012 $delim = '..';
4013 } elseif (strpos($this->methodname, '.') > 0) {
4014 $delim = '.';
4015 } else {
4016 $delim = '';
4017 }
4018
4019 if (strlen($delim) > 0 && substr_count($this->methodname, $delim) == 1 &&
4020 class_exists(substr($this->methodname, 0, strpos($this->methodname, $delim)))) {
4021 // get the class and method name
4022 $class = substr($this->methodname, 0, strpos($this->methodname, $delim));
4023 $method = substr($this->methodname, strpos($this->methodname, $delim) + strlen($delim));
4024 $this->debug("in invoke_method, class=$class method=$method delim=$delim");
4025 }
4026 // set class handler
4027 // added to support single operations
4028 if ($class == '' && $this->class !='') {
4029 $class = $this->class;
4030 $delim = "..";
4031 $method = $this->methodname;
4032 }
4033
4034 // does method exist?
4035 if ($class == '') {
4036 if (!function_exists($this->methodname)) {
4037 $this->debug("in invoke_method, function '$this->methodname' not found!");
4038 $this->result = 'fault: method not found';
4039 $this->fault('SOAP-ENV:Client', "method '$this->methodname' not defined in service");
4040 return;
4041 }
4042 } else {
4043 $method_to_compare = (substr(phpversion(), 0, 2) == '4.') ? strtolower($method) : $method;
4044 if (!in_array($method_to_compare, get_class_methods($class))) {
4045 $this->debug("in invoke_method, method '$this->methodname' not found in class '$class'!");
4046 $this->result = 'fault: method not found';
4047 $this->fault('SOAP-ENV:Client', "method '$this->methodname' not defined in service");
4048 return;
4049 }
4050 }
4051
4052 // evaluate message, getting back parameters
4053 // verify that request parameters match the method's signature
4054 if (! $this->verify_method($this->methodname, $this->methodparams)) {
4055 // debug
4056 $this->debug('ERROR: request not verified against method signature');
4057 $this->result = 'fault: request failed validation against method signature';
4058 // return fault
4059 $this->fault('SOAP-ENV:Client', "Operation '$this->methodname' not defined in service.");
4060 return;
4061 }
4062
4063 // if there are parameters to pass
4064 $this->debug('in invoke_method, params:');
4065 $this->appendDebug($this->varDump($this->methodparams));
4066 $this->debug("in invoke_method, calling '$this->methodname'");
4067 if (!function_exists('call_user_func_array')) {
4068 if ($class == '') {
4069 $this->debug('in invoke_method, calling function using eval()');
4070 $funcCall = "\$this->methodreturn = $this->methodname(";
4071 } else {
4072 if ($delim == '..') {
4073 $this->debug('in invoke_method, calling class method using eval()');
4074 $funcCall = "\$this->methodreturn = " . $class . "::" . $method . "(";
4075 } else {
4076 $this->debug('in invoke_method, calling instance method using eval()');
4077 // generate unique instance name
4078 $instname = "\$inst_" . time();
4079 $funcCall = $instname . " = new " . $class . "(); ";
4080 $funcCall .= "\$this->methodreturn = " . $instname . "->" . $method . "(";
4081 }
4082 }
4083 if ($this->methodparams) {
4084 foreach ($this->methodparams as $param) {
4085 if (is_array($param) || is_object($param)) {
4086 $this->fault('SOAP-ENV:Client', 'NuSOAP does not handle complexType parameters correctly when using eval; call_user_func_array must be available');
4087 return;
4088 }
4089 $funcCall .= "\"$param\",";
4090 }
4091 $funcCall = substr($funcCall, 0, -1);
4092 }
4093 $funcCall .= ');';
4094 $this->debug('in invoke_method, function call: ' . $funcCall);
4095 @eval($funcCall);
4096 } else {
4097 if ($class == '') {
4098 $this->debug('in invoke_method, calling function using call_user_func_array()');
4099 $call_arg = "$this->methodname"; // straight assignment changes $this->methodname to lower case after call_user_func_array()
4100 } elseif ($delim == '..') {
4101 $this->debug('in invoke_method, calling class method using call_user_func_array()');
4102 $call_arg = array($class, $method);
4103 } else {
4104 $this->debug('in invoke_method, calling instance method using call_user_func_array()');
4105 $instance = new $class();
4106 $call_arg = array(&$instance, $method);
4107 }
4108 if (is_array($this->methodparams)) {
4109 $this->methodreturn = call_user_func_array($call_arg, array_values($this->methodparams));
4110 } else {
4111 $this->methodreturn = call_user_func_array($call_arg, array());
4112 }
4113 }
4114 $this->debug('in invoke_method, methodreturn:');
4115 $this->appendDebug($this->varDump($this->methodreturn));
4116 $this->debug("in invoke_method, called method $this->methodname, received data of type " . gettype($this->methodreturn));
4117 }
4118
4130 public function serialize_return()
4131 {
4132 $this->debug('Entering serialize_return methodname: ' . $this->methodname . ' methodURI: ' . $this->methodURI);
4133 // if fault
4134 if (isset($this->methodreturn) && ((get_class((object)$this->methodreturn) == 'soap_fault') || (get_class((object)$this->methodreturn) == 'nusoap_fault'))) {
4135 $this->debug('got a fault object from method');
4136 $this->fault = $this->methodreturn;
4137 return;
4138 } elseif ($this->methodreturnisliteralxml) {
4139 $return_val = $this->methodreturn;
4140 // returned value(s)
4141 } else {
4142 $this->debug('got a(n) ' . gettype($this->methodreturn) . ' from method');
4143 $this->debug('serializing return value');
4144 if ($this->wsdl) {
4145 if (sizeof($this->opData['output']['parts']) > 1) {
4146 $this->debug('more than one output part, so use the method return unchanged');
4147 $opParams = $this->methodreturn;
4148 } elseif (sizeof($this->opData['output']['parts']) == 1) {
4149 $this->debug('exactly one output part, so wrap the method return in a simple array');
4150 // TODO: verify that it is not already wrapped!
4151 //foreach ($this->opData['output']['parts'] as $name => $type) {
4152 // $this->debug('wrap in element named ' . $name);
4153 //}
4154 $opParams = array($this->methodreturn);
4155 }
4156 $return_val = $this->wsdl->serializeRPCParameters($this->methodname, 'output', $opParams);
4157 $this->appendDebug($this->wsdl->getDebug());
4158 $this->wsdl->clearDebug();
4159 if ($errstr = $this->wsdl->getError()) {
4160 $this->debug('got wsdl error: ' . $errstr);
4161 $this->fault('SOAP-ENV:Server', 'unable to serialize result');
4162 return;
4163 }
4164 } else {
4165 if (isset($this->methodreturn)) {
4166 $return_val = $this->serialize_val($this->methodreturn, 'return');
4167 } else {
4168 $return_val = '';
4169 $this->debug('in absence of WSDL, assume void return for backward compatibility');
4170 }
4171 }
4172 }
4173 $this->debug('return value:');
4174 $this->appendDebug($this->varDump($return_val));
4175
4176 $this->debug('serializing response');
4177 if ($this->wsdl) {
4178 $this->debug('have WSDL for serialization: style is ' . $this->opData['style']);
4179 if ($this->opData['style'] == 'rpc') {
4180 $this->debug('style is rpc for serialization: use is ' . $this->opData['output']['use']);
4181 if ($this->opData['output']['use'] == 'literal') {
4182 // 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
4183 $payload = '<ns1:' . $this->methodname . 'Response xmlns:ns1="' . $this->methodURI . '">' . $return_val . '</ns1:' . $this->methodname . "Response>";
4184 } else {
4185 $payload = '<ns1:' . $this->methodname . 'Response xmlns:ns1="' . $this->methodURI . '">' . $return_val . '</ns1:' . $this->methodname . "Response>";
4186 }
4187 } else {
4188 $this->debug('style is not rpc for serialization: assume document');
4189 $payload = $return_val;
4190 }
4191 } else {
4192 $this->debug('do not have WSDL for serialization: assume rpc/encoded');
4193 $payload = '<ns1:' . $this->methodname . 'Response xmlns:ns1="' . $this->methodURI . '">' . $return_val . '</ns1:' . $this->methodname . "Response>";
4194 }
4195 $this->result = 'successful';
4196 if ($this->wsdl) {
4197 //if($this->debug_flag){
4198 $this->appendDebug($this->wsdl->getDebug());
4199 // }
4200 if (isset($opData['output']['encodingStyle'])) {
4201 $encodingStyle = $opData['output']['encodingStyle'];
4202 } else {
4203 $encodingStyle = '';
4204 }
4205 // Added: In case we use a WSDL, return a serialized env. WITH the usedNamespaces.
4206 $this->responseSOAP = $this->serializeEnvelope($payload, $this->responseHeaders, $this->wsdl->usedNamespaces, $this->opData['style'], $this->opData['output']['use'], $encodingStyle);
4207 } else {
4208 $this->responseSOAP = $this->serializeEnvelope($payload, $this->responseHeaders);
4209 }
4210 $this->debug("Leaving serialize_return");
4211 }
4212
4223 public function send_response()
4224 {
4225 $this->debug('Enter send_response');
4226 if ($this->fault) {
4227 $payload = $this->fault->serialize();
4228 $this->outgoing_headers[] = "HTTP/1.0 500 Internal Server Error";
4229 $this->outgoing_headers[] = "Status: 500 Internal Server Error";
4230 } else {
4232 // Some combinations of PHP+Web server allow the Status
4233 // to come through as a header. Since OK is the default
4234 // just do nothing.
4235 // $this->outgoing_headers[] = "HTTP/1.0 200 OK";
4236 // $this->outgoing_headers[] = "Status: 200 OK";
4237 }
4238 // add debug data if in debug mode
4239 if (isset($this->debug_flag) && $this->debug_flag) {
4240 $payload .= $this->getDebugAsXMLComment();
4241 }
4242 $this->outgoing_headers[] = "Server: $this->title Server v$this->version";
4243 preg_match('/\$Revisio' . 'n: ([^ ]+)/', $this->revision, $rev);
4244 $this->outgoing_headers[] = "X-SOAP-Server: $this->title/$this->version (" . $rev[1] . ")";
4245 // Let the Web server decide about this
4246 //$this->outgoing_headers[] = "Connection: Close\r\n";
4247 $payload = $this->getHTTPBody($payload);
4248 $type = $this->getHTTPContentType();
4249 $charset = $this->getHTTPContentTypeCharset();
4250 $this->outgoing_headers[] = "Content-Type: $type" . ($charset ? '; charset=' . $charset : '');
4251 //begin code to compress payload - by John
4252 // NOTE: there is no way to know whether the Web server will also compress
4253 // this data.
4254 if (strlen($payload) > 1024 && isset($this->headers) && isset($this->headers['accept-encoding'])) {
4255 if (strstr($this->headers['accept-encoding'], 'gzip')) {
4256 if (function_exists('gzencode')) {
4257 if (isset($this->debug_flag) && $this->debug_flag) {
4258 $payload .= "<!-- Content being gzipped -->";
4259 }
4260 $this->outgoing_headers[] = "Content-Encoding: gzip";
4261 $payload = gzencode($payload);
4262 } else {
4263 if (isset($this->debug_flag) && $this->debug_flag) {
4264 $payload .= "<!-- Content will not be gzipped: no gzencode -->";
4265 }
4266 }
4267 } elseif (strstr($this->headers['accept-encoding'], 'deflate')) {
4268 // Note: MSIE requires gzdeflate output (no Zlib header and checksum),
4269 // instead of gzcompress output,
4270 // which conflicts with HTTP 1.1 spec (http://www.w3.org/Protocols/rfc2616/rfc2616-sec3.html#sec3.5)
4271 if (function_exists('gzdeflate')) {
4272 if (isset($this->debug_flag) && $this->debug_flag) {
4273 $payload .= "<!-- Content being deflated -->";
4274 }
4275 $this->outgoing_headers[] = "Content-Encoding: deflate";
4276 $payload = gzdeflate($payload);
4277 } else {
4278 if (isset($this->debug_flag) && $this->debug_flag) {
4279 $payload .= "<!-- Content will not be deflated: no gzcompress -->";
4280 }
4281 }
4282 }
4283 }
4284 //end code
4285 $this->outgoing_headers[] = "Content-Length: " . strlen($payload);
4286 reset($this->outgoing_headers);
4287 foreach ($this->outgoing_headers as $hdr) {
4288 header($hdr, false);
4289 }
4290 print $payload;
4291 $this->response = join("\r\n", $this->outgoing_headers) . "\r\n\r\n" . $payload;
4292 }
4293
4303 public function verify_method($operation, $request)
4304 {
4305 if (isset($this->wsdl) && is_object($this->wsdl)) {
4306 if ($this->wsdl->getOperationData($operation)) {
4307 return true;
4308 }
4309 } elseif (isset($this->operations[$operation])) {
4310 return true;
4311 }
4312 return false;
4313 }
4314
4323 public function parseRequest($headers, $data)
4324 {
4325 $this->debug('Entering parseRequest() for data of length ' . strlen($data) . ' and type ' . $headers['content-type']);
4326 if (!strstr($headers['content-type'], 'text/xml')) {
4327 $this->setError('Request not of type text/xml');
4328 return false;
4329 }
4330 if (strpos($headers['content-type'], '=')) {
4331 $enc = str_replace('"', '', substr(strstr($headers["content-type"], '='), 1));
4332 $this->debug('Got response encoding: ' . $enc);
4333 if (preg_match('/^(ISO-8859-1|US-ASCII|UTF-8)$/i', $enc)) {
4334 $this->xml_encoding = strtoupper($enc);
4335 } else {
4336 $this->xml_encoding = 'US-ASCII';
4337 }
4338 } else {
4339 // should be US-ASCII for HTTP 1.0 or ISO-8859-1 for HTTP 1.1
4340 $this->xml_encoding = 'ISO-8859-1';
4341 }
4342 $this->debug('Use encoding: ' . $this->xml_encoding . ' when creating nusoap_parser');
4343 // parse response, get soap parser obj
4344 $parser = new nusoap_parser($data, $this->xml_encoding, '', $this->decode_utf8);
4345 // parser debug
4346 $this->debug("parser debug: \n" . $parser->getDebug());
4347 // if fault occurred during message parsing
4348 if ($err = $parser->getError()) {
4349 $this->result = 'fault: error in msg parsing: ' . $err;
4350 $this->fault('SOAP-ENV:Client', "error in msg parsing:\n" . $err);
4351 // else successfully parsed request into soapval object
4352 } else {
4353 // get/set methodname
4354 $this->methodURI = $parser->root_struct_namespace;
4355 $this->methodname = $parser->root_struct_name;
4356 $this->debug('methodname: ' . $this->methodname . ' methodURI: ' . $this->methodURI);
4357 $this->debug('calling parser->get_soapbody()');
4358 $this->methodparams = $parser->get_soapbody();
4359 // get SOAP headers
4360 $this->requestHeaders = $parser->getHeaders();
4361 // get SOAP Header
4362 $this->requestHeader = $parser->get_soapheader();
4363 // add document for doclit support
4364 $this->document = $parser->document;
4365 }
4366 }
4367
4375 public function getHTTPBody($soapmsg)
4376 {
4377 return $soapmsg;
4378 }
4379
4388 public function getHTTPContentType()
4389 {
4390 return 'text/xml';
4391 }
4392
4403 {
4405 }
4406
4416 public function add_to_map($methodname, $in, $out)
4417 {
4418 $this->operations[$methodname] = array('name' => $methodname,'in' => $in,'out' => $out);
4419 }
4420
4435 public function register($name, $in=array(), $out=array(), $namespace=false, $soapaction=false, $style=false, $use=false, $documentation='', $encodingStyle='')
4436 {
4437 global $HTTP_SERVER_VARS;
4438
4439 if ($this->externalWSDLURL) {
4440 die('You cannot bind to an external WSDL file, and register methods outside of it! Please choose either WSDL or no WSDL.');
4441 }
4442 if (! $name) {
4443 die('You must specify a name when you register an operation');
4444 }
4445 if (!is_array($in)) {
4446 die('You must provide an array for operation inputs');
4447 }
4448 if (!is_array($out)) {
4449 die('You must provide an array for operation outputs');
4450 }
4451 if (false == $namespace) {
4452 }
4453 if (false == $soapaction) {
4454 if (isset($_SERVER)) {
4455 $SERVER_NAME = $_SERVER['SERVER_NAME'];
4456 $SCRIPT_NAME = isset($_SERVER['PHP_SELF']) ? $_SERVER['PHP_SELF'] : $_SERVER['SCRIPT_NAME'];
4457 $HTTPS = isset($_SERVER['HTTPS']) ? $_SERVER['HTTPS'] : (isset($HTTP_SERVER_VARS['HTTPS']) ? $HTTP_SERVER_VARS['HTTPS'] : 'off');
4458 } elseif (isset($HTTP_SERVER_VARS)) {
4459 $SERVER_NAME = $HTTP_SERVER_VARS['SERVER_NAME'];
4460 $SCRIPT_NAME = isset($HTTP_SERVER_VARS['PHP_SELF']) ? $HTTP_SERVER_VARS['PHP_SELF'] : $HTTP_SERVER_VARS['SCRIPT_NAME'];
4461 $HTTPS = isset($HTTP_SERVER_VARS['HTTPS']) ? $HTTP_SERVER_VARS['HTTPS'] : 'off';
4462 } else {
4463 $this->setError("Neither _SERVER nor HTTP_SERVER_VARS is available");
4464 }
4465 if ($HTTPS == '1' || $HTTPS == 'on') {
4466 $SCHEME = 'https';
4467 } else {
4468 $SCHEME = 'http';
4469 }
4470 $soapaction = "$SCHEME://$SERVER_NAME$SCRIPT_NAME/$name";
4471 }
4472 if (false == $style) {
4473 $style = "rpc";
4474 }
4475 if (false == $use) {
4476 $use = "encoded";
4477 }
4478 if ($use == 'encoded' && $encodingStyle = '') {
4479 $encodingStyle = 'http://schemas.xmlsoap.org/soap/encoding/';
4480 }
4481
4482 $this->operations[$name] = array(
4483 'name' => $name,
4484 'in' => $in,
4485 'out' => $out,
4486 'namespace' => $namespace,
4487 'soapaction' => $soapaction,
4488 'style' => $style);
4489 if ($this->wsdl) {
4490 $this->wsdl->addOperation($name, $in, $out, $namespace, $soapaction, $style, $use, $documentation, $encodingStyle);
4491 }
4492 return true;
4493 }
4494
4505 public function fault($faultcode, $faultstring, $faultactor='', $faultdetail='')
4506 {
4507 if ($faultdetail == '' && $this->debug_flag) {
4508 $faultdetail = $this->getDebug();
4509 }
4510 $this->fault = new nusoap_fault($faultcode, $faultactor, $faultstring, $faultdetail);
4511 $this->fault->soap_defencoding = $this->soap_defencoding;
4512 }
4513
4525 public function configureWSDL($serviceName, $namespace = false, $endpoint = false, $style='rpc', $transport = 'http://schemas.xmlsoap.org/soap/http', $schemaTargetNamespace = false)
4526 {
4527 global $HTTP_SERVER_VARS;
4528
4529 if (isset($_SERVER)) {
4530 $SERVER_NAME = $_SERVER['SERVER_NAME'];
4531 $SERVER_PORT = $_SERVER['SERVER_PORT'];
4532 $SCRIPT_NAME = isset($_SERVER['PHP_SELF']) ? $_SERVER['PHP_SELF'] : $_SERVER['SCRIPT_NAME'];
4533 $HTTPS = isset($_SERVER['HTTPS']) ? $_SERVER['HTTPS'] : (isset($HTTP_SERVER_VARS['HTTPS']) ? $HTTP_SERVER_VARS['HTTPS'] : 'off');
4534 } elseif (isset($HTTP_SERVER_VARS)) {
4535 $SERVER_NAME = $HTTP_SERVER_VARS['SERVER_NAME'];
4536 $SERVER_PORT = $HTTP_SERVER_VARS['SERVER_PORT'];
4537 $SCRIPT_NAME = isset($HTTP_SERVER_VARS['PHP_SELF']) ? $HTTP_SERVER_VARS['PHP_SELF'] : $HTTP_SERVER_VARS['SCRIPT_NAME'];
4538 $HTTPS = isset($HTTP_SERVER_VARS['HTTPS']) ? $HTTP_SERVER_VARS['HTTPS'] : 'off';
4539 } else {
4540 $this->setError("Neither _SERVER nor HTTP_SERVER_VARS is available");
4541 }
4542 // If server name has port number attached then strip it (else port number gets duplicated in WSDL output) (occurred using lighttpd and FastCGI)
4543 $colon = strpos($SERVER_NAME, ":");
4544 if ($colon) {
4545 $SERVER_NAME = substr($SERVER_NAME, 0, $colon);
4546 }
4547 if ($SERVER_PORT == 80) {
4548 $SERVER_PORT = '';
4549 } else {
4550 $SERVER_PORT = ':' . $SERVER_PORT;
4551 }
4552 if (false == $namespace) {
4553 $namespace = "http://$SERVER_NAME/soap/$serviceName";
4554 }
4555
4556 if (false == $endpoint) {
4557 if ($HTTPS == '1' || $HTTPS == 'on') {
4558 $SCHEME = 'https';
4559 } else {
4560 $SCHEME = 'http';
4561 }
4562 $endpoint = "$SCHEME://$SERVER_NAME$SERVER_PORT$SCRIPT_NAME";
4563 }
4564
4565 if (false == $schemaTargetNamespace) {
4566 $schemaTargetNamespace = $namespace;
4567 }
4568
4569 $this->wsdl = new wsdl();
4570 $this->wsdl->serviceName = $serviceName;
4571 $this->wsdl->endpoint = $endpoint;
4572 $this->wsdl->namespaces['tns'] = $namespace;
4573 $this->wsdl->namespaces['soap'] = 'http://schemas.xmlsoap.org/wsdl/soap/';
4574 $this->wsdl->namespaces['wsdl'] = 'http://schemas.xmlsoap.org/wsdl/';
4575 if ($schemaTargetNamespace != $namespace) {
4576 $this->wsdl->namespaces['types'] = $schemaTargetNamespace;
4577 }
4578 $this->wsdl->schemas[$schemaTargetNamespace][0] = new nusoap_xmlschema('', '', $this->wsdl->namespaces);
4579 if ($style == 'document') {
4580 $this->wsdl->schemas[$schemaTargetNamespace][0]->schemaInfo['elementFormDefault'] = 'qualified';
4581 }
4582 $this->wsdl->schemas[$schemaTargetNamespace][0]->schemaTargetNamespace = $schemaTargetNamespace;
4583 $this->wsdl->schemas[$schemaTargetNamespace][0]->imports['http://schemas.xmlsoap.org/soap/encoding/'][0] = array('location' => '', 'loaded' => true);
4584 $this->wsdl->schemas[$schemaTargetNamespace][0]->imports['http://schemas.xmlsoap.org/wsdl/'][0] = array('location' => '', 'loaded' => true);
4585 $this->wsdl->bindings[$serviceName . 'Binding'] = array(
4586 'name'=>$serviceName . 'Binding',
4587 'style'=>$style,
4588 'transport'=>$transport,
4589 'portType'=>$serviceName . 'PortType');
4590 $this->wsdl->ports[$serviceName . 'Port'] = array(
4591 'binding'=>$serviceName . 'Binding',
4592 'location'=>$endpoint,
4593 'bindingType'=>'http://schemas.xmlsoap.org/wsdl/soap/');
4594 }
4595}
4596
4601{
4602}
4603
4604?><?php
4605
4606
4607
4617class wsdl extends nusoap_base
4618{
4619 // URL or filename of the root of this WSDL
4620 public $wsdl;
4621 // define internal arrays of bindings, ports, operations, messages, etc.
4622 public $schemas = array();
4624 public $message = array();
4625 public $complexTypes = array();
4626 public $messages = array();
4629 public $portTypes = array();
4631 public $bindings = array();
4633 public $ports = array();
4635 public $opData = array();
4636 public $status = '';
4637 public $documentation = false;
4638 public $endpoint = '';
4639 // array of wsdl docs to import
4640 public $import = array();
4641 // parser vars
4642 public $parser;
4643 public $position = 0;
4644 public $depth = 0;
4645 public $depth_array = array();
4646 // for getting wsdl
4647 public $proxyhost = '';
4648 public $proxyport = '';
4649 public $proxyusername = '';
4650 public $proxypassword = '';
4651 public $timeout = 0;
4653 public $curl_options = array(); // User-specified cURL options
4654 public $use_curl = false; // whether to always try to use cURL
4655 // for HTTP authentication
4656 public $username = ''; // Username for HTTP authentication
4657 public $password = ''; // Password for HTTP authentication
4658 public $authtype = ''; // Type of HTTP authentication
4659 public $certRequest = array(); // Certificate for HTTP SSL authentication
4660
4675 public function __construct($wsdl = '', $proxyhost=false, $proxyport=false, $proxyusername=false, $proxypassword=false, $timeout=0, $response_timeout=30, $curl_options=null, $use_curl=false)
4676 {
4678 $this->debug("ctor wsdl=$wsdl timeout=$timeout response_timeout=$response_timeout");
4679 $this->proxyhost = $proxyhost;
4680 $this->proxyport = $proxyport;
4681 $this->proxyusername = $proxyusername;
4682 $this->proxypassword = $proxypassword;
4683 $this->timeout = $timeout;
4684 $this->response_timeout = $response_timeout;
4685 if (is_array($curl_options)) {
4686 $this->curl_options = $curl_options;
4687 }
4688 $this->use_curl = $use_curl;
4689 $this->fetchWSDL($wsdl);
4690 }
4691
4697 public function fetchWSDL($wsdl)
4698 {
4699 $this->debug("parse and process WSDL path=$wsdl");
4700 $this->wsdl = $wsdl;
4701 // parse wsdl file
4702 if ($this->wsdl != "") {
4703 $this->parseWSDL($this->wsdl);
4704 }
4705 // imports
4706 // TODO: handle imports more properly, grabbing them in-line and nesting them
4707 $imported_urls = array();
4708 $imported = 1;
4709 while ($imported > 0) {
4710 $imported = 0;
4711 // Schema imports
4712 foreach ($this->schemas as $ns => $list) {
4713 foreach ($list as $xs) {
4714 $wsdlparts = parse_url($this->wsdl); // this is bogusly simple!
4715 foreach ($xs->imports as $ns2 => $list2) {
4716 for ($ii = 0; $ii < count($list2); $ii++) {
4717 if (! $list2[$ii]['loaded']) {
4718 $this->schemas[$ns]->imports[$ns2][$ii]['loaded'] = true;
4719 $url = $list2[$ii]['location'];
4720 if ($url != '') {
4721 $urlparts = parse_url($url);
4722 if (!isset($urlparts['host'])) {
4723 $url = $wsdlparts['scheme'] . '://' . $wsdlparts['host'] . (isset($wsdlparts['port']) ? ':' . $wsdlparts['port'] : '') .
4724 substr($wsdlparts['path'], 0, strrpos($wsdlparts['path'], '/') + 1) . $urlparts['path'];
4725 }
4726 if (! in_array($url, $imported_urls)) {
4727 $this->parseWSDL($url);
4728 $imported++;
4729 $imported_urls[] = $url;
4730 }
4731 } else {
4732 $this->debug("Unexpected scenario: empty URL for unloaded import");
4733 }
4734 }
4735 }
4736 }
4737 }
4738 }
4739 // WSDL imports
4740 $wsdlparts = parse_url($this->wsdl); // this is bogusly simple!
4741 foreach ($this->import as $ns => $list) {
4742 for ($ii = 0; $ii < count($list); $ii++) {
4743 if (! $list[$ii]['loaded']) {
4744 $this->import[$ns][$ii]['loaded'] = true;
4745 $url = $list[$ii]['location'];
4746 if ($url != '') {
4747 $urlparts = parse_url($url);
4748 if (!isset($urlparts['host'])) {
4749 $url = $wsdlparts['scheme'] . '://' . $wsdlparts['host'] . (isset($wsdlparts['port']) ? ':' . $wsdlparts['port'] : '') .
4750 substr($wsdlparts['path'], 0, strrpos($wsdlparts['path'], '/') + 1) . $urlparts['path'];
4751 }
4752 if (! in_array($url, $imported_urls)) {
4753 $this->parseWSDL($url);
4754 $imported++;
4755 $imported_urls[] = $url;
4756 }
4757 } else {
4758 $this->debug("Unexpected scenario: empty URL for unloaded import");
4759 }
4760 }
4761 }
4762 }
4763 }
4764 // add new data to operation data
4765 foreach ($this->bindings as $binding => $bindingData) {
4766 if (isset($bindingData['operations']) && is_array($bindingData['operations'])) {
4767 foreach ($bindingData['operations'] as $operation => $data) {
4768 $this->debug('post-parse data gathering for ' . $operation);
4769 $this->bindings[$binding]['operations'][$operation]['input'] =
4770 isset($this->bindings[$binding]['operations'][$operation]['input']) ?
4771 array_merge($this->bindings[$binding]['operations'][$operation]['input'], $this->portTypes[ $bindingData['portType'] ][$operation]['input']) :
4772 $this->portTypes[ $bindingData['portType'] ][$operation]['input'];
4773 $this->bindings[$binding]['operations'][$operation]['output'] =
4774 isset($this->bindings[$binding]['operations'][$operation]['output']) ?
4775 array_merge($this->bindings[$binding]['operations'][$operation]['output'], $this->portTypes[ $bindingData['portType'] ][$operation]['output']) :
4776 $this->portTypes[ $bindingData['portType'] ][$operation]['output'];
4777 if (isset($this->messages[ $this->bindings[$binding]['operations'][$operation]['input']['message'] ])) {
4778 $this->bindings[$binding]['operations'][$operation]['input']['parts'] = $this->messages[ $this->bindings[$binding]['operations'][$operation]['input']['message'] ];
4779 }
4780 if (isset($this->messages[ $this->bindings[$binding]['operations'][$operation]['output']['message'] ])) {
4781 $this->bindings[$binding]['operations'][$operation]['output']['parts'] = $this->messages[ $this->bindings[$binding]['operations'][$operation]['output']['message'] ];
4782 }
4783 // Set operation style if necessary, but do not override one already provided
4784 if (isset($bindingData['style']) && !isset($this->bindings[$binding]['operations'][$operation]['style'])) {
4785 $this->bindings[$binding]['operations'][$operation]['style'] = $bindingData['style'];
4786 }
4787 $this->bindings[$binding]['operations'][$operation]['transport'] = isset($bindingData['transport']) ? $bindingData['transport'] : '';
4788 $this->bindings[$binding]['operations'][$operation]['documentation'] = isset($this->portTypes[ $bindingData['portType'] ][$operation]['documentation']) ? $this->portTypes[ $bindingData['portType'] ][$operation]['documentation'] : '';
4789 $this->bindings[$binding]['operations'][$operation]['endpoint'] = isset($bindingData['endpoint']) ? $bindingData['endpoint'] : '';
4790 }
4791 }
4792 }
4793 }
4794
4801 public function parseWSDL($wsdl = '')
4802 {
4803 $this->debug("parse WSDL at path=$wsdl");
4804
4805 if ($wsdl == '') {
4806 $this->debug('no wsdl passed to parseWSDL()!!');
4807 $this->setError('no wsdl passed to parseWSDL()!!');
4808 return false;
4809 }
4810
4811 // parse $wsdl for url format
4812 $wsdl_props = parse_url($wsdl);
4813
4814 if (isset($wsdl_props['scheme']) && ($wsdl_props['scheme'] == 'http' || $wsdl_props['scheme'] == 'https')) {
4815 $this->debug('getting WSDL http(s) URL ' . $wsdl);
4816 // get wsdl
4817 $tr = new soap_transport_http($wsdl, $this->curl_options, $this->use_curl);
4818 $tr->request_method = 'GET';
4819 $tr->useSOAPAction = false;
4820 if ($this->proxyhost && $this->proxyport) {
4821 $tr->setProxy($this->proxyhost, $this->proxyport, $this->proxyusername, $this->proxypassword);
4822 }
4823 if ($this->authtype != '') {
4824 $tr->setCredentials($this->username, $this->password, $this->authtype, array(), $this->certRequest);
4825 }
4826 $tr->setEncoding('gzip, deflate');
4827 $wsdl_string = $tr->send('', $this->timeout, $this->response_timeout);
4828 //$this->debug("WSDL request\n" . $tr->outgoing_payload);
4829 //$this->debug("WSDL response\n" . $tr->incoming_payload);
4830 $this->appendDebug($tr->getDebug());
4831 // catch errors
4832 if ($err = $tr->getError()) {
4833 $errstr = 'HTTP ERROR: ' . $err;
4834 $this->debug($errstr);
4835 $this->setError($errstr);
4836 unset($tr);
4837 return false;
4838 }
4839 unset($tr);
4840 $this->debug("got WSDL URL");
4841 } else {
4842 // $wsdl is not http(s), so treat it as a file URL or plain file path
4843 if (isset($wsdl_props['scheme']) && ($wsdl_props['scheme'] == 'file') && isset($wsdl_props['path'])) {
4844 $path = isset($wsdl_props['host']) ? ($wsdl_props['host'] . ':' . $wsdl_props['path']) : $wsdl_props['path'];
4845 } else {
4846 $path = $wsdl;
4847 }
4848 $this->debug('getting WSDL file ' . $path);
4849 if ($fp = @fopen($path, 'r')) {
4850 $wsdl_string = '';
4851 while ($data = fread($fp, 32768)) {
4852 $wsdl_string .= $data;
4853 }
4854 fclose($fp);
4855 } else {
4856 $errstr = "Bad path to WSDL file $path";
4857 $this->debug($errstr);
4858 $this->setError($errstr);
4859 return false;
4860 }
4861 }
4862 $this->debug('Parse WSDL');
4863 // end new code added
4864 // Create an XML parser.
4865 $this->parser = xml_parser_create();
4866 // Set the options for parsing the XML data.
4867 // xml_parser_set_option($parser, XML_OPTION_SKIP_WHITE, 1);
4868 xml_parser_set_option($this->parser, XML_OPTION_CASE_FOLDING, 0);
4869 // Set the object for the parser.
4870 xml_set_object($this->parser, $this);
4871 // Set the element handlers for the parser.
4872 xml_set_element_handler($this->parser, 'start_element', 'end_element');
4873 xml_set_character_data_handler($this->parser, 'character_data');
4874 // Parse the XML file.
4875 if (!xml_parse($this->parser, $wsdl_string, true)) {
4876 // Display an error message.
4877 $errstr = sprintf(
4878 'XML error parsing WSDL from %s on line %d: %s',
4879 $wsdl,
4880 xml_get_current_line_number($this->parser),
4881 xml_error_string(xml_get_error_code($this->parser))
4882 );
4883 $this->debug($errstr);
4884 $this->debug("XML payload:\n" . $wsdl_string);
4885 $this->setError($errstr);
4886 return false;
4887 }
4888 // free the parser
4889 xml_parser_free($this->parser);
4890 $this->debug('Parsing WSDL done');
4891 // catch wsdl parse errors
4892 if ($this->getError()) {
4893 return false;
4894 }
4895 return true;
4896 }
4897
4906 public function start_element($parser, $name, $attrs)
4907 {
4908 if ($this->status == 'schema') {
4909 $this->currentSchema->schemaStartElement($parser, $name, $attrs);
4910 $this->appendDebug($this->currentSchema->getDebug());
4911 $this->currentSchema->clearDebug();
4912 } elseif (preg_match('/schema$/', $name)) {
4913 $this->debug('Parsing WSDL schema');
4914 // $this->debug("startElement for $name ($attrs[name]). status = $this->status (".$this->getLocalPart($name).")");
4915 $this->status = 'schema';
4916 $this->currentSchema = new nusoap_xmlschema('', '', $this->namespaces);
4917 $this->currentSchema->schemaStartElement($parser, $name, $attrs);
4918 $this->appendDebug($this->currentSchema->getDebug());
4919 $this->currentSchema->clearDebug();
4920 } else {
4921 // position in the total number of elements, starting from 0
4922 $pos = $this->position++;
4923 $depth = $this->depth++;
4924 // set self as current value for this depth
4925 $this->depth_array[$depth] = $pos;
4926 $this->message[$pos] = array('cdata' => '');
4927 // process attributes
4928 if (count($attrs) > 0) {
4929 // register namespace declarations
4930 foreach ($attrs as $k => $v) {
4931 if (preg_match('/^xmlns/', $k)) {
4932 if ($ns_prefix = substr(strrchr($k, ':'), 1)) {
4933 $this->namespaces[$ns_prefix] = $v;
4934 } else {
4935 $this->namespaces['ns' . (count($this->namespaces) + 1)] = $v;
4936 }
4937 if ($v == 'http://www.w3.org/2001/XMLSchema' || $v == 'http://www.w3.org/1999/XMLSchema' || $v == 'http://www.w3.org/2000/10/XMLSchema') {
4938 $this->XMLSchemaVersion = $v;
4939 $this->namespaces['xsi'] = $v . '-instance';
4940 }
4941 }
4942 }
4943 // expand each attribute prefix to its namespace
4944 foreach ($attrs as $k => $v) {
4945 $k = strpos($k, ':') ? $this->expandQname($k) : $k;
4946 if ($k != 'location' && $k != 'soapAction' && $k != 'namespace') {
4947 $v = strpos($v, ':') ? $this->expandQname($v) : $v;
4948 }
4949 $eAttrs[$k] = $v;
4950 }
4951 $attrs = $eAttrs;
4952 } else {
4953 $attrs = array();
4954 }
4955 // get element prefix, namespace and name
4956 if (preg_match('/:/', $name)) {
4957 // get ns prefix
4958 $prefix = substr($name, 0, strpos($name, ':'));
4959 // get ns
4960 $namespace = isset($this->namespaces[$prefix]) ? $this->namespaces[$prefix] : '';
4961 // get unqualified name
4962 $name = substr(strstr($name, ':'), 1);
4963 }
4964 // process attributes, expanding any prefixes to namespaces
4965 // find status, register data
4966 switch ($this->status) {
4967 case 'message':
4968 if ($name == 'part') {
4969 if (isset($attrs['type'])) {
4970 $this->debug("msg " . $this->currentMessage . ": found part (with type) $attrs[name]: " . implode(',', $attrs));
4971 $this->messages[$this->currentMessage][$attrs['name']] = $attrs['type'];
4972 }
4973 if (isset($attrs['element'])) {
4974 $this->debug("msg " . $this->currentMessage . ": found part (with element) $attrs[name]: " . implode(',', $attrs));
4975 $this->messages[$this->currentMessage][$attrs['name']] = $attrs['element'] . '^';
4976 }
4977 }
4978 break;
4979 case 'portType':
4980 switch ($name) {
4981 case 'operation':
4982 $this->currentPortOperation = $attrs['name'];
4983 $this->debug("portType $this->currentPortType operation: $this->currentPortOperation");
4984 if (isset($attrs['parameterOrder'])) {
4985 $this->portTypes[$this->currentPortType][$attrs['name']]['parameterOrder'] = $attrs['parameterOrder'];
4986 }
4987 break;
4988 case 'documentation':
4989 $this->documentation = true;
4990 break;
4991 // merge input/output data
4992 default:
4993 $m = isset($attrs['message']) ? $this->getLocalPart($attrs['message']) : '';
4994 $this->portTypes[$this->currentPortType][$this->currentPortOperation][$name]['message'] = $m;
4995 break;
4996 }
4997 break;
4998 case 'binding':
4999 switch ($name) {
5000 case 'binding':
5001 // get ns prefix
5002 if (isset($attrs['style'])) {
5003 $this->bindings[$this->currentBinding]['prefix'] = $prefix;
5004 }
5005 $this->bindings[$this->currentBinding] = array_merge($this->bindings[$this->currentBinding], $attrs);
5006 break;
5007 case 'header':
5008 $this->bindings[$this->currentBinding]['operations'][$this->currentOperation][$this->opStatus]['headers'][] = $attrs;
5009 break;
5010 case 'operation':
5011 if (isset($attrs['soapAction'])) {
5012 $this->bindings[$this->currentBinding]['operations'][$this->currentOperation]['soapAction'] = $attrs['soapAction'];
5013 }
5014 if (isset($attrs['style'])) {
5015 $this->bindings[$this->currentBinding]['operations'][$this->currentOperation]['style'] = $attrs['style'];
5016 }
5017 if (isset($attrs['name'])) {
5018 $this->currentOperation = $attrs['name'];
5019 $this->debug("current binding operation: $this->currentOperation");
5020 $this->bindings[$this->currentBinding]['operations'][$this->currentOperation]['name'] = $attrs['name'];
5021 $this->bindings[$this->currentBinding]['operations'][$this->currentOperation]['binding'] = $this->currentBinding;
5022 $this->bindings[$this->currentBinding]['operations'][$this->currentOperation]['endpoint'] = isset($this->bindings[$this->currentBinding]['endpoint']) ? $this->bindings[$this->currentBinding]['endpoint'] : '';
5023 }
5024 break;
5025 case 'input':
5026 $this->opStatus = 'input';
5027 break;
5028 case 'output':
5029 $this->opStatus = 'output';
5030 break;
5031 case 'body':
5032 if (isset($this->bindings[$this->currentBinding]['operations'][$this->currentOperation][$this->opStatus])) {
5033 $this->bindings[$this->currentBinding]['operations'][$this->currentOperation][$this->opStatus] = array_merge($this->bindings[$this->currentBinding]['operations'][$this->currentOperation][$this->opStatus], $attrs);
5034 } else {
5035 $this->bindings[$this->currentBinding]['operations'][$this->currentOperation][$this->opStatus] = $attrs;
5036 }
5037 break;
5038 }
5039 break;
5040 case 'service':
5041 switch ($name) {
5042 case 'port':
5043 $this->currentPort = $attrs['name'];
5044 $this->debug('current port: ' . $this->currentPort);
5045 $this->ports[$this->currentPort]['binding'] = $this->getLocalPart($attrs['binding']);
5046
5047 break;
5048 case 'address':
5049 $this->ports[$this->currentPort]['location'] = $attrs['location'];
5050 $this->ports[$this->currentPort]['bindingType'] = $namespace;
5051 $this->bindings[ $this->ports[$this->currentPort]['binding'] ]['bindingType'] = $namespace;
5052 $this->bindings[ $this->ports[$this->currentPort]['binding'] ]['endpoint'] = $attrs['location'];
5053 break;
5054 }
5055 break;
5056 }
5057 // set status
5058 switch ($name) {
5059 case 'import':
5060 if (isset($attrs['location'])) {
5061 $this->import[$attrs['namespace']][] = array('location' => $attrs['location'], 'loaded' => false);
5062 $this->debug('parsing import ' . $attrs['namespace'] . ' - ' . $attrs['location'] . ' (' . count($this->import[$attrs['namespace']]) . ')');
5063 } else {
5064 $this->import[$attrs['namespace']][] = array('location' => '', 'loaded' => true);
5065 if (! $this->getPrefixFromNamespace($attrs['namespace'])) {
5066 $this->namespaces['ns' . (count($this->namespaces)+1)] = $attrs['namespace'];
5067 }
5068 $this->debug('parsing import ' . $attrs['namespace'] . ' - [no location] (' . count($this->import[$attrs['namespace']]) . ')');
5069 }
5070 break;
5071 //wait for schema
5072 //case 'types':
5073 // $this->status = 'schema';
5074 // break;
5075 case 'message':
5076 $this->status = 'message';
5077 $this->messages[$attrs['name']] = array();
5078 $this->currentMessage = $attrs['name'];
5079 break;
5080 case 'portType':
5081 $this->status = 'portType';
5082 $this->portTypes[$attrs['name']] = array();
5083 $this->currentPortType = $attrs['name'];
5084 break;
5085 case "binding":
5086 if (isset($attrs['name'])) {
5087 // get binding name
5088 if (strpos($attrs['name'], ':')) {
5089 $this->currentBinding = $this->getLocalPart($attrs['name']);
5090 } else {
5091 $this->currentBinding = $attrs['name'];
5092 }
5093 $this->status = 'binding';
5094 $this->bindings[$this->currentBinding]['portType'] = $this->getLocalPart($attrs['type']);
5095 $this->debug("current binding: $this->currentBinding of portType: " . $attrs['type']);
5096 }
5097 break;
5098 case 'service':
5099 $this->serviceName = $attrs['name'];
5100 $this->status = 'service';
5101 $this->debug('current service: ' . $this->serviceName);
5102 break;
5103 case 'definitions':
5104 foreach ($attrs as $name => $value) {
5105 $this->wsdl_info[$name] = $value;
5106 }
5107 break;
5108 }
5109 }
5110 }
5111
5119 public function end_element($parser, $name)
5120 {
5121 // unset schema status
5122 if (/*preg_match('/types$/', $name) ||*/ preg_match('/schema$/', $name)) {
5123 $this->status = "";
5124 $this->appendDebug($this->currentSchema->getDebug());
5125 $this->currentSchema->clearDebug();
5126 $this->schemas[$this->currentSchema->schemaTargetNamespace][] = $this->currentSchema;
5127 $this->debug('Parsing WSDL schema done');
5128 }
5129 if ($this->status == 'schema') {
5130 $this->currentSchema->schemaEndElement($parser, $name);
5131 } else {
5132 // bring depth down a notch
5133 $this->depth--;
5134 }
5135 // end documentation
5136 if ($this->documentation) {
5137 //TODO: track the node to which documentation should be assigned; it can be a part, message, etc.
5138 //$this->portTypes[$this->currentPortType][$this->currentPortOperation]['documentation'] = $this->documentation;
5139 $this->documentation = false;
5140 }
5141 }
5142
5150 public function character_data($parser, $data)
5151 {
5152 $pos = isset($this->depth_array[$this->depth]) ? $this->depth_array[$this->depth] : 0;
5153 if (isset($this->message[$pos]['cdata'])) {
5154 $this->message[$pos]['cdata'] .= $data;
5155 }
5156 if ($this->documentation) {
5157 $this->documentation .= $data;
5158 }
5159 }
5160
5170 public function setCredentials($username, $password, $authtype = 'basic', $certRequest = array())
5171 {
5172 $this->debug("setCredentials username=$username authtype=$authtype certRequest=");
5173 $this->appendDebug($this->varDump($certRequest));
5174 $this->username = $username;
5175 $this->password = $password;
5176 $this->authtype = $authtype;
5177 $this->certRequest = $certRequest;
5178 }
5179
5180 public function getBindingData($binding)
5181 {
5182 if (is_array($this->bindings[$binding])) {
5183 return $this->bindings[$binding];
5184 }
5185 }
5186
5194 public function getOperations($bindingType = 'soap')
5195 {
5196 $ops = array();
5197 if ($bindingType == 'soap') {
5198 $bindingType = 'http://schemas.xmlsoap.org/wsdl/soap/';
5199 } elseif ($bindingType == 'soap12') {
5200 $bindingType = 'http://schemas.xmlsoap.org/wsdl/soap12/';
5201 }
5202 // loop thru ports
5203 foreach ($this->ports as $port => $portData) {
5204 // binding type of port matches parameter
5205 if ($portData['bindingType'] == $bindingType) {
5206 //$this->debug("getOperations for port $port");
5207 //$this->debug("port data: " . $this->varDump($portData));
5208 //$this->debug("bindings: " . $this->varDump($this->bindings[ $portData['binding'] ]));
5209 // merge bindings
5210 if (isset($this->bindings[ $portData['binding'] ]['operations'])) {
5211 $ops = array_merge($ops, $this->bindings[ $portData['binding'] ]['operations']);
5212 }
5213 }
5214 }
5215 return $ops;
5216 }
5217
5226 public function getOperationData($operation, $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 // get binding
5238 //foreach($this->bindings[ $portData['binding'] ]['operations'] as $bOperation => $opData) {
5239 foreach (array_keys($this->bindings[ $portData['binding'] ]['operations']) as $bOperation) {
5240 // note that we could/should also check the namespace here
5241 if ($operation == $bOperation) {
5242 $opData = $this->bindings[ $portData['binding'] ]['operations'][$operation];
5243 return $opData;
5244 }
5245 }
5246 }
5247 }
5248 }
5249
5258 public function getOperationDataForSoapAction($soapAction, $bindingType = 'soap')
5259 {
5260 if ($bindingType == 'soap') {
5261 $bindingType = 'http://schemas.xmlsoap.org/wsdl/soap/';
5262 } elseif ($bindingType == 'soap12') {
5263 $bindingType = 'http://schemas.xmlsoap.org/wsdl/soap12/';
5264 }
5265 // loop thru ports
5266 foreach ($this->ports as $port => $portData) {
5267 // binding type of port matches parameter
5268 if ($portData['bindingType'] == $bindingType) {
5269 // loop through operations for the binding
5270 foreach ($this->bindings[ $portData['binding'] ]['operations'] as $bOperation => $opData) {
5271 if ($opData['soapAction'] == $soapAction) {
5272 return $opData;
5273 }
5274 }
5275 }
5276 }
5277 }
5278
5297 public function getTypeDef($type, $ns)
5298 {
5299 $this->debug("in getTypeDef: type=$type, ns=$ns");
5300 if ((! $ns) && isset($this->namespaces['tns'])) {
5301 $ns = $this->namespaces['tns'];
5302 $this->debug("in getTypeDef: type namespace forced to $ns");
5303 }
5304 if (!isset($this->schemas[$ns])) {
5305 foreach ($this->schemas as $ns0 => $schema0) {
5306 if (strcasecmp($ns, $ns0) == 0) {
5307 $this->debug("in getTypeDef: replacing schema namespace $ns with $ns0");
5308 $ns = $ns0;
5309 break;
5310 }
5311 }
5312 }
5313 if (isset($this->schemas[$ns])) {
5314 $this->debug("in getTypeDef: have schema for namespace $ns");
5315 for ($i = 0; $i < count($this->schemas[$ns]); $i++) {
5316 $xs = &$this->schemas[$ns][$i];
5317 $t = $xs->getTypeDef($type);
5318 //$this->appendDebug($xs->getDebug());
5319 //$xs->clearDebug();
5320 if ($t) {
5321 if (!isset($t['phpType'])) {
5322 // get info for type to tack onto the element
5323 $uqType = substr($t['type'], strrpos($t['type'], ':') + 1);
5324 $ns = substr($t['type'], 0, strrpos($t['type'], ':'));
5325 $etype = $this->getTypeDef($uqType, $ns);
5326 if ($etype) {
5327 $this->debug("found type for [element] $type:");
5328 $this->debug($this->varDump($etype));
5329 if (isset($etype['phpType'])) {
5330 $t['phpType'] = $etype['phpType'];
5331 }
5332 if (isset($etype['elements'])) {
5333 $t['elements'] = $etype['elements'];
5334 }
5335 if (isset($etype['attrs'])) {
5336 $t['attrs'] = $etype['attrs'];
5337 }
5338 }
5339 }
5340 return $t;
5341 }
5342 }
5343 } else {
5344 $this->debug("in getTypeDef: do not have schema for namespace $ns");
5345 }
5346 return false;
5347 }
5348
5354 public function webDescription()
5355 {
5356 global $HTTP_SERVER_VARS;
5357
5358 if (isset($_SERVER)) {
5359 $PHP_SELF = $_SERVER['PHP_SELF'];
5360 } elseif (isset($HTTP_SERVER_VARS)) {
5361 $PHP_SELF = $HTTP_SERVER_VARS['PHP_SELF'];
5362 } else {
5363 $this->setError("Neither _SERVER nor HTTP_SERVER_VARS is available");
5364 }
5365 // begin-patch: https://mantis.ilias.de/view.php?id=28866
5366 $PHP_SELF = filter_var($PHP_SELF, FILTER_SANITIZE_STRING);
5367 // end-patch
5368
5369 $b = '
5370 <html><head><title>NuSOAP: ' . $this->serviceName . '</title>
5371 <style type="text/css">
5372 body { font-family: arial; color: #000000; background-color: #ffffff; margin: 0px 0px 0px 0px; }
5373 p { font-family: arial; color: #000000; margin-top: 0px; margin-bottom: 12px; }
5374 pre { background-color: silver; padding: 5px; font-family: Courier New; font-size: x-small; color: #000000;}
5375 ul { margin-top: 10px; margin-left: 20px; }
5376 li { list-style-type: none; margin-top: 10px; color: #000000; }
5377 .content{
5378 margin-left: 0px; padding-bottom: 2em; }
5379 .nav {
5380 padding-top: 10px; padding-bottom: 10px; padding-left: 15px; font-size: .70em;
5381 margin-top: 10px; margin-left: 0px; color: #000000;
5382 background-color: #ccccff; width: 20%; margin-left: 20px; margin-top: 20px; }
5383 .title {
5384 font-family: arial; font-size: 26px; color: #ffffff;
5385 background-color: #999999; width: 105%; margin-left: 0px;
5386 padding-top: 10px; padding-bottom: 10px; padding-left: 15px;}
5387 .hidden {
5388 position: absolute; visibility: hidden; z-index: 200; left: 250px; top: 100px;
5389 font-family: arial; overflow: hidden; width: 600;
5390 padding: 20px; font-size: 10px; background-color: #999999;
5391 layer-background-color:#FFFFFF; }
5392 a,a:active { color: charcoal; font-weight: bold; }
5393 a:visited { color: #666666; font-weight: bold; }
5394 a:hover { color: cc3300; font-weight: bold; }
5395 </style>
5396 <script language="JavaScript" type="text/javascript">
5397 <!--
5398 // POP-UP CAPTIONS...
5399 function lib_bwcheck(){ //Browsercheck (needed)
5400 this.ver=navigator.appVersion
5401 this.agent=navigator.userAgent
5402 this.dom=document.getElementById?1:0
5403 this.opera5=this.agent.indexOf("Opera 5")>-1
5404 this.ie5=(this.ver.indexOf("MSIE 5")>-1 && this.dom && !this.opera5)?1:0;
5405 this.ie6=(this.ver.indexOf("MSIE 6")>-1 && this.dom && !this.opera5)?1:0;
5406 this.ie4=(document.all && !this.dom && !this.opera5)?1:0;
5407 this.ie=this.ie4||this.ie5||this.ie6
5408 this.mac=this.agent.indexOf("Mac")>-1
5409 this.ns6=(this.dom && parseInt(this.ver) >= 5) ?1:0;
5410 this.ns4=(document.layers && !this.dom)?1:0;
5411 this.bw=(this.ie6 || this.ie5 || this.ie4 || this.ns4 || this.ns6 || this.opera5)
5412 return this
5413 }
5414 var bw = new lib_bwcheck()
5415 //Makes crossbrowser object.
5416 function makeObj(obj){
5417 this.evnt=bw.dom? document.getElementById(obj):bw.ie4?document.all[obj]:bw.ns4?document.layers[obj]:0;
5418 if(!this.evnt) return false
5419 this.css=bw.dom||bw.ie4?this.evnt.style:bw.ns4?this.evnt:0;
5420 this.wref=bw.dom||bw.ie4?this.evnt:bw.ns4?this.css.document:0;
5421 this.writeIt=b_writeIt;
5422 return this
5423 }
5424 // A unit of measure that will be added when setting the position of a layer.
5425 //var px = bw.ns4||window.opera?"":"px";
5426 function b_writeIt(text){
5427 if (bw.ns4){this.wref.write(text);this.wref.close()}
5428 else this.wref.innerHTML = text
5429 }
5430 //Shows the messages
5431 var oDesc;
5432 function popup(divid){
5433 if(oDesc = new makeObj(divid)){
5434 oDesc.css.visibility = "visible"
5435 }
5436 }
5437 function popout(){ // Hides message
5438 if(oDesc) oDesc.css.visibility = "hidden"
5439 }
5440 //-->
5441 </script>
5442 </head>
5443 <body>
5444 <div class=content>
5445 <br><br>
5446 <div class=title>' . $this->serviceName . '</div>
5447 <div class=nav>
5448 <p>View the <a href="' . $PHP_SELF . '?wsdl">WSDL</a> for the service.
5449 Click on an operation name to view it&apos;s details.</p>
5450 <ul>';
5451 foreach ($this->getOperations() as $op => $data) {
5452 // begin-patch: https://mantis.ilias.de/view.php?id=28866
5453 if (isset($data['endpoint'])) {
5454 $data['endpoint'] = filter_var($data['endpoint'], FILTER_SANITIZE_STRING);
5455 }
5456 // end-patch
5457 $b .= "<li><a href='#' onclick=\"popout();popup('$op')\">$op</a></li>";
5458 // create hidden div
5459 $b .= "<div id='$op' class='hidden'>
5460 <a href='#' onclick='popout()'><font color='#ffffff'>Close</font></a><br><br>";
5461 foreach ($data as $donnie => $marie) { // loop through opdata
5462 if ($donnie == 'input' || $donnie == 'output') { // show input/output data
5463 $b .= "<font color='white'>" . ucfirst($donnie) . ':</font><br>';
5464 foreach ($marie as $captain => $tenille) { // loop through data
5465 if ($captain == 'parts') { // loop thru parts
5466 $b .= "&nbsp;&nbsp;$captain:<br>";
5467 //if(is_array($tenille)){
5468 foreach ($tenille as $joanie => $chachi) {
5469 $b .= "&nbsp;&nbsp;&nbsp;&nbsp;$joanie: $chachi<br>";
5470 }
5471 //}
5472 } else {
5473 $b .= "&nbsp;&nbsp;$captain: $tenille<br>";
5474 }
5475 }
5476 } else {
5477 $b .= "<font color='white'>" . ucfirst($donnie) . ":</font> $marie<br>";
5478 }
5479 }
5480 $b .= '</div>';
5481 }
5482 $b .= '
5483 <ul>
5484 </div>
5485 </div></body></html>';
5486 return $b;
5487 }
5488
5496 public function serialize($debug = 0)
5497 {
5498 $xml = '<?xml version="1.0" encoding="ISO-8859-1"?>';
5499 $xml .= "\n<definitions";
5500 foreach ($this->namespaces as $k => $v) {
5501 $xml .= " xmlns:$k=\"$v\"";
5502 }
5503 // 10.9.02 - add poulter fix for wsdl and tns declarations
5504 if (isset($this->namespaces['wsdl'])) {
5505 $xml .= " xmlns=\"" . $this->namespaces['wsdl'] . "\"";
5506 }
5507 if (isset($this->namespaces['tns'])) {
5508 $xml .= " targetNamespace=\"" . $this->namespaces['tns'] . "\"";
5509 }
5510 $xml .= '>';
5511 // imports
5512 if (sizeof($this->import) > 0) {
5513 foreach ($this->import as $ns => $list) {
5514 foreach ($list as $ii) {
5515 if ($ii['location'] != '') {
5516 $xml .= '<import location="' . $ii['location'] . '" namespace="' . $ns . '" />';
5517 } else {
5518 $xml .= '<import namespace="' . $ns . '" />';
5519 }
5520 }
5521 }
5522 }
5523 // types
5524 if (count($this->schemas)>=1) {
5525 $xml .= "\n<types>\n";
5526 foreach ($this->schemas as $ns => $list) {
5527 foreach ($list as $xs) {
5528 $xml .= $xs->serializeSchema();
5529 }
5530 }
5531 $xml .= '</types>';
5532 }
5533 // messages
5534 if (count($this->messages) >= 1) {
5535 foreach ($this->messages as $msgName => $msgParts) {
5536 $xml .= "\n<message name=\"" . $msgName . '">';
5537 if (is_array($msgParts)) {
5538 foreach ($msgParts as $partName => $partType) {
5539 // print 'serializing '.$partType.', sv: '.$this->XMLSchemaVersion.'<br>';
5540 if (strpos($partType, ':')) {
5541 $typePrefix = $this->getPrefixFromNamespace($this->getPrefix($partType));
5542 } elseif (isset($this->typemap[$this->namespaces['xsd']][$partType])) {
5543 // print 'checking typemap: '.$this->XMLSchemaVersion.'<br>';
5544 $typePrefix = 'xsd';
5545 } else {
5546 foreach ($this->typemap as $ns => $types) {
5547 if (isset($types[$partType])) {
5548 $typePrefix = $this->getPrefixFromNamespace($ns);
5549 }
5550 }
5551 if (!isset($typePrefix)) {
5552 die("$partType has no namespace!");
5553 }
5554 }
5555 $ns = $this->getNamespaceFromPrefix($typePrefix);
5556 $localPart = $this->getLocalPart($partType);
5557 $typeDef = $this->getTypeDef($localPart, $ns);
5558 if (($typeDef['typeClass'] ?? '') == 'element') {
5559 $elementortype = 'element';
5560 if (substr($localPart, -1) == '^') {
5561 $localPart = substr($localPart, 0, -1);
5562 }
5563 } else {
5564 $elementortype = 'type';
5565 }
5566 $xml .= "\n" . ' <part name="' . $partName . '" ' . $elementortype . '="' . $typePrefix . ':' . $localPart . '" />';
5567 }
5568 }
5569 $xml .= '</message>';
5570 }
5571 }
5572 // bindings & porttypes
5573 if (count($this->bindings) >= 1) {
5574 $binding_xml = '';
5575 $portType_xml = '';
5576 foreach ($this->bindings as $bindingName => $attrs) {
5577 $binding_xml .= "\n<binding name=\"" . $bindingName . '" type="tns:' . $attrs['portType'] . '">';
5578 $binding_xml .= "\n" . ' <soap:binding style="' . $attrs['style'] . '" transport="' . $attrs['transport'] . '"/>';
5579 $portType_xml .= "\n<portType name=\"" . $attrs['portType'] . '">';
5580 foreach ($attrs['operations'] as $opName => $opParts) {
5581 $binding_xml .= "\n" . ' <operation name="' . $opName . '">';
5582 $binding_xml .= "\n" . ' <soap:operation soapAction="' . $opParts['soapAction'] . '" style="' . $opParts['style'] . '"/>';
5583 if (isset($opParts['input']['encodingStyle']) && $opParts['input']['encodingStyle'] != '') {
5584 $enc_style = ' encodingStyle="' . $opParts['input']['encodingStyle'] . '"';
5585 } else {
5586 $enc_style = '';
5587 }
5588 $binding_xml .= "\n" . ' <input><soap:body use="' . $opParts['input']['use'] . '" namespace="' . $opParts['input']['namespace'] . '"' . $enc_style . '/></input>';
5589 if (isset($opParts['output']['encodingStyle']) && $opParts['output']['encodingStyle'] != '') {
5590 $enc_style = ' encodingStyle="' . $opParts['output']['encodingStyle'] . '"';
5591 } else {
5592 $enc_style = '';
5593 }
5594 $binding_xml .= "\n" . ' <output><soap:body use="' . $opParts['output']['use'] . '" namespace="' . $opParts['output']['namespace'] . '"' . $enc_style . '/></output>';
5595 $binding_xml .= "\n" . ' </operation>';
5596 $portType_xml .= "\n" . ' <operation name="' . $opParts['name'] . '"';
5597 if (isset($opParts['parameterOrder'])) {
5598 $portType_xml .= ' parameterOrder="' . $opParts['parameterOrder'] . '"';
5599 }
5600 $portType_xml .= '>';
5601 if (isset($opParts['documentation']) && $opParts['documentation'] != '') {
5602 $portType_xml .= "\n" . ' <documentation>' . htmlspecialchars($opParts['documentation']) . '</documentation>';
5603 }
5604 $portType_xml .= "\n" . ' <input message="tns:' . $opParts['input']['message'] . '"/>';
5605 $portType_xml .= "\n" . ' <output message="tns:' . $opParts['output']['message'] . '"/>';
5606 $portType_xml .= "\n" . ' </operation>';
5607 }
5608 $portType_xml .= "\n" . '</portType>';
5609 $binding_xml .= "\n" . '</binding>';
5610 }
5611 $xml .= $portType_xml . $binding_xml;
5612 }
5613 // services
5614 $xml .= "\n<service name=\"" . $this->serviceName . '">';
5615 $has_client = isset($_GET['client_id']);
5616 if (count($this->ports) >= 1) {
5617 foreach ($this->ports as $pName => $attrs) {
5618 $xml .= "\n" . ' <port name="' . $pName . '" binding="tns:' . $attrs['binding'] . '">';
5619 $address = $attrs['location'] . ($debug || $has_client ? "?" : "")
5620 . ($debug ? 'debug=1' : '') . ($debug && $has_client ? "&amp;" : "")
5621 . ($has_client ? 'client_id=' . $_GET['client_id'] : '');
5622 $xml .= "\n" . ' <soap:address location="' . $address . '"/>';
5623 $xml .= "\n" . ' </port>';
5624 }
5625 }
5626
5627 $xml .= "\n" . '</service>';
5628 return $xml . "\n</definitions>";
5629 }
5630
5640 public function parametersMatchWrapped($type, &$parameters)
5641 {
5642 $this->debug("in parametersMatchWrapped type=$type, parameters=");
5643 $this->appendDebug($this->varDump($parameters));
5644
5645 // split type into namespace:unqualified-type
5646 if (strpos($type, ':')) {
5647 $uqType = substr($type, strrpos($type, ':') + 1);
5648 $ns = substr($type, 0, strrpos($type, ':'));
5649 $this->debug("in parametersMatchWrapped: got a prefixed type: $uqType, $ns");
5650 if ($this->getNamespaceFromPrefix($ns)) {
5651 $ns = $this->getNamespaceFromPrefix($ns);
5652 $this->debug("in parametersMatchWrapped: expanded prefixed type: $uqType, $ns");
5653 }
5654 } else {
5655 // TODO: should the type be compared to types in XSD, and the namespace
5656 // set to XSD if the type matches?
5657 $this->debug("in parametersMatchWrapped: No namespace for type $type");
5658 $ns = '';
5659 $uqType = $type;
5660 }
5661
5662 // get the type information
5663 if (!$typeDef = $this->getTypeDef($uqType, $ns)) {
5664 $this->debug("in parametersMatchWrapped: $type ($uqType) is not a supported type.");
5665 return false;
5666 }
5667 $this->debug("in parametersMatchWrapped: found typeDef=");
5668 $this->appendDebug($this->varDump($typeDef));
5669 if (substr($uqType, -1) == '^') {
5670 $uqType = substr($uqType, 0, -1);
5671 }
5672 $phpType = $typeDef['phpType'];
5673 $arrayType = (isset($typeDef['arrayType']) ? $typeDef['arrayType'] : '');
5674 $this->debug("in parametersMatchWrapped: uqType: $uqType, ns: $ns, phptype: $phpType, arrayType: $arrayType");
5675
5676 // we expect a complexType or element of complexType
5677 if ($phpType != 'struct') {
5678 $this->debug("in parametersMatchWrapped: not a struct");
5679 return false;
5680 }
5681
5682 // see whether the parameter names match the elements
5683 if (isset($typeDef['elements']) && is_array($typeDef['elements'])) {
5684 $elements = 0;
5685 $matches = 0;
5686 $change = false;
5687 if ($this->isArraySimpleOrStruct($parameters) == 'arraySimple' && count($parameters) == count($typeDef['elements'])) {
5688 $this->debug("in parametersMatchWrapped: (wrapped return value kludge) correct number of elements in simple array, so change array and wrap");
5689 $change = true;
5690 }
5691 foreach ($typeDef['elements'] as $name => $attrs) {
5692 if ($change) {
5693 $this->debug("in parametersMatchWrapped: change parameter $element to name $name");
5694 $parameters[$name] = $parameters[$elements];
5695 unset($parameters[$elements]);
5696 $matches++;
5697 } elseif (isset($parameters[$name])) {
5698 $this->debug("in parametersMatchWrapped: have parameter named $name");
5699 $matches++;
5700 } else {
5701 $this->debug("in parametersMatchWrapped: do not have parameter named $name");
5702 }
5703 $elements++;
5704 }
5705
5706 $this->debug("in parametersMatchWrapped: $matches parameter names match $elements wrapped parameter names");
5707 if ($matches == 0) {
5708 return false;
5709 }
5710 return true;
5711 }
5712
5713 // since there are no elements for the type, if the user passed no
5714 // parameters, the parameters match wrapped.
5715 $this->debug("in parametersMatchWrapped: no elements type $ns:$uqType");
5716 return count($parameters) == 0;
5717 }
5718
5734 public function serializeRPCParameters($operation, $direction, $parameters, $bindingType = 'soap')
5735 {
5736 $this->debug("in serializeRPCParameters: operation=$operation, direction=$direction, XMLSchemaVersion=$this->XMLSchemaVersion, bindingType=$bindingType");
5737 $this->appendDebug('parameters=' . $this->varDump($parameters));
5738
5739 if ($direction != 'input' && $direction != 'output') {
5740 $this->debug('The value of the \$direction argument needs to be either "input" or "output"');
5741 $this->setError('The value of the \$direction argument needs to be either "input" or "output"');
5742 return false;
5743 }
5744 if (!$opData = $this->getOperationData($operation, $bindingType)) {
5745 $this->debug('Unable to retrieve WSDL data for operation: ' . $operation . ' bindingType: ' . $bindingType);
5746 $this->setError('Unable to retrieve WSDL data for operation: ' . $operation . ' bindingType: ' . $bindingType);
5747 return false;
5748 }
5749 $this->debug('in serializeRPCParameters: opData:');
5750 $this->appendDebug($this->varDump($opData));
5751
5752 // Get encoding style for output and set to current
5753 $encodingStyle = 'http://schemas.xmlsoap.org/soap/encoding/';
5754 if (($direction == 'input') && isset($opData['output']['encodingStyle']) && ($opData['output']['encodingStyle'] != $encodingStyle)) {
5755 $encodingStyle = $opData['output']['encodingStyle'];
5756 $enc_style = $encodingStyle;
5757 }
5758
5759 // set input params
5760 $xml = '';
5761 if (isset($opData[$direction]['parts']) && sizeof($opData[$direction]['parts']) > 0) {
5762 $parts = &$opData[$direction]['parts'];
5763 $part_count = sizeof($parts);
5764 $style = $opData['style'];
5765 $use = $opData[$direction]['use'];
5766 $this->debug("have $part_count part(s) to serialize using $style/$use");
5767 if (is_array($parameters)) {
5768 $parametersArrayType = $this->isArraySimpleOrStruct($parameters);
5769 $parameter_count = count($parameters);
5770 $this->debug("have $parameter_count parameter(s) provided as $parametersArrayType to serialize");
5771 // check for Microsoft-style wrapped parameters
5772 if ($style == 'document' && $use == 'literal' && $part_count == 1 && isset($parts['parameters'])) {
5773 $this->debug('check whether the caller has wrapped the parameters');
5774 if ((($parametersArrayType == 'arrayStruct' || $parameter_count == 0) && !isset($parameters['parameters'])) || ($direction == 'output' && $parametersArrayType == 'arraySimple' && $parameter_count == 1)) {
5775 $this->debug('check whether caller\'s parameters match the wrapped ones');
5776 if ($this->parametersMatchWrapped($parts['parameters'], $parameters)) {
5777 $this->debug('wrap the parameters for the caller');
5778 $parameters = array('parameters' => $parameters);
5779 $parameter_count = 1;
5780 }
5781 }
5782 }
5783 foreach ($parts as $name => $type) {
5784 $this->debug("serializing part $name of type $type");
5785 // Track encoding style
5786 if (isset($opData[$direction]['encodingStyle']) && $encodingStyle != $opData[$direction]['encodingStyle']) {
5787 $encodingStyle = $opData[$direction]['encodingStyle'];
5788 $enc_style = $encodingStyle;
5789 } else {
5790 $enc_style = false;
5791 }
5792 // NOTE: add error handling here
5793 // if serializeType returns false, then catch global error and fault
5794 if ($parametersArrayType == 'arraySimple') {
5795 $p = array_shift($parameters);
5796 $this->debug('calling serializeType w/indexed param');
5797 $xml .= $this->serializeType($name, $type, $p, $use, $enc_style);
5798 } elseif (isset($parameters[$name])) {
5799 $this->debug('calling serializeType w/named param');
5800 $xml .= $this->serializeType($name, $type, $parameters[$name], $use, $enc_style);
5801 } else {
5802 // TODO: only send nillable
5803 $this->debug('calling serializeType w/null param');
5804 $xml .= $this->serializeType($name, $type, null, $use, $enc_style);
5805 }
5806 }
5807 } else {
5808 $this->debug('no parameters passed.');
5809 }
5810 }
5811 $this->debug("serializeRPCParameters returning: $xml");
5812 return $xml;
5813 }
5814
5829 public function serializeParameters($operation, $direction, $parameters)
5830 {
5831 $this->debug("in serializeParameters: operation=$operation, direction=$direction, XMLSchemaVersion=$this->XMLSchemaVersion");
5832 $this->appendDebug('parameters=' . $this->varDump($parameters));
5833
5834 if ($direction != 'input' && $direction != 'output') {
5835 $this->debug('The value of the \$direction argument needs to be either "input" or "output"');
5836 $this->setError('The value of the \$direction argument needs to be either "input" or "output"');
5837 return false;
5838 }
5839 if (!$opData = $this->getOperationData($operation)) {
5840 $this->debug('Unable to retrieve WSDL data for operation: ' . $operation);
5841 $this->setError('Unable to retrieve WSDL data for operation: ' . $operation);
5842 return false;
5843 }
5844 $this->debug('opData:');
5845 $this->appendDebug($this->varDump($opData));
5846
5847 // Get encoding style for output and set to current
5848 $encodingStyle = 'http://schemas.xmlsoap.org/soap/encoding/';
5849 if (($direction == 'input') && isset($opData['output']['encodingStyle']) && ($opData['output']['encodingStyle'] != $encodingStyle)) {
5850 $encodingStyle = $opData['output']['encodingStyle'];
5851 $enc_style = $encodingStyle;
5852 }
5853
5854 // set input params
5855 $xml = '';
5856 if (isset($opData[$direction]['parts']) && sizeof($opData[$direction]['parts']) > 0) {
5857 $use = $opData[$direction]['use'];
5858 $this->debug("use=$use");
5859 $this->debug('got ' . count($opData[$direction]['parts']) . ' part(s)');
5860 if (is_array($parameters)) {
5861 $parametersArrayType = $this->isArraySimpleOrStruct($parameters);
5862 $this->debug('have ' . $parametersArrayType . ' parameters');
5863 foreach ($opData[$direction]['parts'] as $name => $type) {
5864 $this->debug('serializing part "' . $name . '" of type "' . $type . '"');
5865 // Track encoding style
5866 if (isset($opData[$direction]['encodingStyle']) && $encodingStyle != $opData[$direction]['encodingStyle']) {
5867 $encodingStyle = $opData[$direction]['encodingStyle'];
5868 $enc_style = $encodingStyle;
5869 } else {
5870 $enc_style = false;
5871 }
5872 // NOTE: add error handling here
5873 // if serializeType returns false, then catch global error and fault
5874 if ($parametersArrayType == 'arraySimple') {
5875 $p = array_shift($parameters);
5876 $this->debug('calling serializeType w/indexed param');
5877 $xml .= $this->serializeType($name, $type, $p, $use, $enc_style);
5878 } elseif (isset($parameters[$name])) {
5879 $this->debug('calling serializeType w/named param');
5880 $xml .= $this->serializeType($name, $type, $parameters[$name], $use, $enc_style);
5881 } else {
5882 // TODO: only send nillable
5883 $this->debug('calling serializeType w/null param');
5884 $xml .= $this->serializeType($name, $type, null, $use, $enc_style);
5885 }
5886 }
5887 } else {
5888 $this->debug('no parameters passed.');
5889 }
5890 }
5891 $this->debug("serializeParameters returning: $xml");
5892 return $xml;
5893 }
5894
5907 public function serializeType($name, $type, $value, $use='encoded', $encodingStyle=false, $unqualified=false)
5908 {
5909 $this->debug("in serializeType: name=$name, type=$type, use=$use, encodingStyle=$encodingStyle, unqualified=" . ($unqualified ? "unqualified" : "qualified"));
5910 $this->appendDebug("value=" . $this->varDump($value));
5911 if ($use == 'encoded' && $encodingStyle) {
5912 $encodingStyle = ' SOAP-ENV:encodingStyle="' . $encodingStyle . '"';
5913 }
5914
5915 // if a soapval has been supplied, let its type override the WSDL
5916 if (is_object($value) && get_class($value) == 'soapval') {
5917 if ($value->type_ns) {
5918 $type = $value->type_ns . ':' . $value->type;
5919 $forceType = true;
5920 $this->debug("in serializeType: soapval overrides type to $type");
5921 } elseif ($value->type) {
5922 $type = $value->type;
5923 $forceType = true;
5924 $this->debug("in serializeType: soapval overrides type to $type");
5925 } else {
5926 $forceType = false;
5927 $this->debug("in serializeType: soapval does not override type");
5928 }
5929 $attrs = $value->attributes;
5930 $value = $value->value;
5931 $this->debug("in serializeType: soapval overrides value to $value");
5932 if ($attrs) {
5933 if (!is_array($value)) {
5934 $value['!'] = $value;
5935 }
5936 foreach ($attrs as $n => $v) {
5937 $value['!' . $n] = $v;
5938 }
5939 $this->debug("in serializeType: soapval provides attributes");
5940 }
5941 } else {
5942 $forceType = false;
5943 }
5944
5945 $xml = '';
5946 if (strpos($type, ':')) {
5947 $uqType = substr($type, strrpos($type, ':') + 1);
5948 $ns = substr($type, 0, strrpos($type, ':'));
5949 $this->debug("in serializeType: got a prefixed type: $uqType, $ns");
5950 if ($this->getNamespaceFromPrefix($ns)) {
5951 $ns = $this->getNamespaceFromPrefix($ns);
5952 $this->debug("in serializeType: expanded prefixed type: $uqType, $ns");
5953 }
5954
5955 if ($ns == $this->XMLSchemaVersion || $ns == 'http://schemas.xmlsoap.org/soap/encoding/') {
5956 $this->debug('in serializeType: type namespace indicates XML Schema or SOAP Encoding type');
5957 if ($unqualified && $use == 'literal') {
5958 $elementNS = " xmlns=\"\"";
5959 } else {
5960 $elementNS = '';
5961 }
5962 if (is_null($value)) {
5963 if ($use == 'literal') {
5964 // TODO: depends on minOccurs
5965 $xml = "<$name$elementNS/>";
5966 } else {
5967 // TODO: depends on nillable, which should be checked before calling this method
5968 $xml = "<$name$elementNS xsi:nil=\"true\" xsi:type=\"" . $this->getPrefixFromNamespace($ns) . ":$uqType\"/>";
5969 }
5970 $this->debug("in serializeType: returning: $xml");
5971 return $xml;
5972 }
5973 if ($uqType == 'Array') {
5974 // JBoss/Axis does this sometimes
5975 return $this->serialize_val($value, $name, false, false, false, false, $use);
5976 }
5977 if ($uqType == 'boolean') {
5978 if ((is_string($value) && $value == 'false') || (! $value)) {
5979 $value = 'false';
5980 } else {
5981 $value = 'true';
5982 }
5983 }
5984 if ($uqType == 'string' && gettype($value) == 'string') {
5985 $value = $this->expandEntities($value);
5986 }
5987 if (($uqType == 'long' || $uqType == 'unsignedLong') && gettype($value) == 'double') {
5988 $value = sprintf("%.0lf", $value);
5989 }
5990 // it's a scalar
5991 // TODO: what about null/nil values?
5992 // check type isn't a custom type extending xmlschema namespace
5993 if (!$this->getTypeDef($uqType, $ns)) {
5994 if ($use == 'literal') {
5995 if ($forceType) {
5996 $xml = "<$name$elementNS xsi:type=\"" . $this->getPrefixFromNamespace($ns) . ":$uqType\">$value</$name>";
5997 } else {
5998 $xml = "<$name$elementNS>$value</$name>";
5999 }
6000 } else {
6001 $xml = "<$name$elementNS xsi:type=\"" . $this->getPrefixFromNamespace($ns) . ":$uqType\"$encodingStyle>$value</$name>";
6002 }
6003 $this->debug("in serializeType: returning: $xml");
6004 return $xml;
6005 }
6006 $this->debug('custom type extends XML Schema or SOAP Encoding namespace (yuck)');
6007 } elseif ($ns == 'http://xml.apache.org/xml-soap') {
6008 $this->debug('in serializeType: appears to be Apache SOAP type');
6009 if ($uqType == 'Map') {
6010 $tt_prefix = $this->getPrefixFromNamespace('http://xml.apache.org/xml-soap');
6011 if (! $tt_prefix) {
6012 $this->debug('in serializeType: Add namespace for Apache SOAP type');
6013 $tt_prefix = 'ns' . rand(1000, 9999);
6014 $this->namespaces[$tt_prefix] = 'http://xml.apache.org/xml-soap';
6015 // force this to be added to usedNamespaces
6016 $tt_prefix = $this->getPrefixFromNamespace('http://xml.apache.org/xml-soap');
6017 }
6018 $contents = '';
6019 foreach ($value as $k => $v) {
6020 $this->debug("serializing map element: key $k, value $v");
6021 $contents .= '<item>';
6022 $contents .= $this->serialize_val($k, 'key', false, false, false, false, $use);
6023 $contents .= $this->serialize_val($v, 'value', false, false, false, false, $use);
6024 $contents .= '</item>';
6025 }
6026 if ($use == 'literal') {
6027 if ($forceType) {
6028 $xml = "<$name xsi:type=\"" . $tt_prefix . ":$uqType\">$contents</$name>";
6029 } else {
6030 $xml = "<$name>$contents</$name>";
6031 }
6032 } else {
6033 $xml = "<$name xsi:type=\"" . $tt_prefix . ":$uqType\"$encodingStyle>$contents</$name>";
6034 }
6035 $this->debug("in serializeType: returning: $xml");
6036 return $xml;
6037 }
6038 $this->debug('in serializeType: Apache SOAP type, but only support Map');
6039 }
6040 } else {
6041 // TODO: should the type be compared to types in XSD, and the namespace
6042 // set to XSD if the type matches?
6043 $this->debug("in serializeType: No namespace for type $type");
6044 $ns = '';
6045 $uqType = $type;
6046 }
6047 if (!$typeDef = $this->getTypeDef($uqType, $ns)) {
6048 $this->setError("$type ($uqType) is not a supported type.");
6049 $this->debug("in serializeType: $type ($uqType) is not a supported type.");
6050 return false;
6051 } else {
6052 $this->debug("in serializeType: found typeDef");
6053 $this->appendDebug('typeDef=' . $this->varDump($typeDef));
6054 if (substr($uqType, -1) == '^') {
6055 $uqType = substr($uqType, 0, -1);
6056 }
6057 }
6058 $phpType = $typeDef['phpType'];
6059 $this->debug("in serializeType: uqType: $uqType, ns: $ns, phptype: $phpType, arrayType: " . (isset($typeDef['arrayType']) ? $typeDef['arrayType'] : ''));
6060 // if php type == struct, map value to the <all> element names
6061 if ($phpType == 'struct') {
6062 if (isset($typeDef['typeClass']) && $typeDef['typeClass'] == 'element') {
6063 $elementName = $uqType;
6064 if (isset($typeDef['form']) && ($typeDef['form'] == 'qualified')) {
6065 $elementNS = " xmlns=\"$ns\"";
6066 } else {
6067 $elementNS = " xmlns=\"\"";
6068 }
6069 } else {
6070 $elementName = $name;
6071 if ($unqualified) {
6072 $elementNS = " xmlns=\"\"";
6073 } else {
6074 $elementNS = '';
6075 }
6076 }
6077 if (is_null($value)) {
6078 if ($use == 'literal') {
6079 // TODO: depends on minOccurs
6080 $xml = "<$elementName$elementNS/>";
6081 } else {
6082 $xml = "<$elementName$elementNS xsi:nil=\"true\" xsi:type=\"" . $this->getPrefixFromNamespace($ns) . ":$uqType\"/>";
6083 }
6084 $this->debug("in serializeType: returning: $xml");
6085 return $xml;
6086 }
6087 if (is_object($value)) {
6088 $value = get_object_vars($value);
6089 }
6090 if (is_array($value)) {
6091 $elementAttrs = $this->serializeComplexTypeAttributes($typeDef, $value, $ns, $uqType);
6092 if ($use == 'literal') {
6093 if ($forceType) {
6094 $xml = "<$elementName$elementNS$elementAttrs xsi:type=\"" . $this->getPrefixFromNamespace($ns) . ":$uqType\">";
6095 } else {
6096 $xml = "<$elementName$elementNS$elementAttrs>";
6097 }
6098 } else {
6099 $xml = "<$elementName$elementNS$elementAttrs xsi:type=\"" . $this->getPrefixFromNamespace($ns) . ":$uqType\"$encodingStyle>";
6100 }
6101
6102 $xml .= $this->serializeComplexTypeElements($typeDef, $value, $ns, $uqType, $use, $encodingStyle);
6103 $xml .= "</$elementName>";
6104 } else {
6105 $this->debug("in serializeType: phpType is struct, but value is not an array");
6106 $this->setError("phpType is struct, but value is not an array: see debug output for details");
6107 $xml = '';
6108 }
6109 } elseif ($phpType == 'array') {
6110 if (isset($typeDef['form']) && ($typeDef['form'] == 'qualified')) {
6111 $elementNS = " xmlns=\"$ns\"";
6112 } else {
6113 if ($unqualified) {
6114 $elementNS = " xmlns=\"\"";
6115 } else {
6116 $elementNS = '';
6117 }
6118 }
6119 if (is_null($value)) {
6120 if ($use == 'literal') {
6121 // TODO: depends on minOccurs
6122 $xml = "<$name$elementNS/>";
6123 } else {
6124 $xml = "<$name$elementNS xsi:nil=\"true\" xsi:type=\"" .
6125 $this->getPrefixFromNamespace('http://schemas.xmlsoap.org/soap/encoding/') .
6126 ":Array\" " .
6127 $this->getPrefixFromNamespace('http://schemas.xmlsoap.org/soap/encoding/') .
6128 ':arrayType="' .
6129 $this->getPrefixFromNamespace($this->getPrefix($typeDef['arrayType'])) .
6130 ':' .
6131 $this->getLocalPart($typeDef['arrayType']) . "[0]\"/>";
6132 }
6133 $this->debug("in serializeType: returning: $xml");
6134 return $xml;
6135 }
6136 if (isset($typeDef['multidimensional'])) {
6137 $nv = array();
6138 foreach ($value as $v) {
6139 $cols = ',' . sizeof($v);
6140 $nv = array_merge($nv, $v);
6141 }
6142 $value = $nv;
6143 } else {
6144 $cols = '';
6145 }
6146 if (is_array($value) && sizeof($value) >= 1) {
6147 $rows = sizeof($value);
6148 $contents = '';
6149 foreach ($value as $k => $v) {
6150 $this->debug("serializing array element: $k, $v of type: $typeDef[arrayType]");
6151 //if (strpos($typeDef['arrayType'], ':') ) {
6152 if (!in_array($typeDef['arrayType'], $this->typemap['http://www.w3.org/2001/XMLSchema'])) {
6153 $contents .= $this->serializeType('item', $typeDef['arrayType'], $v, $use);
6154 } else {
6155 $contents .= $this->serialize_val($v, 'item', $typeDef['arrayType'], null, $this->XMLSchemaVersion, false, $use);
6156 }
6157 }
6158 } else {
6159 $rows = 0;
6160 $contents = null;
6161 }
6162 // TODO: for now, an empty value will be serialized as a zero element
6163 // array. Revisit this when coding the handling of null/nil values.
6164 if ($use == 'literal') {
6165 $xml = "<$name$elementNS>"
6166 . $contents
6167 . "</$name>";
6168 } else {
6169 $xml = "<$name$elementNS xsi:type=\"" . $this->getPrefixFromNamespace('http://schemas.xmlsoap.org/soap/encoding/') . ':Array" ' .
6170 $this->getPrefixFromNamespace('http://schemas.xmlsoap.org/soap/encoding/')
6171 . ':arrayType="'
6172 . $this->getPrefixFromNamespace($this->getPrefix($typeDef['arrayType']))
6173 . ":" . $this->getLocalPart($typeDef['arrayType']) . "[$rows$cols]\">"
6174 . $contents
6175 . "</$name>";
6176 }
6177 } elseif ($phpType == 'scalar') {
6178 if (isset($typeDef['form']) && ($typeDef['form'] == 'qualified')) {
6179 $elementNS = " xmlns=\"$ns\"";
6180 } else {
6181 if ($unqualified) {
6182 $elementNS = " xmlns=\"\"";
6183 } else {
6184 $elementNS = '';
6185 }
6186 }
6187 if ($use == 'literal') {
6188 if ($forceType) {
6189 $xml = "<$name$elementNS xsi:type=\"" . $this->getPrefixFromNamespace($ns) . ":$uqType\">$value</$name>";
6190 } else {
6191 $xml = "<$name$elementNS>$value</$name>";
6192 }
6193 } else {
6194 $xml = "<$name$elementNS xsi:type=\"" . $this->getPrefixFromNamespace($ns) . ":$uqType\"$encodingStyle>$value</$name>";
6195 }
6196 }
6197 $this->debug("in serializeType: returning: $xml");
6198 return $xml;
6199 }
6200
6211 public function serializeComplexTypeAttributes($typeDef, $value, $ns, $uqType)
6212 {
6213 $xml = '';
6214 if (isset($typeDef['attrs']) && is_array($typeDef['attrs'])) {
6215 $this->debug("serialize attributes for XML Schema type $ns:$uqType");
6216 if (is_array($value)) {
6217 $xvalue = $value;
6218 } elseif (is_object($value)) {
6219 $xvalue = get_object_vars($value);
6220 } else {
6221 $this->debug("value is neither an array nor an object for XML Schema type $ns:$uqType");
6222 $xvalue = array();
6223 }
6224 foreach ($typeDef['attrs'] as $aName => $attrs) {
6225 if (isset($xvalue['!' . $aName])) {
6226 $xname = '!' . $aName;
6227 $this->debug("value provided for attribute $aName with key $xname");
6228 } elseif (isset($xvalue[$aName])) {
6229 $xname = $aName;
6230 $this->debug("value provided for attribute $aName with key $xname");
6231 } elseif (isset($attrs['default'])) {
6232 $xname = '!' . $aName;
6233 $xvalue[$xname] = $attrs['default'];
6234 $this->debug('use default value of ' . $xvalue[$aName] . ' for attribute ' . $aName);
6235 } else {
6236 $xname = '';
6237 $this->debug("no value provided for attribute $aName");
6238 }
6239 if ($xname) {
6240 $xml .= " $aName=\"" . $this->expandEntities($xvalue[$xname]) . "\"";
6241 }
6242 }
6243 } else {
6244 $this->debug("no attributes to serialize for XML Schema type $ns:$uqType");
6245 }
6246 if (isset($typeDef['extensionBase'])) {
6247 $ns = $this->getPrefix($typeDef['extensionBase']);
6248 $uqType = $this->getLocalPart($typeDef['extensionBase']);
6249 if ($this->getNamespaceFromPrefix($ns)) {
6250 $ns = $this->getNamespaceFromPrefix($ns);
6251 }
6252 if ($typeDef = $this->getTypeDef($uqType, $ns)) {
6253 $this->debug("serialize attributes for extension base $ns:$uqType");
6254 $xml .= $this->serializeComplexTypeAttributes($typeDef, $value, $ns, $uqType);
6255 } else {
6256 $this->debug("extension base $ns:$uqType is not a supported type");
6257 }
6258 }
6259 return $xml;
6260 }
6261
6274 public function serializeComplexTypeElements($typeDef, $value, $ns, $uqType, $use='encoded', $encodingStyle=false)
6275 {
6276 $xml = '';
6277 if (isset($typeDef['elements']) && is_array($typeDef['elements'])) {
6278 $this->debug("in serializeComplexTypeElements, serialize elements for XML Schema type $ns:$uqType");
6279 if (is_array($value)) {
6280 $xvalue = $value;
6281 } elseif (is_object($value)) {
6282 $xvalue = get_object_vars($value);
6283 } else {
6284 $this->debug("value is neither an array nor an object for XML Schema type $ns:$uqType");
6285 $xvalue = array();
6286 }
6287 // toggle whether all elements are present - ideally should validate against schema
6288 if (count($typeDef['elements']) != count($xvalue)) {
6289 $optionals = true;
6290 }
6291 foreach ($typeDef['elements'] as $eName => $attrs) {
6292 if (!isset($xvalue[$eName])) {
6293 if (isset($attrs['default'])) {
6294 $xvalue[$eName] = $attrs['default'];
6295 $this->debug('use default value of ' . $xvalue[$eName] . ' for element ' . $eName);
6296 }
6297 }
6298 // if user took advantage of a minOccurs=0, then only serialize named parameters
6299 if (isset($optionals)
6300 && (!isset($xvalue[$eName]))
6301 && ((!isset($attrs['nillable'])) || $attrs['nillable'] != 'true')
6302 ) {
6303 if (isset($attrs['minOccurs']) && $attrs['minOccurs'] <> '0') {
6304 $this->debug("apparent error: no value provided for element $eName with minOccurs=" . $attrs['minOccurs']);
6305 }
6306 // do nothing
6307 $this->debug("no value provided for complexType element $eName and element is not nillable, so serialize nothing");
6308 } else {
6309 // get value
6310 if (isset($xvalue[$eName])) {
6311 $v = $xvalue[$eName];
6312 } else {
6313 $v = null;
6314 }
6315 if (isset($attrs['form'])) {
6316 $unqualified = ($attrs['form'] == 'unqualified');
6317 } else {
6318 $unqualified = false;
6319 }
6320 if (isset($attrs['maxOccurs']) && ($attrs['maxOccurs'] == 'unbounded' || $attrs['maxOccurs'] > 1) && isset($v) && is_array($v) && $this->isArraySimpleOrStruct($v) == 'arraySimple') {
6321 $vv = $v;
6322 foreach ($vv as $k => $v) {
6323 if (isset($attrs['type']) || isset($attrs['ref'])) {
6324 // serialize schema-defined type
6325 $xml .= $this->serializeType($eName, isset($attrs['type']) ? $attrs['type'] : $attrs['ref'], $v, $use, $encodingStyle, $unqualified);
6326 } else {
6327 // serialize generic type (can this ever really happen?)
6328 $this->debug("calling serialize_val() for $v, $eName, false, false, false, false, $use");
6329 $xml .= $this->serialize_val($v, $eName, false, false, false, false, $use);
6330 }
6331 }
6332 } else {
6333 if (isset($attrs['type']) || isset($attrs['ref'])) {
6334 // serialize schema-defined type
6335 $xml .= $this->serializeType($eName, isset($attrs['type']) ? $attrs['type'] : $attrs['ref'], $v, $use, $encodingStyle, $unqualified);
6336 } else {
6337 // serialize generic type (can this ever really happen?)
6338 $this->debug("calling serialize_val() for $v, $eName, false, false, false, false, $use");
6339 $xml .= $this->serialize_val($v, $eName, false, false, false, false, $use);
6340 }
6341 }
6342 }
6343 }
6344 } else {
6345 $this->debug("no elements to serialize for XML Schema type $ns:$uqType");
6346 }
6347 if (isset($typeDef['extensionBase'])) {
6348 $ns = $this->getPrefix($typeDef['extensionBase']);
6349 $uqType = $this->getLocalPart($typeDef['extensionBase']);
6350 if ($this->getNamespaceFromPrefix($ns)) {
6351 $ns = $this->getNamespaceFromPrefix($ns);
6352 }
6353 if ($typeDef = $this->getTypeDef($uqType, $ns)) {
6354 $this->debug("serialize elements for extension base $ns:$uqType");
6355 $xml .= $this->serializeComplexTypeElements($typeDef, $value, $ns, $uqType, $use, $encodingStyle);
6356 } else {
6357 $this->debug("extension base $ns:$uqType is not a supported type");
6358 }
6359 }
6360 return $xml;
6361 }
6362
6377 public function addComplexType($name, $typeClass='complexType', $phpType='array', $compositor='', $restrictionBase='', $elements=array(), $attrs=array(), $arrayType='')
6378 {
6379 if (count($elements) > 0) {
6380 $eElements = array();
6381 foreach ($elements as $n => $e) {
6382 // expand each element
6383 $ee = array();
6384 foreach ($e as $k => $v) {
6385 $k = strpos($k, ':') ? $this->expandQname($k) : $k;
6386 $v = strpos($v, ':') ? $this->expandQname($v) : $v;
6387 $ee[$k] = $v;
6388 }
6389 $eElements[$n] = $ee;
6390 }
6391 $elements = $eElements;
6392 }
6393
6394 if (count($attrs) > 0) {
6395 foreach ($attrs as $n => $a) {
6396 // expand each attribute
6397 foreach ($a as $k => $v) {
6398 $k = strpos($k, ':') ? $this->expandQname($k) : $k;
6399 $v = strpos($v, ':') ? $this->expandQname($v) : $v;
6400 $aa[$k] = $v;
6401 }
6402 $eAttrs[$n] = $aa;
6403 }
6404 $attrs = $eAttrs;
6405 }
6406
6407 $restrictionBase = strpos($restrictionBase, ':') ? $this->expandQname($restrictionBase) : $restrictionBase;
6408 $arrayType = strpos($arrayType, ':') ? $this->expandQname($arrayType) : $arrayType;
6409
6410 $typens = isset($this->namespaces['types']) ? $this->namespaces['types'] : $this->namespaces['tns'];
6411 $this->schemas[$typens][0]->addComplexType($name, $typeClass, $phpType, $compositor, $restrictionBase, $elements, $attrs, $arrayType);
6412 }
6413
6425 public function addSimpleType($name, $restrictionBase='', $typeClass='simpleType', $phpType='scalar', $enumeration=array())
6426 {
6427 $restrictionBase = strpos($restrictionBase, ':') ? $this->expandQname($restrictionBase) : $restrictionBase;
6428
6429 $typens = isset($this->namespaces['types']) ? $this->namespaces['types'] : $this->namespaces['tns'];
6430 $this->schemas[$typens][0]->addSimpleType($name, $restrictionBase, $typeClass, $phpType, $enumeration);
6431 }
6432
6440 public function addElement($attrs)
6441 {
6442 $typens = isset($this->namespaces['types']) ? $this->namespaces['types'] : $this->namespaces['tns'];
6443 $this->schemas[$typens][0]->addElement($attrs);
6444 }
6445
6460 public function addOperation($name, $in = false, $out = false, $namespace = false, $soapaction = false, $style = 'rpc', $use = 'encoded', $documentation = '', $encodingStyle = '')
6461 {
6462 if ($use == 'encoded' && $encodingStyle == '') {
6463 $encodingStyle = 'http://schemas.xmlsoap.org/soap/encoding/';
6464 }
6465
6466 if ($style == 'document') {
6467 $elements = array();
6468 foreach ($in as $n => $t) {
6469 $elements[$n] = array('name' => $n, 'type' => $t);
6470 }
6471 $this->addComplexType($name . 'RequestType', 'complexType', 'struct', 'all', '', $elements);
6472 $this->addElement(array('name' => $name, 'type' => $name . 'RequestType'));
6473 $in = array('parameters' => 'tns:' . $name . '^');
6474
6475 $elements = array();
6476 foreach ($out as $n => $t) {
6477 $elements[$n] = array('name' => $n, 'type' => $t);
6478 }
6479 $this->addComplexType($name . 'ResponseType', 'complexType', 'struct', 'all', '', $elements);
6480 $this->addElement(array('name' => $name . 'Response', 'type' => $name . 'ResponseType', 'form' => 'qualified'));
6481 $out = array('parameters' => 'tns:' . $name . 'Response' . '^');
6482 }
6483
6484 // get binding
6485 $this->bindings[ $this->serviceName . 'Binding' ]['operations'][$name] =
6486 array(
6487 'name' => $name,
6488 'binding' => $this->serviceName . 'Binding',
6489 'endpoint' => $this->endpoint,
6490 'soapAction' => $soapaction,
6491 'style' => $style,
6492 'input' => array(
6493 'use' => $use,
6494 'namespace' => $namespace,
6495 'encodingStyle' => $encodingStyle,
6496 'message' => $name . 'Request',
6497 'parts' => $in),
6498 'output' => array(
6499 'use' => $use,
6500 'namespace' => $namespace,
6501 'encodingStyle' => $encodingStyle,
6502 'message' => $name . 'Response',
6503 'parts' => $out),
6504 'namespace' => $namespace,
6505 'transport' => 'http://schemas.xmlsoap.org/soap/http',
6506 'documentation' => $documentation);
6507 // add portTypes
6508 // add messages
6509 if ($in) {
6510 foreach ($in as $pName => $pType) {
6511 if (strpos($pType, ':')) {
6512 $pType = $this->getNamespaceFromPrefix($this->getPrefix($pType)) . ":" . $this->getLocalPart($pType);
6513 }
6514 $this->messages[$name . 'Request'][$pName] = $pType;
6515 }
6516 } else {
6517 $this->messages[$name . 'Request']= '0';
6518 }
6519 if ($out) {
6520 foreach ($out as $pName => $pType) {
6521 if (strpos($pType, ':')) {
6522 $pType = $this->getNamespaceFromPrefix($this->getPrefix($pType)) . ":" . $this->getLocalPart($pType);
6523 }
6524 $this->messages[$name . 'Response'][$pName] = $pType;
6525 }
6526 } else {
6527 $this->messages[$name . 'Response']= '0';
6528 }
6529 return true;
6530 }
6531}
6532?><?php
6533
6534
6535
6546{
6547 public $xml = '';
6548 public $xml_encoding = '';
6549 public $method = '';
6550 public $root_struct = '';
6553 public $root_header = '';
6554 public $document = ''; // incoming SOAP body (text)
6555 // determines where in the message we are (envelope,header,body,method)
6556 public $status = '';
6557 public $position = 0;
6558 public $depth = 0;
6560 public $namespaces = array();
6561 public $message = array();
6562 public $parent = '';
6563 public $fault = false;
6564 public $fault_code = '';
6565 public $fault_str = '';
6566 public $fault_detail = '';
6567 public $depth_array = array();
6568 public $debug_flag = true;
6569 public $soapresponse = null; // parsed SOAP Body
6570 public $soapheader = null; // parsed SOAP Header
6571 public $responseHeaders = ''; // incoming SOAP headers (text)
6572 public $body_position = 0;
6573 // for multiref parsing:
6574 // array of id => pos
6575 public $ids = array();
6576 // array of id => hrefs => pos
6577 public $multirefs = array();
6578 // toggle for auto-decoding element content
6579 public $decode_utf8 = true;
6580
6590 public function __construct($xml, $encoding='UTF-8', $method='', $decode_utf8=true)
6591 {
6593 $this->xml = $xml;
6594 $this->xml_encoding = $encoding;
6595 $this->method = $method;
6596 $this->decode_utf8 = $decode_utf8;
6597
6598 // Check whether content has been read.
6599 if (!empty($xml)) {
6600 // Check XML encoding
6601 $pos_xml = strpos($xml, '<?xml');
6602 if ($pos_xml !== false) {
6603 $xml_decl = substr($xml, $pos_xml, strpos($xml, '?>', $pos_xml + 2) - $pos_xml + 1);
6604 if (preg_match("/encoding=[\"']([^\"']*)[\"']/", $xml_decl, $res)) {
6605 $xml_encoding = $res[1];
6606 if (strtoupper($xml_encoding) != $encoding) {
6607 $err = "Charset from HTTP Content-Type '" . $encoding . "' does not match encoding from XML declaration '" . $xml_encoding . "'";
6608 $this->debug($err);
6609 if ($encoding != 'ISO-8859-1' || strtoupper($xml_encoding) != 'UTF-8') {
6610 $this->setError($err);
6611 return;
6612 }
6613 // when HTTP says ISO-8859-1 (the default) and XML says UTF-8 (the typical), assume the other endpoint is just sloppy and proceed
6614 } else {
6615 $this->debug('Charset from HTTP Content-Type matches encoding from XML declaration');
6616 }
6617 } else {
6618 $this->debug('No encoding specified in XML declaration');
6619 }
6620 } else {
6621 $this->debug('No XML declaration');
6622 }
6623 $this->debug('Entering nusoap_parser(), length=' . strlen($xml) . ', encoding=' . $encoding);
6624 // Create an XML parser - why not xml_parser_create_ns?
6625 $this->parser = xml_parser_create($this->xml_encoding);
6626 // Set the options for parsing the XML data.
6627 //xml_parser_set_option($parser, XML_OPTION_SKIP_WHITE, 1);
6628 xml_parser_set_option($this->parser, XML_OPTION_CASE_FOLDING, 0);
6629 xml_parser_set_option($this->parser, XML_OPTION_TARGET_ENCODING, $this->xml_encoding);
6630 // Set the object for the parser.
6631 xml_set_object($this->parser, $this);
6632 // Set the element handlers for the parser.
6633 xml_set_element_handler($this->parser, 'start_element', 'end_element');
6634 xml_set_character_data_handler($this->parser, 'character_data');
6635
6636 // Parse the XML file.
6637 if (!xml_parse($this->parser, $xml, true)) {
6638 // Display an error message.
6639 $err = sprintf(
6640 'XML error parsing SOAP payload on line %d: %s',
6641 xml_get_current_line_number($this->parser),
6642 xml_error_string(xml_get_error_code($this->parser))
6643 );
6644 $this->debug($err);
6645 $this->debug("XML payload:\n" . $xml);
6646 $this->setError($err);
6647 } else {
6648 $this->debug('parsed successfully, found root struct: ' . $this->root_struct . ' of name ' . $this->root_struct_name);
6649 // get final value
6650 $this->soapresponse = $this->message[$this->root_struct]['result'];
6651 // get header value
6652 if ($this->root_header != '' && isset($this->message[$this->root_header]['result'])) {
6653 $this->soapheader = $this->message[$this->root_header]['result'];
6654 }
6655 // resolve hrefs/ids
6656 if (sizeof($this->multirefs) > 0) {
6657 foreach ($this->multirefs as $id => $hrefs) {
6658 $this->debug('resolving multirefs for id: ' . $id);
6659 $idVal = $this->buildVal($this->ids[$id]);
6660 if (is_array($idVal) && isset($idVal['!id'])) {
6661 unset($idVal['!id']);
6662 }
6663 foreach ($hrefs as $refPos => $ref) {
6664 $this->debug('resolving href at pos ' . $refPos);
6665 $this->multirefs[$id][$refPos] = $idVal;
6666 }
6667 }
6668 }
6669 }
6670 xml_parser_free($this->parser);
6671 } else {
6672 $this->debug('xml was empty, didn\'t parse!');
6673 $this->setError('xml was empty, didn\'t parse!');
6674 }
6675 }
6676
6685 public function start_element($parser, $name, $attrs)
6686 {
6687 // position in a total number of elements, starting from 0
6688 // update class level pos
6689 $pos = $this->position++;
6690 // and set mine
6691 $this->message[$pos] = array('pos' => $pos,'children'=>'','cdata'=>'');
6692 // depth = how many levels removed from root?
6693 // set mine as current global depth and increment global depth value
6694 $this->message[$pos]['depth'] = $this->depth++;
6695
6696 // else add self as child to whoever the current parent is
6697 if ($pos != 0) {
6698 $this->message[$this->parent]['children'] .= '|' . $pos;
6699 }
6700 // set my parent
6701 $this->message[$pos]['parent'] = $this->parent;
6702 // set self as current parent
6703 $this->parent = $pos;
6704 // set self as current value for this depth
6705 $this->depth_array[$this->depth] = $pos;
6706 // get element prefix
6707 if (strpos($name, ':')) {
6708 // get ns prefix
6709 $prefix = substr($name, 0, strpos($name, ':'));
6710 // get unqualified name
6711 $name = substr(strstr($name, ':'), 1);
6712 }
6713 // set status
6714 if ($name == 'Envelope') {
6715 $this->status = 'envelope';
6716 } elseif ($name == 'Header' && $this->status = 'envelope') {
6717 $this->root_header = $pos;
6718 $this->status = 'header';
6719 } elseif ($name == 'Body' && $this->status = 'envelope') {
6720 $this->status = 'body';
6721 $this->body_position = $pos;
6722 // set method
6723 } elseif ($this->status == 'body' && $pos == ($this->body_position+1)) {
6724 $this->status = 'method';
6725 $this->root_struct_name = $name;
6726 $this->root_struct = $pos;
6727 $this->message[$pos]['type'] = 'struct';
6728 $this->debug("found root struct $this->root_struct_name, pos $this->root_struct");
6729 }
6730 // set my status
6731 $this->message[$pos]['status'] = $this->status;
6732 // set name
6733 $this->message[$pos]['name'] = htmlspecialchars($name);
6734 // set attrs
6735 $this->message[$pos]['attrs'] = $attrs;
6736
6737 // loop through atts, logging ns and type declarations
6738 $attstr = '';
6739 foreach ($attrs as $key => $value) {
6740 $key_prefix = $this->getPrefix($key);
6741 $key_localpart = $this->getLocalPart($key);
6742 // if ns declarations, add to class level array of valid namespaces
6743 if ($key_prefix == 'xmlns') {
6744 if (preg_match('/^http:\/\/www.w3.org\/[0-9]{4}\/XMLSchema$/', $value)) {
6745 $this->XMLSchemaVersion = $value;
6746 $this->namespaces['xsd'] = $this->XMLSchemaVersion;
6747 $this->namespaces['xsi'] = $this->XMLSchemaVersion . '-instance';
6748 }
6749 $this->namespaces[$key_localpart] = $value;
6750 // set method namespace
6751 if ($name == $this->root_struct_name) {
6752 $this->methodNamespace = $value;
6753 }
6754 // if it's a type declaration, set type
6755 } elseif ($key_localpart == 'type') {
6756 if (isset($this->message[$pos]['type']) && $this->message[$pos]['type'] == 'array') {
6757 // do nothing: already processed arrayType
6758 } else {
6759 $value_prefix = $this->getPrefix($value);
6760 $value_localpart = $this->getLocalPart($value);
6761 $this->message[$pos]['type'] = $value_localpart;
6762 $this->message[$pos]['typePrefix'] = $value_prefix;
6763 if (isset($this->namespaces[$value_prefix])) {
6764 $this->message[$pos]['type_namespace'] = $this->namespaces[$value_prefix];
6765 } elseif (isset($attrs['xmlns:' . $value_prefix])) {
6766 $this->message[$pos]['type_namespace'] = $attrs['xmlns:' . $value_prefix];
6767 }
6768 // should do something here with the namespace of specified type?
6769 }
6770 } elseif ($key_localpart == 'arrayType') {
6771 $this->message[$pos]['type'] = 'array';
6772 /* do arrayType ereg here
6773 [1] arrayTypeValue ::= atype asize
6774 [2] atype ::= QName rank*
6775 [3] rank ::= '[' (',')* ']'
6776 [4] asize ::= '[' length~ ']'
6777 [5] length ::= nextDimension* Digit+
6778 [6] nextDimension ::= Digit+ ','
6779 */
6780 $expr = '/([A-Za-z0-9_]+):([A-Za-z]+[A-Za-z0-9_]+)\[([0-9]+),?([0-9]*)\]/';
6781 if (preg_match($expr, $value, $regs)) {
6782 $this->message[$pos]['typePrefix'] = $regs[1];
6783 $this->message[$pos]['arrayTypePrefix'] = $regs[1];
6784 if (isset($this->namespaces[$regs[1]])) {
6785 $this->message[$pos]['arrayTypeNamespace'] = $this->namespaces[$regs[1]];
6786 } elseif (isset($attrs['xmlns:' . $regs[1]])) {
6787 $this->message[$pos]['arrayTypeNamespace'] = $attrs['xmlns:' . $regs[1]];
6788 }
6789 $this->message[$pos]['arrayType'] = $regs[2];
6790 $this->message[$pos]['arraySize'] = $regs[3];
6791 $this->message[$pos]['arrayCols'] = $regs[4];
6792 }
6793 // specifies nil value (or not)
6794 } elseif ($key_localpart == 'nil') {
6795 $this->message[$pos]['nil'] = ($value == 'true' || $value == '1');
6796 // some other attribute
6797 } elseif ($key != 'href' && $key != 'xmlns' && $key_localpart != 'encodingStyle' && $key_localpart != 'root') {
6798 $this->message[$pos]['xattrs']['!' . $key] = $value;
6799 }
6800
6801 if ($key == 'xmlns') {
6802 $this->default_namespace = $value;
6803 }
6804 // log id
6805 if ($key == 'id') {
6806 $this->ids[$value] = $pos;
6807 }
6808 // root
6809 if ($key_localpart == 'root' && $value == 1) {
6810 $this->status = 'method';
6811 $this->root_struct_name = $name;
6812 $this->root_struct = $pos;
6813 $this->debug("found root struct $this->root_struct_name, pos $pos");
6814 }
6815 // for doclit
6816 $attstr .= " $key=\"$value\"";
6817 }
6818 // get namespace - must be done after namespace atts are processed
6819 if (isset($prefix)) {
6820 $this->message[$pos]['namespace'] = $this->namespaces[$prefix];
6821 $this->default_namespace = $this->namespaces[$prefix];
6822 } else {
6823 $this->message[$pos]['namespace'] = $this->default_namespace;
6824 }
6825 if ($this->status == 'header') {
6826 if ($this->root_header != $pos) {
6827 $this->responseHeaders .= "<" . (isset($prefix) ? $prefix . ':' : '') . "$name$attstr>";
6828 }
6829 } elseif ($this->root_struct_name != '') {
6830 $this->document .= "<" . (isset($prefix) ? $prefix . ':' : '') . "$name$attstr>";
6831 }
6832 }
6833
6841 public function end_element($parser, $name)
6842 {
6843 // position of current element is equal to the last value left in depth_array for my depth
6844 $pos = $this->depth_array[$this->depth--];
6845
6846 // get element prefix
6847 if (strpos($name, ':')) {
6848 // get ns prefix
6849 $prefix = substr($name, 0, strpos($name, ':'));
6850 // get unqualified name
6851 $name = substr(strstr($name, ':'), 1);
6852 }
6853
6854 // build to native type
6855 if (isset($this->body_position) && $pos > $this->body_position) {
6856 // deal w/ multirefs
6857 if (isset($this->message[$pos]['attrs']['href'])) {
6858 // get id
6859 $id = substr($this->message[$pos]['attrs']['href'], 1);
6860 // add placeholder to href array
6861 $this->multirefs[$id][$pos] = 'placeholder';
6862 // add set a reference to it as the result value
6863 $this->message[$pos]['result'] =& $this->multirefs[$id][$pos];
6864 // build complexType values
6865 } elseif ($this->message[$pos]['children'] != '') {
6866 // if result has already been generated (struct/array)
6867 if (!isset($this->message[$pos]['result'])) {
6868 $this->message[$pos]['result'] = $this->buildVal($pos);
6869 }
6870 // build complexType values of attributes and possibly simpleContent
6871 } elseif (isset($this->message[$pos]['xattrs'])) {
6872 if (isset($this->message[$pos]['nil']) && $this->message[$pos]['nil']) {
6873 $this->message[$pos]['xattrs']['!'] = null;
6874 } elseif (isset($this->message[$pos]['cdata']) && trim($this->message[$pos]['cdata']) != '') {
6875 if (isset($this->message[$pos]['type'])) {
6876 $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'] : '');
6877 } else {
6878 $parent = $this->message[$pos]['parent'];
6879 if (isset($this->message[$parent]['type']) && ($this->message[$parent]['type'] == 'array') && isset($this->message[$parent]['arrayType'])) {
6880 $this->message[$pos]['xattrs']['!'] = $this->decodeSimple($this->message[$pos]['cdata'], $this->message[$parent]['arrayType'], isset($this->message[$parent]['arrayTypeNamespace']) ? $this->message[$parent]['arrayTypeNamespace'] : '');
6881 } else {
6882 $this->message[$pos]['xattrs']['!'] = $this->message[$pos]['cdata'];
6883 }
6884 }
6885 }
6886 $this->message[$pos]['result'] = $this->message[$pos]['xattrs'];
6887 // set value of simpleType (or nil complexType)
6888 } else {
6889 //$this->debug('adding data for scalar value '.$this->message[$pos]['name'].' of value '.$this->message[$pos]['cdata']);
6890 if (isset($this->message[$pos]['nil']) && $this->message[$pos]['nil']) {
6891 $this->message[$pos]['xattrs']['!'] = null;
6892 } elseif (isset($this->message[$pos]['type'])) {
6893 $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'] : '');
6894 } else {
6895 $parent = $this->message[$pos]['parent'];
6896 if (isset($this->message[$parent]['type']) && ($this->message[$parent]['type'] == 'array') && isset($this->message[$parent]['arrayType'])) {
6897 $this->message[$pos]['result'] = $this->decodeSimple($this->message[$pos]['cdata'], $this->message[$parent]['arrayType'], isset($this->message[$parent]['arrayTypeNamespace']) ? $this->message[$parent]['arrayTypeNamespace'] : '');
6898 } else {
6899 $this->message[$pos]['result'] = $this->message[$pos]['cdata'];
6900 }
6901 }
6902
6903 /* add value to parent's result, if parent is struct/array
6904 $parent = $this->message[$pos]['parent'];
6905 if($this->message[$parent]['type'] != 'map'){
6906 if(strtolower($this->message[$parent]['type']) == 'array'){
6907 $this->message[$parent]['result'][] = $this->message[$pos]['result'];
6908 } else {
6909 $this->message[$parent]['result'][$this->message[$pos]['name']] = $this->message[$pos]['result'];
6910 }
6911 }
6912 */
6913 }
6914 }
6915
6916 // for doclit
6917 if ($this->status == 'header') {
6918 if ($this->root_header != $pos) {
6919 $this->responseHeaders .= "</" . (isset($prefix) ? $prefix . ':' : '') . "$name>";
6920 }
6921 } elseif ($pos >= $this->root_struct) {
6922 $this->document .= "</" . (isset($prefix) ? $prefix . ':' : '') . "$name>";
6923 }
6924 // switch status
6925 if ($pos == $this->root_struct) {
6926 $this->status = 'body';
6927 $this->root_struct_namespace = $this->message[$pos]['namespace'];
6928 } elseif ($name == 'Body') {
6929 $this->status = 'envelope';
6930 } elseif ($name == 'Header') {
6931 $this->status = 'envelope';
6932 } elseif ($name == 'Envelope') {
6933 //
6934 }
6935 // set parent back to my parent
6936 $this->parent = $this->message[$pos]['parent'];
6937 }
6938
6946 public function character_data($parser, $data)
6947 {
6948 $pos = $this->depth_array[$this->depth];
6949 if ($this->xml_encoding=='UTF-8') {
6950 // TODO: add an option to disable this for folks who want
6951 // raw UTF-8 that, e.g., might not map to iso-8859-1
6952 // TODO: this can also be handled with xml_parser_set_option($this->parser, XML_OPTION_TARGET_ENCODING, "ISO-8859-1");
6953 if ($this->decode_utf8) {
6954 $data = utf8_decode($data);
6955 }
6956 }
6957 $this->message[$pos]['cdata'] .= $data;
6958 // for doclit
6959 if ($this->status == 'header') {
6960 $this->responseHeaders .= $data;
6961 } else {
6962 $this->document .= $data;
6963 }
6964 }
6965
6973 public function get_response()
6974 {
6975 return $this->soapresponse;
6976 }
6977
6984 public function get_soapbody()
6985 {
6986 return $this->soapresponse;
6987 }
6988
6995 public function get_soapheader()
6996 {
6997 return $this->soapheader;
6998 }
6999
7006 public function getHeaders()
7007 {
7009 }
7010
7020 public function decodeSimple($value, $type, $typens)
7021 {
7022 // TODO: use the namespace!
7023 if ((!isset($type)) || $type == 'string' || $type == 'long' || $type == 'unsignedLong') {
7024 return (string) $value;
7025 }
7026 if ($type == 'int' || $type == 'integer' || $type == 'short' || $type == 'byte') {
7027 return (int) $value;
7028 }
7029 if ($type == 'float' || $type == 'double' || $type == 'decimal') {
7030 return (float) $value;
7031 }
7032 if ($type == 'boolean') {
7033 if (strtolower($value) == 'false' || strtolower($value) == 'f') {
7034 return false;
7035 }
7036 return (bool) $value;
7037 }
7038 if ($type == 'base64' || $type == 'base64Binary') {
7039 $this->debug('Decode base64 value');
7040 return base64_decode($value);
7041 }
7042 // obscure numeric types
7043 if ($type == 'nonPositiveInteger' || $type == 'negativeInteger'
7044 || $type == 'nonNegativeInteger' || $type == 'positiveInteger'
7045 || $type == 'unsignedInt'
7046 || $type == 'unsignedShort' || $type == 'unsignedByte') {
7047 return (int) $value;
7048 }
7049 // bogus: parser treats array with no elements as a simple type
7050 if ($type == 'array') {
7051 return array();
7052 }
7053 // everything else
7054 return (string) $value;
7055 }
7056
7065 public function buildVal($pos)
7066 {
7067 if (!isset($this->message[$pos]['type'])) {
7068 $this->message[$pos]['type'] = '';
7069 }
7070 $this->debug('in buildVal() for ' . $this->message[$pos]['name'] . "(pos $pos) of type " . $this->message[$pos]['type']);
7071 // if there are children...
7072 if ($this->message[$pos]['children'] != '') {
7073 $this->debug('in buildVal, there are children');
7074 $children = explode('|', $this->message[$pos]['children']);
7075 array_shift($children); // knock off empty
7076 // md array
7077 if (isset($this->message[$pos]['arrayCols']) && $this->message[$pos]['arrayCols'] != '') {
7078 $r=0; // rowcount
7079 $c=0; // colcount
7080 foreach ($children as $child_pos) {
7081 $this->debug("in buildVal, got an MD array element: $r, $c");
7082 $params[$r][] = $this->message[$child_pos]['result'];
7083 $c++;
7084 if ($c == $this->message[$pos]['arrayCols']) {
7085 $c = 0;
7086 $r++;
7087 }
7088 }
7089 // array
7090 } elseif ($this->message[$pos]['type'] == 'array' || $this->message[$pos]['type'] == 'Array') {
7091 $this->debug('in buildVal, adding array ' . $this->message[$pos]['name']);
7092 foreach ($children as $child_pos) {
7093 $params[] = &$this->message[$child_pos]['result'];
7094 }
7095 // apache Map type: java hashtable
7096 } elseif ($this->message[$pos]['type'] == 'Map' && $this->message[$pos]['type_namespace'] == 'http://xml.apache.org/xml-soap') {
7097 $this->debug('in buildVal, Java Map ' . $this->message[$pos]['name']);
7098 foreach ($children as $child_pos) {
7099 $kv = explode("|", $this->message[$child_pos]['children']);
7100 $params[$this->message[$kv[1]]['result']] = &$this->message[$kv[2]]['result'];
7101 }
7102 // generic compound type
7103 //} elseif($this->message[$pos]['type'] == 'SOAPStruct' || $this->message[$pos]['type'] == 'struct') {
7104 } else {
7105 // Apache Vector type: treat as an array
7106 $this->debug('in buildVal, adding Java Vector or generic compound type ' . $this->message[$pos]['name']);
7107 if ($this->message[$pos]['type'] == 'Vector' && $this->message[$pos]['type_namespace'] == 'http://xml.apache.org/xml-soap') {
7108 $notstruct = 1;
7109 } else {
7110 $notstruct = 0;
7111 }
7112 //
7113 foreach ($children as $child_pos) {
7114 if ($notstruct) {
7115 $params[] = &$this->message[$child_pos]['result'];
7116 } else {
7117 if (isset($params[$this->message[$child_pos]['name']])) {
7118 // de-serialize repeated element name into an array
7119 if ((!is_array($params[$this->message[$child_pos]['name']])) || (!isset($params[$this->message[$child_pos]['name']][0]))) {
7120 $params[$this->message[$child_pos]['name']] = array($params[$this->message[$child_pos]['name']]);
7121 }
7122 $params[$this->message[$child_pos]['name']][] = &$this->message[$child_pos]['result'];
7123 } else {
7124 $params[$this->message[$child_pos]['name']] = &$this->message[$child_pos]['result'];
7125 }
7126 }
7127 }
7128 }
7129 if (isset($this->message[$pos]['xattrs'])) {
7130 $this->debug('in buildVal, handling attributes');
7131 foreach ($this->message[$pos]['xattrs'] as $n => $v) {
7132 $params[$n] = $v;
7133 }
7134 }
7135 // handle simpleContent
7136 if (isset($this->message[$pos]['cdata']) && trim($this->message[$pos]['cdata']) != '') {
7137 $this->debug('in buildVal, handling simpleContent');
7138 if (isset($this->message[$pos]['type'])) {
7139 $params['!'] = $this->decodeSimple($this->message[$pos]['cdata'], $this->message[$pos]['type'], isset($this->message[$pos]['type_namespace']) ? $this->message[$pos]['type_namespace'] : '');
7140 } else {
7141 $parent = $this->message[$pos]['parent'];
7142 if (isset($this->message[$parent]['type']) && ($this->message[$parent]['type'] == 'array') && isset($this->message[$parent]['arrayType'])) {
7143 $params['!'] = $this->decodeSimple($this->message[$pos]['cdata'], $this->message[$parent]['arrayType'], isset($this->message[$parent]['arrayTypeNamespace']) ? $this->message[$parent]['arrayTypeNamespace'] : '');
7144 } else {
7145 $params['!'] = $this->message[$pos]['cdata'];
7146 }
7147 }
7148 }
7149 $ret = is_array($params) ? $params : array();
7150 $this->debug('in buildVal, return:');
7151 $this->appendDebug($this->varDump($ret));
7152 return $ret;
7153 } else {
7154 $this->debug('in buildVal, no children, building scalar');
7155 $cdata = isset($this->message[$pos]['cdata']) ? $this->message[$pos]['cdata'] : '';
7156 if (isset($this->message[$pos]['type'])) {
7157 $ret = $this->decodeSimple($cdata, $this->message[$pos]['type'], isset($this->message[$pos]['type_namespace']) ? $this->message[$pos]['type_namespace'] : '');
7158 $this->debug("in buildVal, return: $ret");
7159 return $ret;
7160 }
7161 $parent = $this->message[$pos]['parent'];
7162 if (isset($this->message[$parent]['type']) && ($this->message[$parent]['type'] == 'array') && isset($this->message[$parent]['arrayType'])) {
7163 $ret = $this->decodeSimple($cdata, $this->message[$parent]['arrayType'], isset($this->message[$parent]['arrayTypeNamespace']) ? $this->message[$parent]['arrayTypeNamespace'] : '');
7164 $this->debug("in buildVal, return: $ret");
7165 return $ret;
7166 }
7167 $ret = $this->message[$pos]['cdata'];
7168 $this->debug("in buildVal, return: $ret");
7169 return $ret;
7170 }
7171 }
7172}
7173
7178{
7179}
7180
7181?><?php
7182
7183
7184
7206{
7207 public $username = ''; // Username for HTTP authentication
7208 public $password = ''; // Password for HTTP authentication
7209 public $authtype = ''; // Type of HTTP authentication
7210 public $certRequest = array(); // Certificate for HTTP SSL authentication
7211 public $requestHeaders = false; // SOAP headers in request (text)
7212 public $responseHeaders = ''; // SOAP headers from response (incomplete namespace resolution) (text)
7213 public $responseHeader = null; // SOAP Header from response (parsed)
7214 public $document = ''; // SOAP body response portion (incomplete namespace resolution) (text)
7216 public $forceEndpoint = ''; // overrides WSDL endpoint
7217 public $proxyhost = '';
7218 public $proxyport = '';
7219 public $proxyusername = '';
7220 public $proxypassword = '';
7221 public $xml_encoding = ''; // character set encoding of incoming (response) messages
7222 public $http_encoding = false;
7223 public $timeout = 0; // HTTP connection timeout
7224 public $response_timeout = 30; // HTTP response timeout
7225 public $endpointType = ''; // soap|wsdl, empty for WSDL initialization error
7227 public $defaultRpcParams = false; // This is no longer used
7228 public $request = ''; // HTTP request
7229 public $response = ''; // HTTP response
7230 public $responseData = ''; // SOAP payload of response
7231 public $cookies = array(); // Cookies from response or for request
7232 public $decode_utf8 = true; // toggles whether the parser decodes element content w/ utf8_decode()
7233 public $operations = array(); // WSDL operations, empty for WSDL initialization error
7234 public $curl_options = array(); // User-specified cURL options
7235 public $bindingType = ''; // WSDL operation binding type
7236 public $use_curl = false; // whether to always try to use cURL
7237
7238 /*
7239 * fault related variables
7240 */
7245 public $fault;
7261
7276 public function __construct($endpoint, $wsdl = false, $proxyhost = false, $proxyport = false, $proxyusername = false, $proxypassword = false, $timeout = 0, $response_timeout = 30)
7277 {
7279 $this->endpoint = $endpoint;
7280 $this->proxyhost = $proxyhost;
7281 $this->proxyport = $proxyport;
7282 $this->proxyusername = $proxyusername;
7283 $this->proxypassword = $proxypassword;
7284 $this->timeout = $timeout;
7285 $this->response_timeout = $response_timeout;
7286
7287 $this->debug("ctor wsdl=$wsdl timeout=$timeout response_timeout=$response_timeout");
7288 $this->appendDebug('endpoint=' . $this->varDump($endpoint));
7289
7290 // make values
7291 if ($wsdl) {
7292 if (is_object($endpoint) && (get_class($endpoint) == 'wsdl')) {
7293 $this->wsdl = $endpoint;
7294 $this->endpoint = $this->wsdl->wsdl;
7295 $this->wsdlFile = $this->endpoint;
7296 $this->debug('existing wsdl instance created from ' . $this->endpoint);
7297 $this->checkWSDL();
7298 } else {
7299 $this->wsdlFile = $this->endpoint;
7300 $this->wsdl = null;
7301 $this->debug('will use lazy evaluation of wsdl from ' . $this->endpoint);
7302 }
7303 $this->endpointType = 'wsdl';
7304 } else {
7305 $this->debug("instantiate SOAP with endpoint at $endpoint");
7306 $this->endpointType = 'soap';
7307 }
7308 }
7309
7335 public function call($operation, $params=array(), $namespace='http://tempuri.org', $soapAction='', $headers=false, $rpcParams=null, $style='rpc', $use='encoded')
7336 {
7337 $this->operation = $operation;
7338 $this->fault = false;
7339 $this->setError('');
7340 $this->request = '';
7341 $this->response = '';
7342 $this->responseData = '';
7343 $this->faultstring = '';
7344 $this->faultcode = '';
7345 $this->opData = array();
7346
7347 $this->debug("call: operation=$operation, namespace=$namespace, soapAction=$soapAction, rpcParams=$rpcParams, style=$style, use=$use, endpointType=$this->endpointType");
7348 $this->appendDebug('params=' . $this->varDump($params));
7349 $this->appendDebug('headers=' . $this->varDump($headers));
7350 if ($headers) {
7351 $this->requestHeaders = $headers;
7352 }
7353 if ($this->endpointType == 'wsdl' && is_null($this->wsdl)) {
7354 $this->loadWSDL();
7355 if ($this->getError()) {
7356 return false;
7357 }
7358 }
7359 // serialize parameters
7360 if ($this->endpointType == 'wsdl' && $opData = $this->getOperationData($operation)) {
7361 // use WSDL for operation
7362 $this->opData = $opData;
7363 $this->debug("found operation");
7364 $this->appendDebug('opData=' . $this->varDump($opData));
7365 if (isset($opData['soapAction'])) {
7366 $soapAction = $opData['soapAction'];
7367 }
7368 if (! $this->forceEndpoint) {
7369 $this->endpoint = $opData['endpoint'];
7370 } else {
7371 $this->endpoint = $this->forceEndpoint;
7372 }
7373 $namespace = isset($opData['input']['namespace']) ? $opData['input']['namespace'] : $namespace;
7374 $style = $opData['style'];
7375 $use = $opData['input']['use'];
7376 // add ns to ns array
7377 if ($namespace != '' && !isset($this->wsdl->namespaces[$namespace])) {
7378 $nsPrefix = 'ns' . rand(1000, 9999);
7379 $this->wsdl->namespaces[$nsPrefix] = $namespace;
7380 }
7381 $nsPrefix = $this->wsdl->getPrefixFromNamespace($namespace);
7382 // serialize payload
7383 if (is_string($params)) {
7384 $this->debug("serializing param string for WSDL operation $operation");
7385 $payload = $params;
7386 } elseif (is_array($params)) {
7387 $this->debug("serializing param array for WSDL operation $operation");
7388 $payload = $this->wsdl->serializeRPCParameters($operation, 'input', $params, $this->bindingType);
7389 } else {
7390 $this->debug('params must be array or string');
7391 $this->setError('params must be array or string');
7392 return false;
7393 }
7394 $usedNamespaces = $this->wsdl->usedNamespaces;
7395 if (isset($opData['input']['encodingStyle'])) {
7396 $encodingStyle = $opData['input']['encodingStyle'];
7397 } else {
7398 $encodingStyle = '';
7399 }
7400 $this->appendDebug($this->wsdl->getDebug());
7401 $this->wsdl->clearDebug();
7402 if ($errstr = $this->wsdl->getError()) {
7403 $this->debug('got wsdl error: ' . $errstr);
7404 $this->setError('wsdl error: ' . $errstr);
7405 return false;
7406 }
7407 } elseif ($this->endpointType == 'wsdl') {
7408 // operation not in WSDL
7409 $this->appendDebug($this->wsdl->getDebug());
7410 $this->wsdl->clearDebug();
7411 $this->setError('operation ' . $operation . ' not present.');
7412 $this->debug("operation '$operation' not present.");
7413 return false;
7414 } else {
7415 // no WSDL
7416 //$this->namespaces['ns1'] = $namespace;
7417 $nsPrefix = 'ns' . rand(1000, 9999);
7418 // serialize
7419 $payload = '';
7420 if (is_string($params)) {
7421 $this->debug("serializing param string for operation $operation");
7422 $payload = $params;
7423 } elseif (is_array($params)) {
7424 $this->debug("serializing param array for operation $operation");
7425 foreach ($params as $k => $v) {
7426 $payload .= $this->serialize_val($v, $k, false, false, false, false, $use);
7427 }
7428 } else {
7429 $this->debug('params must be array or string');
7430 $this->setError('params must be array or string');
7431 return false;
7432 }
7433 $usedNamespaces = array();
7434 if ($use == 'encoded') {
7435 $encodingStyle = 'http://schemas.xmlsoap.org/soap/encoding/';
7436 } else {
7437 $encodingStyle = '';
7438 }
7439 }
7440 // wrap RPC calls with method element
7441 if ($style == 'rpc') {
7442 if ($use == 'literal') {
7443 $this->debug("wrapping RPC request with literal method element");
7444 if ($namespace) {
7445 // 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
7446 $payload = "<$nsPrefix:$operation xmlns:$nsPrefix=\"$namespace\">" .
7447 $payload .
7448 "</$nsPrefix:$operation>";
7449 } else {
7450 $payload = "<$operation>" . $payload . "</$operation>";
7451 }
7452 } else {
7453 $this->debug("wrapping RPC request with encoded method element");
7454 if ($namespace) {
7455 $payload = "<$nsPrefix:$operation xmlns:$nsPrefix=\"$namespace\">" .
7456 $payload .
7457 "</$nsPrefix:$operation>";
7458 } else {
7459 $payload = "<$operation>" .
7460 $payload .
7461 "</$operation>";
7462 }
7463 }
7464 }
7465 // serialize envelope
7466 $soapmsg = $this->serializeEnvelope($payload, $this->requestHeaders, $usedNamespaces, $style, $use, $encodingStyle);
7467 $this->debug("endpoint=$this->endpoint, soapAction=$soapAction, namespace=$namespace, style=$style, use=$use, encodingStyle=$encodingStyle");
7468 $this->debug('SOAP message length=' . strlen($soapmsg) . ' contents (max 1000 bytes)=' . substr($soapmsg, 0, 1000));
7469 // send
7470 $return = $this->send($this->getHTTPBody($soapmsg), $soapAction, $this->timeout, $this->response_timeout);
7471 if ($errstr = $this->getError()) {
7472 $this->debug('Error: ' . $errstr);
7473 return false;
7474 } else {
7475 $this->return = $return;
7476 $this->debug('sent message successfully and got a(n) ' . gettype($return));
7477 $this->appendDebug('return=' . $this->varDump($return));
7478
7479 // fault?
7480 if (is_array($return) && isset($return['faultcode'])) {
7481 $this->debug('got fault');
7482 $this->setError($return['faultcode'] . ': ' . $return['faultstring']);
7483 $this->fault = true;
7484 foreach ($return as $k => $v) {
7485 $this->$k = $v;
7486 $this->debug("$k = $v<br>");
7487 }
7488 return $return;
7489 } elseif ($style == 'document') {
7490 // NOTE: if the response is defined to have multiple parts (i.e. unwrapped),
7491 // we are only going to return the first part here...sorry about that
7492 return $return;
7493 } else {
7494 // array of return values
7495 if (is_array($return)) {
7496 // multiple 'out' parameters, which we return wrapped up
7497 // in the array
7498 if (sizeof($return) > 1) {
7499 return $return;
7500 }
7501 // single 'out' parameter (normally the return value)
7502 $return = array_shift($return);
7503 $this->debug('return shifted value: ');
7504 $this->appendDebug($this->varDump($return));
7505 return $return;
7506 // nothing returned (ie, echoVoid)
7507 } else {
7508 return "";
7509 }
7510 }
7511 }
7512 }
7513
7519 public function checkWSDL()
7520 {
7521 $this->appendDebug($this->wsdl->getDebug());
7522 $this->wsdl->clearDebug();
7523 $this->debug('checkWSDL');
7524 // catch errors
7525 if ($errstr = $this->wsdl->getError()) {
7526 $this->debug('got wsdl error: ' . $errstr);
7527 $this->setError('wsdl error: ' . $errstr);
7528 } elseif ($this->operations = $this->wsdl->getOperations('soap')) {
7529 $this->bindingType = 'soap';
7530 $this->debug('got ' . count($this->operations) . ' operations from wsdl ' . $this->wsdlFile . ' for binding type ' . $this->bindingType);
7531 } elseif ($this->operations = $this->wsdl->getOperations('soap12')) {
7532 $this->bindingType = 'soap12';
7533 $this->debug('got ' . count($this->operations) . ' operations from wsdl ' . $this->wsdlFile . ' for binding type ' . $this->bindingType);
7534 $this->debug('**************** WARNING: SOAP 1.2 BINDING *****************');
7535 } else {
7536 $this->debug('getOperations returned false');
7537 $this->setError('no operations defined in the WSDL document!');
7538 }
7539 }
7540
7546 public function loadWSDL()
7547 {
7548 $this->debug('instantiating wsdl class with doc: ' . $this->wsdlFile);
7549 $this->wsdl = new wsdl('', $this->proxyhost, $this->proxyport, $this->proxyusername, $this->proxypassword, $this->timeout, $this->response_timeout, $this->curl_options, $this->use_curl);
7550 $this->wsdl->setCredentials($this->username, $this->password, $this->authtype, $this->certRequest);
7551 $this->wsdl->fetchWSDL($this->wsdlFile);
7552 $this->checkWSDL();
7553 }
7554
7562 public function getOperationData($operation)
7563 {
7564 if ($this->endpointType == 'wsdl' && is_null($this->wsdl)) {
7565 $this->loadWSDL();
7566 if ($this->getError()) {
7567 return false;
7568 }
7569 }
7570 if (isset($this->operations[$operation])) {
7571 return $this->operations[$operation];
7572 }
7573 $this->debug("No data for operation: $operation");
7574 }
7575
7590 public function send($msg, $soapaction = '', $timeout=0, $response_timeout=30)
7591 {
7592 $this->checkCookies();
7593 // detect transport
7594 switch (true) {
7595 // http(s)
7596 case preg_match('/^http/', $this->endpoint):
7597 $this->debug('transporting via HTTP');
7598 if ($this->persistentConnection == true && is_object($this->persistentConnection)) {
7600 } else {
7601 $http = new soap_transport_http($this->endpoint, $this->curl_options, $this->use_curl);
7602 if ($this->persistentConnection) {
7603 $http->usePersistentConnection();
7604 }
7605 }
7606 $http->setContentType($this->getHTTPContentType(), $this->getHTTPContentTypeCharset());
7607 $http->setSOAPAction($soapaction);
7608 if ($this->proxyhost && $this->proxyport) {
7609 $http->setProxy($this->proxyhost, $this->proxyport, $this->proxyusername, $this->proxypassword);
7610 }
7611 if ($this->authtype != '') {
7612 $http->setCredentials($this->username, $this->password, $this->authtype, array(), $this->certRequest);
7613 }
7614 if ($this->http_encoding != '') {
7615 $http->setEncoding($this->http_encoding);
7616 }
7617 $this->debug('sending message, length=' . strlen($msg));
7618 if (preg_match('/^http:/', $this->endpoint)) {
7619 //if(strpos($this->endpoint,'http:')){
7620 $this->responseData = $http->send($msg, $timeout, $response_timeout, $this->cookies);
7621 } elseif (preg_match('/^https/', $this->endpoint)) {
7622 //} elseif(strpos($this->endpoint,'https:')){
7623 //if(phpversion() == '4.3.0-dev'){
7624 //$response = $http->send($msg,$timeout,$response_timeout);
7625 //$this->request = $http->outgoing_payload;
7626 //$this->response = $http->incoming_payload;
7627 //} else
7628 $this->responseData = $http->sendHTTPS($msg, $timeout, $response_timeout, $this->cookies);
7629 } else {
7630 $this->setError('no http/s in endpoint url');
7631 }
7632 $this->request = $http->outgoing_payload;
7633 $this->response = $http->incoming_payload;
7634 $this->appendDebug($http->getDebug());
7635 $this->UpdateCookies($http->incoming_cookies);
7636
7637 // save transport object if using persistent connections
7638 if ($this->persistentConnection) {
7639 $http->clearDebug();
7640 if (!is_object($this->persistentConnection)) {
7641 $this->persistentConnection = $http;
7642 }
7643 }
7644
7645 if ($err = $http->getError()) {
7646 $this->setError('HTTP Error: ' . $err);
7647 return false;
7648 } elseif ($this->getError()) {
7649 return false;
7650 } else {
7651 $this->debug('got response, length=' . strlen($this->responseData) . ' type=' . $http->incoming_headers['content-type']);
7652 return $this->parseResponse($http->incoming_headers, $this->responseData);
7653 }
7654 break;
7655 default:
7656 $this->setError('no transport found, or selected transport is not yet supported!');
7657 return false;
7658 break;
7659 }
7660 }
7661
7670 public function parseResponse($headers, $data)
7671 {
7672 $this->debug('Entering parseResponse() for data of length ' . strlen($data) . ' headers:');
7673 $this->appendDebug($this->varDump($headers));
7674 if (!strstr($headers['content-type'], 'text/xml')) {
7675 $this->setError('Response not of type text/xml: ' . $headers['content-type']);
7676 return false;
7677 }
7678 if (strpos($headers['content-type'], '=')) {
7679 $enc = str_replace('"', '', substr(strstr($headers["content-type"], '='), 1));
7680 $this->debug('Got response encoding: ' . $enc);
7681 if (preg_match('/^(ISO-8859-1|US-ASCII|UTF-8)$/i', $enc)) {
7682 $this->xml_encoding = strtoupper($enc);
7683 } else {
7684 $this->xml_encoding = 'US-ASCII';
7685 }
7686 } else {
7687 // should be US-ASCII for HTTP 1.0 or ISO-8859-1 for HTTP 1.1
7688 $this->xml_encoding = 'ISO-8859-1';
7689 }
7690 $this->debug('Use encoding: ' . $this->xml_encoding . ' when creating nusoap_parser');
7691 $parser = new nusoap_parser($data, $this->xml_encoding, $this->operation, $this->decode_utf8);
7692 // add parser debug data to our debug
7693 $this->appendDebug($parser->getDebug());
7694 // if parse errors
7695 if ($errstr = $parser->getError()) {
7696 $this->setError($errstr);
7697 // destroy the parser object
7698 unset($parser);
7699 return false;
7700 } else {
7701 // get SOAP headers
7702 $this->responseHeaders = $parser->getHeaders();
7703 // get SOAP headers
7704 $this->responseHeader = $parser->get_soapheader();
7705 // get decoded message
7706 $return = $parser->get_soapbody();
7707 // add document for doclit support
7708 $this->document = $parser->document;
7709 // destroy the parser object
7710 unset($parser);
7711 // return decode message
7712 return $return;
7713 }
7714 }
7715
7723 public function setCurlOption($option, $value)
7724 {
7725 $this->debug("setCurlOption option=$option, value=");
7726 $this->appendDebug($this->varDump($value));
7727 $this->curl_options[$option] = $value;
7728 }
7729
7736 public function setEndpoint($endpoint)
7737 {
7738 $this->debug("setEndpoint(\"$endpoint\")");
7739 $this->forceEndpoint = $endpoint;
7740 }
7741
7748 public function setHeaders($headers)
7749 {
7750 $this->debug("setHeaders headers=");
7751 $this->appendDebug($this->varDump($headers));
7752 $this->requestHeaders = $headers;
7753 }
7754
7761 public function getHeaders()
7762 {
7764 }
7765
7772 public function getHeader()
7773 {
7774 return $this->responseHeader;
7775 }
7776
7787 {
7788 $this->proxyhost = $proxyhost;
7789 $this->proxyport = $proxyport;
7790 $this->proxyusername = $proxyusername;
7791 $this->proxypassword = $proxypassword;
7792 }
7793
7803 public function setCredentials($username, $password, $authtype = 'basic', $certRequest = array())
7804 {
7805 $this->debug("setCredentials username=$username authtype=$authtype certRequest=");
7806 $this->appendDebug($this->varDump($certRequest));
7807 $this->username = $username;
7808 $this->password = $password;
7809 $this->authtype = $authtype;
7810 $this->certRequest = $certRequest;
7811 }
7812
7819 public function setHTTPEncoding($enc='gzip, deflate')
7820 {
7821 $this->debug("setHTTPEncoding(\"$enc\")");
7822 $this->http_encoding = $enc;
7823 }
7824
7831 public function setUseCURL($use)
7832 {
7833 $this->debug("setUseCURL($use)");
7834 $this->use_curl = $use;
7835 }
7836
7843 {
7844 $this->debug("useHTTPPersistentConnection");
7845 $this->persistentConnection = true;
7846 }
7847
7859 public function getDefaultRpcParams()
7860 {
7862 }
7863
7875 public function setDefaultRpcParams($rpcParams)
7876 {
7877 $this->defaultRpcParams = $rpcParams;
7878 }
7879
7887 public function getProxy()
7888 {
7889 $r = rand();
7890 $evalStr = $this->_getProxyClassCode($r);
7891 //$this->debug("proxy class: $evalStr");
7892 if ($this->getError()) {
7893 $this->debug("Error from _getProxyClassCode, so return NULL");
7894 return null;
7895 }
7896 // eval the class
7897 eval($evalStr);
7898 // instantiate proxy object
7899 eval("\$proxy = new nusoap_proxy_$r('');");
7900 // transfer current wsdl data to the proxy thereby avoiding parsing the wsdl twice
7901 $proxy->endpointType = 'wsdl';
7902 $proxy->wsdlFile = $this->wsdlFile;
7903 $proxy->wsdl = $this->wsdl;
7904 $proxy->operations = $this->operations;
7905 $proxy->defaultRpcParams = $this->defaultRpcParams;
7906 // transfer other state
7907 $proxy->soap_defencoding = $this->soap_defencoding;
7908 $proxy->username = $this->username;
7909 $proxy->password = $this->password;
7910 $proxy->authtype = $this->authtype;
7911 $proxy->certRequest = $this->certRequest;
7912 $proxy->requestHeaders = $this->requestHeaders;
7913 $proxy->endpoint = $this->endpoint;
7914 $proxy->forceEndpoint = $this->forceEndpoint;
7915 $proxy->proxyhost = $this->proxyhost;
7916 $proxy->proxyport = $this->proxyport;
7917 $proxy->proxyusername = $this->proxyusername;
7918 $proxy->proxypassword = $this->proxypassword;
7919 $proxy->http_encoding = $this->http_encoding;
7920 $proxy->timeout = $this->timeout;
7921 $proxy->response_timeout = $this->response_timeout;
7922 $proxy->persistentConnection = &$this->persistentConnection;
7923 $proxy->decode_utf8 = $this->decode_utf8;
7924 $proxy->curl_options = $this->curl_options;
7925 $proxy->bindingType = $this->bindingType;
7926 $proxy->use_curl = $this->use_curl;
7927 return $proxy;
7928 }
7929
7936 public function _getProxyClassCode($r)
7937 {
7938 $this->debug("in getProxy endpointType=$this->endpointType");
7939 $this->appendDebug("wsdl=" . $this->varDump($this->wsdl));
7940 if ($this->endpointType != 'wsdl') {
7941 $evalStr = 'A proxy can only be created for a WSDL client';
7942 $this->setError($evalStr);
7943 $evalStr = "echo \"$evalStr\";";
7944 return $evalStr;
7945 }
7946 if ($this->endpointType == 'wsdl' && is_null($this->wsdl)) {
7947 $this->loadWSDL();
7948 if ($this->getError()) {
7949 return "echo \"" . $this->getError() . "\";";
7950 }
7951 }
7952 $evalStr = '';
7953 foreach ($this->operations as $operation => $opData) {
7954 if ($operation != '') {
7955 // create param string and param comment string
7956 if (sizeof($opData['input']['parts']) > 0) {
7957 $paramStr = '';
7958 $paramArrayStr = '';
7959 $paramCommentStr = '';
7960 foreach ($opData['input']['parts'] as $name => $type) {
7961 $paramStr .= "\$$name, ";
7962 $paramArrayStr .= "'$name' => \$$name, ";
7963 $paramCommentStr .= "$type \$$name, ";
7964 }
7965 $paramStr = substr($paramStr, 0, strlen($paramStr)-2);
7966 $paramArrayStr = substr($paramArrayStr, 0, strlen($paramArrayStr)-2);
7967 $paramCommentStr = substr($paramCommentStr, 0, strlen($paramCommentStr)-2);
7968 } else {
7969 $paramStr = '';
7970 $paramArrayStr = '';
7971 $paramCommentStr = 'void';
7972 }
7973 $opData['namespace'] = !isset($opData['namespace']) ? 'http://testuri.com' : $opData['namespace'];
7974 $evalStr .= "// $paramCommentStr
7975 function " . str_replace('.', '__', $operation) . "($paramStr) {
7976 \$params = array($paramArrayStr);
7977 return \$this->call('$operation', \$params, '" . $opData['namespace'] . "', '" . (isset($opData['soapAction']) ? $opData['soapAction'] : '') . "');
7978 }
7979 ";
7980 unset($paramStr);
7981 unset($paramCommentStr);
7982 }
7983 }
7984 $evalStr = 'class nusoap_proxy_' . $r . ' extends nusoap_client {
7985 ' . $evalStr . '
7986}';
7987 return $evalStr;
7988 }
7989
7996 public function getProxyClassCode()
7997 {
7998 $r = rand();
7999 return $this->_getProxyClassCode($r);
8000 }
8001
8009 public function getHTTPBody($soapmsg)
8010 {
8011 return $soapmsg;
8012 }
8013
8022 public function getHTTPContentType()
8023 {
8024 return 'text/xml';
8025 }
8026
8037 {
8039 }
8040
8041 /*
8042 * whether or not parser should decode utf8 element content
8043 *
8044 * @return always returns true
8045 * @access public
8046 */
8047 public function decodeUTF8($bool)
8048 {
8049 $this->decode_utf8 = $bool;
8050 return true;
8051 }
8052
8061 public function setCookie($name, $value)
8062 {
8063 if (strlen($name) == 0) {
8064 return false;
8065 }
8066 $this->cookies[] = array('name' => $name, 'value' => $value);
8067 return true;
8068 }
8069
8076 public function getCookies()
8077 {
8078 return $this->cookies;
8079 }
8080
8087 public function checkCookies()
8088 {
8089 if (sizeof($this->cookies) == 0) {
8090 return true;
8091 }
8092 $this->debug('checkCookie: check ' . sizeof($this->cookies) . ' cookies');
8093 $curr_cookies = $this->cookies;
8094 $this->cookies = array();
8095 foreach ($curr_cookies as $cookie) {
8096 if (! is_array($cookie)) {
8097 $this->debug('Remove cookie that is not an array');
8098 continue;
8099 }
8100 if ((isset($cookie['expires'])) && (! empty($cookie['expires']))) {
8101 if (strtotime($cookie['expires']) > time()) {
8102 $this->cookies[] = $cookie;
8103 } else {
8104 $this->debug('Remove expired cookie ' . $cookie['name']);
8105 }
8106 } else {
8107 $this->cookies[] = $cookie;
8108 }
8109 }
8110 $this->debug('checkCookie: ' . sizeof($this->cookies) . ' cookies left in array');
8111 return true;
8112 }
8113
8121 public function UpdateCookies($cookies)
8122 {
8123 if (sizeof($this->cookies) == 0) {
8124 // no existing cookies: take whatever is new
8125 if (sizeof($cookies) > 0) {
8126 $this->debug('Setting new cookie(s)');
8127 $this->cookies = $cookies;
8128 }
8129 return true;
8130 }
8131 if (sizeof($cookies) == 0) {
8132 // no new cookies: keep what we've got
8133 return true;
8134 }
8135 // merge
8136 foreach ($cookies as $newCookie) {
8137 if (!is_array($newCookie)) {
8138 continue;
8139 }
8140 if ((!isset($newCookie['name'])) || (!isset($newCookie['value']))) {
8141 continue;
8142 }
8143 $newName = $newCookie['name'];
8144
8145 $found = false;
8146 for ($i = 0; $i < count($this->cookies); $i++) {
8147 $cookie = $this->cookies[$i];
8148 if (!is_array($cookie)) {
8149 continue;
8150 }
8151 if (!isset($cookie['name'])) {
8152 continue;
8153 }
8154 if ($newName != $cookie['name']) {
8155 continue;
8156 }
8157 $newDomain = isset($newCookie['domain']) ? $newCookie['domain'] : 'NODOMAIN';
8158 $domain = isset($cookie['domain']) ? $cookie['domain'] : 'NODOMAIN';
8159 if ($newDomain != $domain) {
8160 continue;
8161 }
8162 $newPath = isset($newCookie['path']) ? $newCookie['path'] : 'NOPATH';
8163 $path = isset($cookie['path']) ? $cookie['path'] : 'NOPATH';
8164 if ($newPath != $path) {
8165 continue;
8166 }
8167 $this->cookies[$i] = $newCookie;
8168 $found = true;
8169 $this->debug('Update cookie ' . $newName . '=' . $newCookie['value']);
8170 break;
8171 }
8172 if (! $found) {
8173 $this->debug('Add cookie ' . $newName . '=' . $newCookie['value']);
8174 $this->cookies[] = $newCookie;
8175 }
8176 }
8177 return true;
8178 }
8179}
8180
8181if (!extension_loaded('soap')) {
8185 class soapclient extends nusoap_client
8186 {
8187 }
8188}
8189?>
$id
plugin.php for ilComponentBuildPluginInfoObjectiveTest::testAddPlugins
Definition: plugin.php:23
if(!defined('PATH_SEPARATOR')) $GLOBALS['_PEAR_default_error_mode']
Definition: PEAR.php:64
$out
Definition: buildRTE.php:24
foreach($mandatory_scripts as $file) $timestamp
Definition: buildRTE.php:70
Backward compatibility.
Definition: nusoap.php:2062
nusoap_base
Definition: nusoap.php:97
getPrefix($str)
returns the prefix part of a prefixed string returns false, if not prefixed
Definition: nusoap.php:839
& getDebug()
gets the current debug data for this instance
Definition: nusoap.php:332
& getDebugAsXMLComment()
gets the current debug data for this instance as an XML comment this may change the contents of the d...
Definition: nusoap.php:346
getmicrotime()
returns the time in ODBC canonical form with microseconds
Definition: nusoap.php:889
setError($str)
sets error string
Definition: nusoap.php:395
getNamespaceFromPrefix($prefix)
pass it a prefix, it returns a namespace
Definition: nusoap.php:855
contractQname($qname)
contracts (changes namespace to prefix) a qualified name
Definition: nusoap.php:769
debug($string)
adds debug data to the instance debug string with formatting
Definition: nusoap.php:292
getDebugLevel()
gets the debug level for this instance
Definition: nusoap.php:270
getPrefixFromNamespace($ns)
returns the prefix for a given namespace (or prefix) or false if no prefixes registered for the given...
Definition: nusoap.php:872
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:433
setGlobalDebugLevel($level)
sets the global debug level, which applies to future instances
Definition: nusoap.php:259
serializeEnvelope($body, $headers=false, $namespaces=array(), $style='rpc', $use='encoded', $encodingStyle='http://schemas.xmlsoap.org/soap/encoding/')
serializes a message
Definition: nusoap.php:700
clearDebug()
clears the current debug data for this instance
Definition: nusoap.php:319
expandEntities($val)
expands entities, e.g.
Definition: nusoap.php:363
formatDump($str)
formats a string to be inserted into an HTML stream
Definition: nusoap.php:756
$soap_defencoding
Definition: nusoap.php:164
expandQname($qname)
expands (changes prefix to namespace) a qualified name
Definition: nusoap.php:795
$XMLSchemaVersion
Definition: nusoap.php:155
varDump($data)
Returns a string with the output of var_dump.
Definition: nusoap.php:909
setDebugLevel($level)
sets the debug level for this instance
Definition: nusoap.php:281
getError()
returns error string if present
Definition: nusoap.php:381
__toString()
represents the object as a string
Definition: nusoap.php:924
appendDebug($string)
adds debug data to the instance debug string without formatting
Definition: nusoap.php:305
getLocalPart($str)
returns the local part of a prefixed string returns the original string, if not prefixed
Definition: nusoap.php:821
isArraySimpleOrStruct($val)
detect if array is a simple array or a struct (associative array)
Definition: nusoap.php:407
getGlobalDebugLevel()
gets the global debug level, which applies to future instances
Definition: nusoap.php:248
__construct()
constructor
Definition: nusoap.php:237
[nu]soapclient higher level class for easy usage.
Definition: nusoap.php:7206
setCurlOption($option, $value)
sets user-specified cURL options
Definition: nusoap.php:7723
setCredentials($username, $password, $authtype='basic', $certRequest=array())
if authenticating, set user credentials here
Definition: nusoap.php:7803
setHTTPProxy($proxyhost, $proxyport, $proxyusername='', $proxypassword='')
set proxy info here
Definition: nusoap.php:7786
getProxy()
dynamically creates an instance of a proxy class, allowing user to directly call methods from wsdl
Definition: nusoap.php:7887
send($msg, $soapaction='', $timeout=0, $response_timeout=30)
send the SOAP message
Definition: nusoap.php:7590
setUseCURL($use)
Set whether to try to use cURL connections if possible.
Definition: nusoap.php:7831
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:7335
getProxyClassCode()
dynamically creates proxy class code
Definition: nusoap.php:7996
checkCookies()
checks all Cookies and delete those which are expired
Definition: nusoap.php:8087
getHTTPContentType()
gets the HTTP content type for the current request.
Definition: nusoap.php:8022
setHTTPEncoding($enc='gzip, deflate')
use HTTP encoding
Definition: nusoap.php:7819
getHeader()
get the SOAP response Header (parsed)
Definition: nusoap.php:7772
decodeUTF8($bool)
Definition: nusoap.php:8047
useHTTPPersistentConnection()
use HTTP persistent connections if possible
Definition: nusoap.php:7842
setCookie($name, $value)
adds a new Cookie into $this->cookies array
Definition: nusoap.php:8061
getHTTPContentTypeCharset()
gets the HTTP content type charset for the current request.
Definition: nusoap.php:8036
getOperationData($operation)
get available data pertaining to an operation
Definition: nusoap.php:7562
getDefaultRpcParams()
gets the default RPC parameter setting.
Definition: nusoap.php:7859
checkWSDL()
check WSDL passed as an instance or pulled from an endpoint
Definition: nusoap.php:7519
setHeaders($headers)
set the SOAP headers
Definition: nusoap.php:7748
loadWSDL()
instantiate wsdl object and parse wsdl file
Definition: nusoap.php:7546
getHTTPBody($soapmsg)
gets the HTTP body for the current request.
Definition: nusoap.php:8009
setDefaultRpcParams($rpcParams)
sets the default RPC parameter setting.
Definition: nusoap.php:7875
__construct($endpoint, $wsdl=false, $proxyhost=false, $proxyport=false, $proxyusername=false, $proxypassword=false, $timeout=0, $response_timeout=30)
constructor
Definition: nusoap.php:7276
setEndpoint($endpoint)
sets the SOAP endpoint, which can override WSDL
Definition: nusoap.php:7736
UpdateCookies($cookies)
updates the current cookies with a new set
Definition: nusoap.php:8121
getHeaders()
get the SOAP response headers (namespace resolution incomplete)
Definition: nusoap.php:7761
_getProxyClassCode($r)
dynamically creates proxy class code
Definition: nusoap.php:7936
getCookies()
gets all Cookies
Definition: nusoap.php:8076
parseResponse($headers, $data)
processes SOAP message returned from server
Definition: nusoap.php:7670
Contains information for a SOAP fault.
Definition: nusoap.php:1036
serialize()
serialize a fault
Definition: nusoap.php:1085
__construct($faultcode, $faultactor='', $faultstring='', $faultdetail='')
constructor
Definition: nusoap.php:1070
nusoap_parser class parses SOAP XML messages into native PHP values
Definition: nusoap.php:6546
$root_struct_namespace
Definition: nusoap.php:6552
character_data($parser, $data)
element content handler
Definition: nusoap.php:6946
get_soapbody()
get the parsed SOAP Body (NULL if there was none)
Definition: nusoap.php:6984
end_element($parser, $name)
end-element handler
Definition: nusoap.php:6841
getHeaders()
get the unparsed SOAP Header
Definition: nusoap.php:7006
get_response()
get the parsed message (SOAP Body)
Definition: nusoap.php:6973
decodeSimple($value, $type, $typens)
decodes simple types into PHP variables
Definition: nusoap.php:7020
get_soapheader()
get the parsed SOAP Header (NULL if there was none)
Definition: nusoap.php:6995
start_element($parser, $name, $attrs)
start-element handler
Definition: nusoap.php:6685
buildVal($pos)
builds response structures for compound values (arrays/structs) and scalars
Definition: nusoap.php:7065
__construct($xml, $encoding='UTF-8', $method='', $decode_utf8=true)
constructor that actually does the parsing
Definition: nusoap.php:6590
nusoap_server allows the user to create a SOAP server that is capable of receiving messages and retur...
Definition: nusoap.php:3523
verify_method($operation, $request)
takes the value that was created by parsing the request and compares to the method's signature,...
Definition: nusoap.php:4303
$methodreturnisliteralxml
Definition: nusoap.php:3632
getHTTPBody($soapmsg)
gets the HTTP body for the current response.
Definition: nusoap.php:4375
invoke_method()
invokes a PHP function for the requested SOAP method
Definition: nusoap.php:3984
add_to_map($methodname, $in, $out)
add a method to the dispatch map (this has been replaced by the register method)
Definition: nusoap.php:4416
getHTTPContentType()
gets the HTTP content type for the current response.
Definition: nusoap.php:4388
__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:3680
parse_request($data='')
parses a request
Definition: nusoap.php:3936
getHTTPContentTypeCharset()
gets the HTTP content type charset for the current response.
Definition: nusoap.php:4402
serialize_return()
serializes the return value from a PHP function into a full SOAP Envelope
Definition: nusoap.php:4130
send_response()
sends an HTTP response
Definition: nusoap.php:4223
fault($faultcode, $faultstring, $faultactor='', $faultdetail='')
Specify a fault to be returned to the client.
Definition: nusoap.php:4505
parse_http_headers()
parses HTTP request headers.
Definition: nusoap.php:3807
service($data)
processes request and returns response
Definition: nusoap.php:3744
parseRequest($headers, $data)
processes SOAP message received from client
Definition: nusoap.php:4323
configureWSDL($serviceName, $namespace=false, $endpoint=false, $style='rpc', $transport='http://schemas.xmlsoap.org/soap/http', $schemaTargetNamespace=false)
Sets up wsdl object.
Definition: nusoap.php:4525
parses an XML Schema, allows access to it's data, other utility methods.
Definition: nusoap.php:1128
schemaCharacterData($parser, $data)
element content handler
Definition: nusoap.php:1628
getTypeDef($type)
returns an associative array of information about a given type returns false if no type exists by the...
Definition: nusoap.php:1808
addComplexType($name, $typeClass='complexType', $phpType='array', $compositor='', $restrictionBase='', $elements=array(), $attrs=array(), $arrayType='')
adds a complex type to the schema
Definition: nusoap.php:1995
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:1922
addElement($attrs)
adds an element to the schema
Definition: nusoap.php:2045
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:1774
xdebug($string)
adds debug data to the clas level debug string
Definition: nusoap.php:1757
addSimpleType($name, $restrictionBase='', $typeClass='simpleType', $phpType='scalar', $enumeration=array())
adds a simple type to the schema
Definition: nusoap.php:2024
serializeSchema()
serialize the schema
Definition: nusoap.php:1639
__construct($schema='', $xml='', $namespaces=array())
constructor
Definition: nusoap.php:1166
parseString($xml, $type)
parse an XML string
Definition: nusoap.php:1226
schemaEndElement($parser, $name)
end-element handler
Definition: nusoap.php:1590
schemaStartElement($parser, $name, $attrs)
start-element handler
Definition: nusoap.php:1292
serializeTypeDef($type)
returns a sample serialization of a given type, or false if no type by the given name
Definition: nusoap.php:1885
parseFile($xml, $type)
parse an XML file
Definition: nusoap.php:1199
CreateTypeName($ename)
gets a type name for an unnamed type
Definition: nusoap.php:1275
Backward compatibility.
Definition: nusoap.php:1111
Backward compatibility.
Definition: nusoap.php:7178
Backward compatibility.
Definition: nusoap.php:4601
transport class for sending/receiving data via HTTP and HTTPS NOTE: PHP must be compiled with the CUR...
Definition: nusoap.php:2187
sendRequest($data, $cookies=null)
sends the SOAP request via HTTP[S]
Definition: nusoap.php:2932
setCurlOption($option, $value)
sets a cURL option
Definition: nusoap.php:2253
getCookiesForRequest($cookies, $secure=false)
sort out cookies for the current request
Definition: nusoap.php:3467
send($data, $timeout=0, $response_timeout=30, $cookies=null)
sends the SOAP request and gets the SOAP response via HTTP[S]
Definition: nusoap.php:2600
parseCookie($cookie_str)
parse an incoming Cookie into it's parts
Definition: nusoap.php:3400
setURL($url)
sets the URL to which to connect
Definition: nusoap.php:2293
getResponse()
gets the SOAP response via HTTP[S]
Definition: nusoap.php:2990
setContentType($type, $charset=false)
sets the content-type for the SOAP message to be sent
Definition: nusoap.php:3368
unsetHeader($name)
unsets an HTTP header
Definition: nusoap.php:2279
isSkippableCurlHeader(&$data)
Test if the given string starts with a header that is to be skipped.
Definition: nusoap.php:2796
setSOAPAction($soapaction)
set the soapaction value
Definition: nusoap.php:2731
setEncoding($enc='gzip, deflate')
use http encoding
Definition: nusoap.php:2742
usePersistentConnection()
specifies that an HTTP persistent connection should be used
Definition: nusoap.php:3379
setCredentials($username, $password, $authtype='basic', $digestRequest=array(), $certRequest=array())
if authenticating, set user credentials here
Definition: nusoap.php:2656
buildPayload($data, $cookie_str='')
Writes the payload, including HTTP headers, to $this->outgoing_payload.
Definition: nusoap.php:2884
connect($connection_timeout=0, $response_timeout=30)
establish an HTTP connection
Definition: nusoap.php:2357
setHeader($name, $value)
sets an HTTP header
Definition: nusoap.php:2267
io_method()
gets the I/O method to use
Definition: nusoap.php:2338
decodeChunked($buffer, $lb)
decode a string that is encoded w/ "chunked' transfer encoding as defined in RFC2068 19....
Definition: nusoap.php:2826
setProxy($proxyhost, $proxyport, $proxyusername='', $proxypassword='', $proxyauthtype='basic')
set proxy info here
Definition: nusoap.php:2767
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:2641
__construct($url, $curl_options=null, $use_curl=false)
constructor
Definition: nusoap.php:2231
For creating serializable abstractions of native PHP types.
Definition: nusoap.php:2081
serialize($use='encoded')
return serialized value
Definition: nusoap.php:2154
$element_ns
Definition: nusoap.php:2109
__construct($name='soapval', $type=false, $value=-1, $element_ns=false, $type_ns=false, $attributes=false)
constructor
Definition: nusoap.php:2136
decode()
decodes a soapval object into a PHP native type
Definition: nusoap.php:2165
$attributes
Definition: nusoap.php:2123
parses a WSDL file, allows access to it's data, other utility methods.
Definition: nusoap.php:4618
$currentMessage
Definition: nusoap.php:4627
$import
Definition: nusoap.php:4640
$username
Definition: nusoap.php:4656
$ports
Definition: nusoap.php:4633
$proxyhost
Definition: nusoap.php:4647
character_data($parser, $data)
element content handler
Definition: nusoap.php:5150
serializeComplexTypeAttributes($typeDef, $value, $ns, $uqType)
serializes the attributes for a complexType
Definition: nusoap.php:6211
$opData
Definition: nusoap.php:4635
$currentSchema
Definition: nusoap.php:4623
getBindingData($binding)
Definition: nusoap.php:5180
serializeRPCParameters($operation, $direction, $parameters, $bindingType='soap')
serialize PHP values according to a WSDL message definition contrary to the method name,...
Definition: nusoap.php:5734
$currentPortType
Definition: nusoap.php:4630
addElement($attrs)
adds an element to the WSDL types
Definition: nusoap.php:6440
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:5297
$status
Definition: nusoap.php:4636
getOperations($bindingType='soap')
returns an assoc array of operation names => operation data
Definition: nusoap.php:5194
setCredentials($username, $password, $authtype='basic', $certRequest=array())
if authenticating, set user credentials here
Definition: nusoap.php:5170
$proxypassword
Definition: nusoap.php:4650
$certRequest
Definition: nusoap.php:4659
getOperationData($operation, $bindingType='soap')
returns an associative array of data necessary for calling an operation
Definition: nusoap.php:5226
$portTypes
Definition: nusoap.php:4629
$currentOperation
Definition: nusoap.php:4628
$messages
Definition: nusoap.php:4626
serializeParameters($operation, $direction, $parameters)
serialize a PHP value according to a WSDL message definition
Definition: nusoap.php:5829
fetchWSDL($wsdl)
fetches the WSDL document and parses it
Definition: nusoap.php:4697
$password
Definition: nusoap.php:4657
addSimpleType($name, $restrictionBase='', $typeClass='simpleType', $phpType='scalar', $enumeration=array())
adds an XML Schema simple type to the WSDL types
Definition: nusoap.php:6425
$depth
Definition: nusoap.php:4644
$bindings
Definition: nusoap.php:4631
serialize($debug=0)
serialize the parsed wsdl
Definition: nusoap.php:5496
$wsdl
Definition: nusoap.php:4620
$timeout
Definition: nusoap.php:4651
$endpoint
Definition: nusoap.php:4638
$use_curl
Definition: nusoap.php:4654
$proxyusername
Definition: nusoap.php:4649
getOperationDataForSoapAction($soapAction, $bindingType='soap')
returns an associative array of data necessary for calling an operation
Definition: nusoap.php:5258
$documentation
Definition: nusoap.php:4637
webDescription()
prints html description of services
Definition: nusoap.php:5354
serializeType($name, $type, $value, $use='encoded', $encodingStyle=false, $unqualified=false)
serializes a PHP value according a given type definition
Definition: nusoap.php:5907
parseWSDL($wsdl='')
parses the wsdl document
Definition: nusoap.php:4801
$message
Definition: nusoap.php:4624
parametersMatchWrapped($type, &$parameters)
determine whether a set of parameters are unwrapped when they are expect to be wrapped,...
Definition: nusoap.php:5640
start_element($parser, $name, $attrs)
start-element handler
Definition: nusoap.php:4906
$proxyport
Definition: nusoap.php:4648
$authtype
Definition: nusoap.php:4658
end_element($parser, $name)
end-element handler
Definition: nusoap.php:5119
$parser
Definition: nusoap.php:4642
$depth_array
Definition: nusoap.php:4645
serializeComplexTypeElements($typeDef, $value, $ns, $uqType, $use='encoded', $encodingStyle=false)
serializes the elements for a complexType
Definition: nusoap.php:6274
$position
Definition: nusoap.php:4643
$schemas
Definition: nusoap.php:4622
$currentPort
Definition: nusoap.php:4634
$complexTypes
Definition: nusoap.php:4625
$curl_options
Definition: nusoap.php:4653
__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:4675
$response_timeout
Definition: nusoap.php:4652
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:6377
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:6460
$currentBinding
Definition: nusoap.php:4632
$c
Definition: cli.php:38
if($err=$client->getError()) $namespace
if(! $DIC->user() ->getId()||!ilLTIConsumerAccess::hasCustomProviderCreationAccess()) $params
Definition: ltiregstart.php:33
$scope
Definition: ltiregstart.php:53
$path
Definition: ltiservices.php:32
if(empty($path)) $serviceName
Definition: ltiservices.php:38
$res
Definition: ltiservices.php:69
if($clientAssertionType !='urn:ietf:params:oauth:client-assertion-type:jwt-bearer'|| $grantType !='client_credentials') $parts
Definition: ltitoken.php:64
if(count($parts) !=3) $payload
Definition: ltitoken.php:70
if($format !==null) $name
Definition: metadata.php:247
$i
Definition: metadata.php:41
$attributes
Definition: metadata.php:248
$xml
Definition: metadata.php:351
__construct(Container $dic, ilPlugin $plugin)
@inheritDoc
string $key
Consumer key/client ID value.
Definition: System.php:193
$a
thx to https://mlocati.github.io/php-cs-fixer-configurator for the examples
catch(\Exception $e) $req
Definition: xapiproxy.php:93
usleepWindows($usec)
sleeps some number of microseconds
Definition: nusoap.php:1012
iso8601_to_timestamp($datestr)
convert ISO 8601 compliant date string to unix timestamp
Definition: nusoap.php:971
timestamp_to_iso8601($timestamp, $utc=true)
convert unix timestamp to ISO 8601 compliant date string
Definition: nusoap.php:941
$type
$url
$_SERVER['HTTP_HOST']
Definition: raiseError.php:10
$http
Definition: raiseError.php:7
$_GET['client_id']
Definition: saml1-acs.php:21
$param
Definition: xapitoken.php:46
$cols
Definition: xhr_table.php:11
$rows
Definition: xhr_table.php:10