ILIAS  release_10 Revision v10.1-43-ga1241a92c2f
nusoap.php
Go to the documentation of this file.
1 <?php
2 
19 /*
20 $Id$
21 
22 NuSOAP - Web Services Toolkit for PHP
23 
24 Copyright (c) 2002 NuSphere Corporation
25 
26 This library is free software; you can redistribute it and/or
27 modify it under the terms of the GNU Lesser General Public
28 License as published by the Free Software Foundation; either
29 version 2.1 of the License, or (at your option) any later version.
30 
31 This library is distributed in the hope that it will be useful,
32 but WITHOUT ANY WARRANTY; without even the implied warranty of
33 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
34 Lesser General Public License for more details.
35 
36 You should have received a copy of the GNU Lesser General Public
37 License along with this library; if not, write to the Free Software
38 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
39 
40 The NuSOAP project home is:
41 http://sourceforge.net/projects/nusoap/
42 
43 The primary support for NuSOAP is the mailing list:
44 nusoap-general@lists.sourceforge.net
45 
46 If you have any questions or comments, please email:
47 
48 Dietrich Ayala
49 dietrich@ganx4.com
50 http://dietrich.ganx4.com/nusoap
51 
52 NuSphere Corporation
53 http://www.nusphere.com
54 
55 */
56 
57 /*
58  * Some of the standards implmented in whole or part by NuSOAP:
59  *
60  * SOAP 1.1 (http://www.w3.org/TR/2000/NOTE-SOAP-20000508/)
61  * WSDL 1.1 (http://www.w3.org/TR/2001/NOTE-wsdl-20010315)
62  * SOAP Messages With Attachments (http://www.w3.org/TR/SOAP-attachments)
63  * XML 1.0 (http://www.w3.org/TR/2006/REC-xml-20060816/)
64  * Namespaces in XML 1.0 (http://www.w3.org/TR/2006/REC-xml-names-20060816/)
65  * XML Schema 1.0 (http://www.w3.org/TR/xmlschema-0/)
66  * RFC 2045 Multipurpose Internet Mail Extensions (MIME) Part One: Format of Internet Message Bodies
67  * RFC 2068 Hypertext Transfer Protocol -- HTTP/1.1
68  * RFC 2617 HTTP Authentication: Basic and Digest Access Authentication
69  */
70 
71 // class variable emulation
72 // cf. http://www.webkreator.com/php/techniques/php-static-class-variables.html
73 
74 // alex patch: we need an object here, otherwise we will get a warning in php 5.4
75 if (
76  !isset($GLOBALS['_transient']) ||
77  !isset($GLOBALS['_transient']['static']) ||
78  !isset($GLOBALS['_transient']['static']['nusoap_base']) ||
79  !is_object($GLOBALS['_transient']['static']['nusoap_base'])
80 ) {
81  $GLOBALS['_transient']['static']['nusoap_base'] = new stdClass();
82 }
83 $GLOBALS['_transient']['static']['nusoap_base']->globalDebugLevel = 0;
84 
95 {
102  public $title = 'NuSOAP';
109  public $version = '0.7.3';
116  public $revision = '$Revision$';
123  public $error_str = '';
130  public $debug_str = '';
138  public $charencoding = true;
145  public $debugLevel;
146 
153  public $XMLSchemaVersion = 'http://www.w3.org/2001/XMLSchema';
154 
161  //var $soap_defencoding = 'ISO-8859-1';
162  public $soap_defencoding = 'UTF-8';
163 
172  public $namespaces = array(
173  'SOAP-ENV' => 'http://schemas.xmlsoap.org/soap/envelope/',
174  'xsd' => 'http://www.w3.org/2001/XMLSchema',
175  'xsi' => 'http://www.w3.org/2001/XMLSchema-instance',
176  'SOAP-ENC' => 'http://schemas.xmlsoap.org/soap/encoding/'
177  );
178 
185  public $usedNamespaces = array();
186 
194  public $typemap = array(
195  'http://www.w3.org/2001/XMLSchema' => array(
196  'string'=>'string','boolean'=>'boolean','float'=>'double','double'=>'double','decimal'=>'double',
197  'duration'=>'','dateTime'=>'string','time'=>'string','date'=>'string','gYearMonth'=>'',
198  'gYear'=>'','gMonthDay'=>'','gDay'=>'','gMonth'=>'','hexBinary'=>'string','base64Binary'=>'string',
199  // abstract "any" types
200  'anyType'=>'string','anySimpleType'=>'string',
201  // derived datatypes
202  'normalizedString'=>'string','token'=>'string','language'=>'','NMTOKEN'=>'','NMTOKENS'=>'','Name'=>'','NCName'=>'','ID'=>'',
203  'IDREF'=>'','IDREFS'=>'','ENTITY'=>'','ENTITIES'=>'','integer'=>'integer','nonPositiveInteger'=>'integer',
204  'negativeInteger'=>'integer','long'=>'integer','int'=>'integer','short'=>'integer','byte'=>'integer','nonNegativeInteger'=>'integer',
205  'unsignedLong'=>'','unsignedInt'=>'','unsignedShort'=>'','unsignedByte'=>'','positiveInteger'=>''),
206  'http://www.w3.org/2000/10/XMLSchema' => array(
207  'i4'=>'','int'=>'integer','boolean'=>'boolean','string'=>'string','double'=>'double',
208  'float'=>'double','dateTime'=>'string',
209  'timeInstant'=>'string','base64Binary'=>'string','base64'=>'string','ur-type'=>'array'),
210  'http://www.w3.org/1999/XMLSchema' => array(
211  'i4'=>'','int'=>'integer','boolean'=>'boolean','string'=>'string','double'=>'double',
212  'float'=>'double','dateTime'=>'string',
213  'timeInstant'=>'string','base64Binary'=>'string','base64'=>'string','ur-type'=>'array'),
214  'http://soapinterop.org/xsd' => array('SOAPStruct'=>'struct'),
215  'http://schemas.xmlsoap.org/soap/encoding/' => array('base64'=>'string','array'=>'array','Array'=>'array'),
216  'http://xml.apache.org/xml-soap' => array('Map')
217  );
218 
227  public $xmlEntities = array('quot' => '"','amp' => '&',
228  'lt' => '<','gt' => '>','apos' => "'");
229 
235  public function __construct()
236  {
237  $this->debugLevel = $GLOBALS['_transient']['static']['nusoap_base']->globalDebugLevel;
238  }
239 
246  public function getGlobalDebugLevel()
247  {
248  return $GLOBALS['_transient']['static']['nusoap_base']->globalDebugLevel;
249  }
250 
257  public function setGlobalDebugLevel($level)
258  {
259  $GLOBALS['_transient']['static']['nusoap_base']->globalDebugLevel = $level;
260  }
261 
268  public function getDebugLevel()
269  {
270  return $this->debugLevel;
271  }
272 
279  public function setDebugLevel($level)
280  {
281  $this->debugLevel = $level;
282  }
283 
290  public function debug($string)
291  {
292  if ($this->debugLevel > 0) {
293  $this->appendDebug($this->getmicrotime() . ' ' . get_class($this) . ": $string\n");
294  }
295  }
296 
303  public function appendDebug($string)
304  {
305  if ($this->debugLevel > 0) {
306  // it would be nice to use a memory stream here to use
307  // memory more efficiently
308  $this->debug_str .= $string;
309  }
310  }
311 
317  public function clearDebug()
318  {
319  // it would be nice to use a memory stream here to use
320  // memory more efficiently
321  $this->debug_str = '';
322  }
323 
330  public function &getDebug()
331  {
332  // it would be nice to use a memory stream here to use
333  // memory more efficiently
334  return $this->debug_str;
335  }
336 
344  public function &getDebugAsXMLComment()
345  {
346  // it would be nice to use a memory stream here to use
347  // memory more efficiently
348  while (strpos($this->debug_str, '--')) {
349  $this->debug_str = str_replace('--', '- -', $this->debug_str);
350  }
351  $ret = "<!--\n" . $this->debug_str . "\n-->";
352  return $ret;
353  }
354 
361  public function expandEntities($val)
362  {
363  if ($this->charencoding) {
364  $val = str_replace('&', '&amp;', $val);
365  $val = str_replace("'", '&apos;', $val);
366  $val = str_replace('"', '&quot;', $val);
367  $val = str_replace('<', '&lt;', $val);
368  $val = str_replace('>', '&gt;', $val);
369  }
370  return $val;
371  }
372 
379  public function getError()
380  {
381  if ($this->error_str != '') {
382  return $this->error_str;
383  }
384  return false;
385  }
386 
393  public function setError($str)
394  {
395  $this->error_str = $str;
396  }
397 
405  public function isArraySimpleOrStruct($val)
406  {
407  $keyList = array_keys($val);
408  foreach ($keyList as $keyListValue) {
409  if (!is_int($keyListValue)) {
410  return 'arrayStruct';
411  }
412  }
413  return 'arraySimple';
414  }
415 
431  public function serialize_val($val, $name=false, $type=false, $name_ns=false, $type_ns=false, $attributes=false, $use='encoded', $soapval=false)
432  {
433  $this->debug("in serialize_val: name=$name, type=$type, name_ns=$name_ns, type_ns=$type_ns, use=$use, soapval=$soapval");
434  $this->appendDebug('value=' . $this->varDump($val));
435  $this->appendDebug('attributes=' . $this->varDump($attributes));
436 
437  if (is_object($val) && get_class($val) == 'soapval' && (! $soapval)) {
438  $this->debug("serialize_val: serialize soapval");
439  $xml = $val->serialize($use);
440  $this->appendDebug($val->getDebug());
441  $val->clearDebug();
442  $this->debug("serialize_val of soapval returning $xml");
443  return $xml;
444  }
445  // force valid name if necessary
446  if (is_numeric($name)) {
447  $name = '__numeric_' . $name;
448  } elseif (! $name) {
449  $name = 'noname';
450  }
451  // if name has ns, add ns prefix to name
452  $xmlns = '';
453  if ($name_ns) {
454  $prefix = 'nu' . rand(1000, 9999);
455  $name = $prefix . ':' . $name;
456  $xmlns .= " xmlns:$prefix=\"$name_ns\"";
457  }
458  // if type is prefixed, create type prefix
459  if ($type_ns != '' && $type_ns == $this->namespaces['xsd']) {
460  // need to fix this. shouldn't default to xsd if no ns specified
461  // w/o checking against typemap
462  $type_prefix = 'xsd';
463  } elseif ($type_ns) {
464  $type_prefix = 'ns' . rand(1000, 9999);
465  $xmlns .= " xmlns:$type_prefix=\"$type_ns\"";
466  }
467  // serialize attributes if present
468  $atts = '';
469  if ($attributes) {
470  foreach ($attributes as $k => $v) {
471  $atts .= " $k=\"" . $this->expandEntities($v) . '"';
472  }
473  }
474  // serialize null value
475  if (is_null($val)) {
476  $this->debug("serialize_val: serialize null");
477  if ($use == 'literal') {
478  // TODO: depends on minOccurs
479  $xml = "<$name$xmlns$atts/>";
480  $this->debug("serialize_val returning $xml");
481  return $xml;
482  } else {
483  if (isset($type) && isset($type_prefix)) {
484  $type_str = " xsi:type=\"$type_prefix:$type\"";
485  } else {
486  $type_str = '';
487  }
488  $xml = "<$name$xmlns$type_str$atts xsi:nil=\"true\"/>";
489  $this->debug("serialize_val returning $xml");
490  return $xml;
491  }
492  }
493  // serialize if an xsd built-in primitive type
494  if ($type != '' && isset($this->typemap[$this->XMLSchemaVersion][$type])) {
495  $this->debug("serialize_val: serialize xsd built-in primitive type");
496  if (is_bool($val)) {
497  if ($type == 'boolean') {
498  $val = $val ? 'true' : 'false';
499  } elseif (! $val) {
500  $val = 0;
501  }
502  } elseif (is_string($val)) {
503  $val = $this->expandEntities($val);
504  }
505  if ($use == 'literal') {
506  $xml = "<$name$xmlns$atts>$val</$name>";
507  $this->debug("serialize_val returning $xml");
508  return $xml;
509  } else {
510  $xml = "<$name$xmlns xsi:type=\"xsd:$type\"$atts>$val</$name>";
511  $this->debug("serialize_val returning $xml");
512  return $xml;
513  }
514  }
515  // detect type and serialize
516  $xml = '';
517  switch (true) {
518  case (is_bool($val) || $type == 'boolean'):
519  $this->debug("serialize_val: serialize boolean");
520  if ($type == 'boolean') {
521  $val = $val ? 'true' : 'false';
522  } elseif (! $val) {
523  $val = 0;
524  }
525  if ($use == 'literal') {
526  $xml .= "<$name$xmlns$atts>$val</$name>";
527  } else {
528  $xml .= "<$name$xmlns xsi:type=\"xsd:boolean\"$atts>$val</$name>";
529  }
530  break;
531  case (is_int($val) || is_long($val) || $type == 'int'):
532  $this->debug("serialize_val: serialize int");
533  if ($use == 'literal') {
534  $xml .= "<$name$xmlns$atts>$val</$name>";
535  } else {
536  $xml .= "<$name$xmlns xsi:type=\"xsd:int\"$atts>$val</$name>";
537  }
538  break;
539  case (is_float($val)|| is_double($val) || $type == 'float'):
540  $this->debug("serialize_val: serialize float");
541  if ($use == 'literal') {
542  $xml .= "<$name$xmlns$atts>$val</$name>";
543  } else {
544  $xml .= "<$name$xmlns xsi:type=\"xsd:float\"$atts>$val</$name>";
545  }
546  break;
547  case (is_string($val) || $type == 'string'):
548  $this->debug("serialize_val: serialize string");
549  $val = $this->expandEntities($val);
550  if ($use == 'literal') {
551  $xml .= "<$name$xmlns$atts>$val</$name>";
552  } else {
553  $xml .= "<$name$xmlns xsi:type=\"xsd:string\"$atts>$val</$name>";
554  }
555  break;
556  case is_object($val):
557  $this->debug("serialize_val: serialize object");
558  if (get_class($val) == 'soapval') {
559  $this->debug("serialize_val: serialize soapval object");
560  $pXml = $val->serialize($use);
561  $this->appendDebug($val->getDebug());
562  $val->clearDebug();
563  } else {
564  if (! $name) {
565  $name = get_class($val);
566  $this->debug("In serialize_val, used class name $name as element name");
567  } else {
568  $this->debug("In serialize_val, do not override name $name for element name for class " . get_class($val));
569  }
570  foreach (get_object_vars($val) as $k => $v) {
571  $pXml = isset($pXml) ? $pXml . $this->serialize_val($v, $k, false, false, false, false, $use) : $this->serialize_val($v, $k, false, false, false, false, $use);
572  }
573  }
574  if (isset($type) && isset($type_prefix)) {
575  $type_str = " xsi:type=\"$type_prefix:$type\"";
576  } else {
577  $type_str = '';
578  }
579  if ($use == 'literal') {
580  $xml .= "<$name$xmlns$atts>$pXml</$name>";
581  } else {
582  $xml .= "<$name$xmlns$type_str$atts>$pXml</$name>";
583  }
584  break;
585  break;
586  case (is_array($val) || $type):
587  // detect if struct or array
588  $valueType = $this->isArraySimpleOrStruct($val);
589  if ($valueType=='arraySimple' || preg_match('/^ArrayOf/', $type)) {
590  $this->debug("serialize_val: serialize array");
591  $i = 0;
592  if (is_array($val) && count($val)> 0) {
593  foreach ($val as $v) {
594  if (is_object($v) && get_class($v) == 'soapval') {
595  $tt_ns = $v->type_ns;
596  $tt = $v->type;
597  } elseif (is_array($v)) {
598  $tt = $this->isArraySimpleOrStruct($v);
599  } else {
600  $tt = gettype($v);
601  }
602  $array_types[$tt] = 1;
603  // TODO: for literal, the name should be $name
604  $xml .= $this->serialize_val($v, 'item', false, false, false, false, $use);
605  ++$i;
606  }
607  if (count($array_types) > 1) {
608  $array_typename = 'xsd:anyType';
609  } elseif (isset($tt) && isset($this->typemap[$this->XMLSchemaVersion][$tt])) {
610  if ($tt == 'integer') {
611  $tt = 'int';
612  }
613  $array_typename = 'xsd:' . $tt;
614  } elseif (isset($tt) && $tt == 'arraySimple') {
615  $array_typename = 'SOAP-ENC:Array';
616  } elseif (isset($tt) && $tt == 'arrayStruct') {
617  $array_typename = 'unnamed_struct_use_soapval';
618  } else {
619  // if type is prefixed, create type prefix
620  if ($tt_ns != '' && $tt_ns == $this->namespaces['xsd']) {
621  $array_typename = 'xsd:' . $tt;
622  } elseif ($tt_ns) {
623  $tt_prefix = 'ns' . rand(1000, 9999);
624  $array_typename = "$tt_prefix:$tt";
625  $xmlns .= " xmlns:$tt_prefix=\"$tt_ns\"";
626  } else {
627  $array_typename = $tt;
628  }
629  }
630  $array_type = $i;
631  if ($use == 'literal') {
632  $type_str = '';
633  } elseif (isset($type) && isset($type_prefix)) {
634  $type_str = " xsi:type=\"$type_prefix:$type\"";
635  } else {
636  $type_str = " xsi:type=\"SOAP-ENC:Array\" SOAP-ENC:arrayType=\"" . $array_typename . "[$array_type]\"";
637  }
638  // empty array
639  } else {
640  if ($use == 'literal') {
641  $type_str = '';
642  } elseif (isset($type) && isset($type_prefix)) {
643  $type_str = " xsi:type=\"$type_prefix:$type\"";
644  } else {
645  $type_str = " xsi:type=\"SOAP-ENC:Array\" SOAP-ENC:arrayType=\"xsd:anyType[0]\"";
646  }
647  }
648  // TODO: for array in literal, there is no wrapper here
649  $xml = "<$name$xmlns$type_str$atts>" . $xml . "</$name>";
650  } else {
651  // got a struct
652  $this->debug("serialize_val: serialize struct");
653  if (isset($type) && isset($type_prefix)) {
654  $type_str = " xsi:type=\"$type_prefix:$type\"";
655  } else {
656  $type_str = '';
657  }
658  if ($use == 'literal') {
659  $xml .= "<$name$xmlns$atts>";
660  } else {
661  $xml .= "<$name$xmlns$type_str$atts>";
662  }
663  foreach ($val as $k => $v) {
664  // Apache Map
665  if ($type == 'Map' && $type_ns == 'http://xml.apache.org/xml-soap') {
666  $xml .= '<item>';
667  $xml .= $this->serialize_val($k, 'key', false, false, false, false, $use);
668  $xml .= $this->serialize_val($v, 'value', false, false, false, false, $use);
669  $xml .= '</item>';
670  } else {
671  $xml .= $this->serialize_val($v, $k, false, false, false, false, $use);
672  }
673  }
674  $xml .= "</$name>";
675  }
676  break;
677  default:
678  $this->debug("serialize_val: serialize unknown");
679  $xml .= 'not detected, got ' . gettype($val) . ' for ' . $val;
680  break;
681  }
682  $this->debug("serialize_val returning $xml");
683  return $xml;
684  }
685 
698  public function serializeEnvelope($body, $headers=false, $namespaces=array(), $style='rpc', $use='encoded', $encodingStyle='http://schemas.xmlsoap.org/soap/encoding/')
699  {
700  // TODO: add an option to automatically run utf8_encode on $body and $headers
701  // if $this->soap_defencoding is UTF-8. Not doing this automatically allows
702  // one to send arbitrary UTF-8 characters, not just characters that map to ISO-8859-1
703 
704  $this->debug("In serializeEnvelope length=" . strlen($body) . " body (max 1000 characters)=" . substr($body, 0, 1000) . " style=$style use=$use encodingStyle=$encodingStyle");
705  $this->debug("headers:");
706  $this->appendDebug($this->varDump($headers));
707  $this->debug("namespaces:");
708  $this->appendDebug($this->varDump($namespaces));
709 
710  // serialize namespaces
711  $ns_string = '';
712  foreach (array_merge($this->namespaces, $namespaces) as $k => $v) {
713  $ns_string .= " xmlns:$k=\"$v\"";
714  }
715  if ($encodingStyle) {
716  $ns_string = " SOAP-ENV:encodingStyle=\"$encodingStyle\"$ns_string";
717  }
718 
719  // serialize headers
720  if ($headers) {
721  if (is_array($headers)) {
722  $xml = '';
723  foreach ($headers as $k => $v) {
724  if (is_object($v) && get_class($v) == 'soapval') {
725  $xml .= $this->serialize_val($v, false, false, false, false, false, $use);
726  } else {
727  $xml .= $this->serialize_val($v, $k, false, false, false, false, $use);
728  }
729  }
730  $headers = $xml;
731  $this->debug("In serializeEnvelope, serialized array of headers to $headers");
732  }
733  $headers = "<SOAP-ENV:Header>" . $headers . "</SOAP-ENV:Header>";
734  }
735  // serialize envelope
736  return
737  '<?xml version="1.0" encoding="' . $this->soap_defencoding . '"?' . ">" .
738  '<SOAP-ENV:Envelope' . $ns_string . ">" .
739  $headers .
740  "<SOAP-ENV:Body>" .
741  $body .
742  "</SOAP-ENV:Body>" .
743  "</SOAP-ENV:Envelope>";
744  }
745 
754  public function formatDump($str)
755  {
756  $str = htmlspecialchars($str);
757  return nl2br($str);
758  }
759 
767  public function contractQname($qname)
768  {
769  // get element namespace
770  //$this->xdebug("Contract $qname");
771  if (strrpos($qname, ':')) {
772  // get unqualified name
773  $name = substr($qname, strrpos($qname, ':') + 1);
774  // get ns
775  $ns = substr($qname, 0, strrpos($qname, ':'));
776  $p = $this->getPrefixFromNamespace($ns);
777  if ($p) {
778  return $p . ':' . $name;
779  }
780  return $qname;
781  } else {
782  return $qname;
783  }
784  }
785 
793  public function expandQname($qname)
794  {
795  // get element prefix
796  if (strpos($qname, ':') && !preg_match('/^http:\/\//', $qname)) {
797  // get unqualified name
798  $name = substr(strstr($qname, ':'), 1);
799  // get ns prefix
800  $prefix = substr($qname, 0, strpos($qname, ':'));
801  if (isset($this->namespaces[$prefix])) {
802  return $this->namespaces[$prefix] . ':' . $name;
803  } else {
804  return $qname;
805  }
806  } else {
807  return $qname;
808  }
809  }
810 
819  public function getLocalPart($str)
820  {
821  if ($sstr = strrchr($str, ':')) {
822  // get unqualified name
823  return substr($sstr, 1);
824  } else {
825  return $str;
826  }
827  }
828 
837  public function getPrefix($str)
838  {
839  if ($pos = strrpos($str, ':')) {
840  // get prefix
841  return substr($str, 0, $pos);
842  }
843  return false;
844  }
845 
853  public function getNamespaceFromPrefix($prefix)
854  {
855  if (isset($this->namespaces[$prefix])) {
856  return $this->namespaces[$prefix];
857  }
858  //$this->setError("No namespace registered for prefix '$prefix'");
859  return false;
860  }
861 
870  public function getPrefixFromNamespace($ns)
871  {
872  foreach ($this->namespaces as $p => $n) {
873  if ($ns == $n || $ns == $p) {
874  $this->usedNamespaces[$p] = $n;
875  return $p;
876  }
877  }
878  return false;
879  }
880 
887  public function getmicrotime()
888  {
889  if (function_exists('gettimeofday')) {
890  $tod = gettimeofday();
891  $sec = $tod['sec'];
892  $usec = $tod['usec'];
893  } else {
894  $sec = time();
895  $usec = 0;
896  }
897  return strftime('%Y-%m-%d %H:%M:%S', $sec) . '.' . sprintf('%06d', $usec);
898  }
899 
907  public function varDump($data)
908  {
909  ob_start();
910  var_dump($data);
911  $ret_val = ob_get_contents();
912  ob_end_clean();
913  return $ret_val;
914  }
915 
922  public function __toString()
923  {
924  return $this->varDump($this);
925  }
926 }
927 
928 // XML Schema Datatype Helper Functions
929 
930 //xsd:dateTime helpers
931 
939 function timestamp_to_iso8601($timestamp, $utc=true)
940 {
941  $datestr = date('Y-m-d\TH:i:sO', $timestamp);
942  if ($utc) {
943  $pattern = '/' .
944  '([0-9]{4})-' . // centuries & years CCYY-
945  '([0-9]{2})-' . // months MM-
946  '([0-9]{2})' . // days DD
947  'T' . // separator T
948  '([0-9]{2}):' . // hours hh:
949  '([0-9]{2}):' . // minutes mm:
950  '([0-9]{2})(\.[0-9]*)?' . // seconds ss.ss...
951  '(Z|[+\-][0-9]{2}:?[0-9]{2})?' . // Z to indicate UTC, -/+HH:MM:SS.SS... for local tz's
952  '/';
953 
954  if (preg_match($pattern, $datestr, $regs)) {
955  return sprintf('%04d-%02d-%02dT%02d:%02d:%02dZ', $regs[1], $regs[2], $regs[3], $regs[4], $regs[5], $regs[6]);
956  }
957  return false;
958  } else {
959  return $datestr;
960  }
961 }
962 
969 function iso8601_to_timestamp($datestr)
970 {
971  $pattern = '/' .
972  '([0-9]{4})-' . // centuries & years CCYY-
973  '([0-9]{2})-' . // months MM-
974  '([0-9]{2})' . // days DD
975  'T' . // separator T
976  '([0-9]{2}):' . // hours hh:
977  '([0-9]{2}):' . // minutes mm:
978  '([0-9]{2})(\.[0-9]+)?' . // seconds ss.ss...
979  '(Z|[+\-][0-9]{2}:?[0-9]{2})?' . // Z to indicate UTC, -/+HH:MM:SS.SS... for local tz's
980  '/';
981 
982  if (preg_match($pattern, $datestr, $regs)) {
983  // not utc
984  if ($regs[8] != 'Z') {
985  $op = substr($regs[8], 0, 1);
986  $h = substr($regs[8], 1, 2);
987  $m = substr($regs[8], strlen($regs[8])-2, 2);
988  if ($op == '-') {
989  $regs[4] = $regs[4] + $h;
990  $regs[5] = $regs[5] + $m;
991  } elseif ($op == '+') {
992  $regs[4] = $regs[4] - $h;
993  $regs[5] = $regs[5] - $m;
994  }
995  }
996  return gmmktime($regs[4], $regs[5], $regs[6], $regs[2], $regs[3], $regs[1]);
997  // return strtotime("$regs[1]-$regs[2]-$regs[3] $regs[4]:$regs[5]:$regs[6]Z");
998  } else {
999  return false;
1000  }
1001 }
1002 
1010 function usleepWindows($usec)
1011 {
1012  $start = gettimeofday();
1013 
1014  do {
1015  $stop = gettimeofday();
1016  $timePassed = 1000000 * ($stop['sec'] - $start['sec'])
1017  + $stop['usec'] - $start['usec'];
1018  } while ($timePassed < $usec);
1019 }
1020 
1021 ?><?php
1022 
1023 
1024 
1034 {
1040  public $faultcode;
1046  public $faultactor;
1059 
1068  public function __construct($faultcode, $faultactor='', $faultstring='', $faultdetail='')
1069  {
1071  $this->faultcode = $faultcode;
1072  $this->faultactor = $faultactor;
1073  $this->faultstring = $faultstring;
1074  $this->faultdetail = $faultdetail;
1075  }
1076 
1083  public function serialize()
1084  {
1085  $ns_string = '';
1086  foreach ($this->namespaces as $k => $v) {
1087  $ns_string .= "\n xmlns:$k=\"$v\"";
1088  }
1089  $return_msg =
1090  '<?xml version="1.0" encoding="' . $this->soap_defencoding . '"?>' .
1091  '<SOAP-ENV:Envelope SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"' . $ns_string . ">\n" .
1092  '<SOAP-ENV:Body>' .
1093  '<SOAP-ENV:Fault>' .
1094  $this->serialize_val($this->faultcode, 'faultcode') .
1095  $this->serialize_val($this->faultstring, 'faultstring') .
1096  $this->serialize_val($this->faultactor, 'faultactor') .
1097  $this->serialize_val($this->faultdetail, 'detail') .
1098  '</SOAP-ENV:Fault>' .
1099  '</SOAP-ENV:Body>' .
1100  '</SOAP-ENV:Envelope>';
1101  return $return_msg;
1102  }
1103 }
1104 
1109 {
1110 }
1111 
1112 ?><?php
1113 
1114 
1115 
1126 {
1127  // files
1128  public $schema = '';
1129  public $xml = '';
1130  // namespaces
1132  // schema info
1133  public $schemaInfo = array();
1134  public $schemaTargetNamespace = '';
1135  // types, elements, attributes defined by the schema
1136  public $attributes = array();
1137  public $complexTypes = array();
1138  public $complexTypeStack = array();
1139  public $currentComplexType = null;
1140  public $elements = array();
1141  public $elementStack = array();
1142  public $currentElement = null;
1143  public $simpleTypes = array();
1144  public $simpleTypeStack = array();
1145  public $currentSimpleType = null;
1146  // imports
1147  public $imports = array();
1148  // parser vars
1149  public $parser;
1150  public $position = 0;
1151  public $depth = 0;
1152  public $depth_array = array();
1153  public $message = array();
1154  public $defaultNamespace = array();
1155 
1164  public function __construct($schema='', $xml='', $namespaces=array())
1165  {
1167  $this->debug('nusoap_xmlschema class instantiated, inside constructor');
1168  // files
1169  $this->schema = $schema;
1170  $this->xml = $xml;
1171 
1172  // namespaces
1173  $this->enclosingNamespaces = $namespaces;
1174  $this->namespaces = array_merge($this->namespaces, $namespaces);
1175 
1176  // parse schema file
1177  if ($schema != '') {
1178  $this->debug('initial schema file: ' . $schema);
1179  $this->parseFile($schema, 'schema');
1180  }
1181 
1182  // parse xml file
1183  if ($xml != '') {
1184  $this->debug('initial xml file: ' . $xml);
1185  $this->parseFile($xml, 'xml');
1186  }
1187  }
1188 
1197  public function parseFile($xml, $type)
1198  {
1199  // parse xml file
1200  if ($xml != "") {
1201  $xmlStr = @join("", @file($xml));
1202  if ($xmlStr == "") {
1203  $msg = 'Error reading XML from ' . $xml;
1204  $this->setError($msg);
1205  $this->debug($msg);
1206  return false;
1207  } else {
1208  $this->debug("parsing $xml");
1209  $this->parseString($xmlStr, $type);
1210  $this->debug("done parsing $xml");
1211  return true;
1212  }
1213  }
1214  return false;
1215  }
1216 
1224  public function parseString($xml, $type)
1225  {
1226  // parse xml string
1227  if ($xml != "") {
1228  // Create an XML parser.
1229  $this->parser = xml_parser_create();
1230  // Set the options for parsing the XML data.
1231  xml_parser_set_option($this->parser, XML_OPTION_CASE_FOLDING, 0);
1232 
1233  // Set the object for the parser.
1234  xml_set_object($this->parser, $this);
1235 
1236  // Set the element handlers for the parser.
1237  if ($type == "schema") {
1238  xml_set_element_handler($this->parser, 'schemaStartElement', 'schemaEndElement');
1239  xml_set_character_data_handler($this->parser, 'schemaCharacterData');
1240  } elseif ($type == "xml") {
1241  xml_set_element_handler($this->parser, 'xmlStartElement', 'xmlEndElement');
1242  xml_set_character_data_handler($this->parser, 'xmlCharacterData');
1243  }
1244 
1245  // Parse the XML file.
1246  if (!xml_parse($this->parser, $xml, true)) {
1247  // Display an error message.
1248  $errstr = sprintf(
1249  'XML error parsing XML schema on line %d: %s',
1250  xml_get_current_line_number($this->parser),
1251  xml_error_string(xml_get_error_code($this->parser))
1252  );
1253  $this->debug($errstr);
1254  $this->debug("XML payload:\n" . $xml);
1255  $this->setError($errstr);
1256  }
1257 
1258  xml_parser_free($this->parser);
1259  } else {
1260  $this->debug('no xml passed to parseString()!!');
1261  $this->setError('no xml passed to parseString()!!');
1262  }
1263  }
1264 
1272  public function CreateTypeName($ename)
1273  {
1274  $scope = '';
1275  for ($i = 0; $i < count($this->complexTypeStack); $i++) {
1276  $scope .= $this->complexTypeStack[$i] . '_';
1277  }
1278  return $scope . $ename . '_ContainedType';
1279  }
1280 
1289  public function schemaStartElement($parser, $name, $attrs)
1290  {
1291 
1292  // position in the total number of elements, starting from 0
1293  $pos = $this->position++;
1294  $depth = $this->depth++;
1295  // set self as current value for this depth
1296  $this->depth_array[$depth] = $pos;
1297  $this->message[$pos] = array('cdata' => '');
1298  if ($depth > 0) {
1299  $this->defaultNamespace[$pos] = $this->defaultNamespace[$this->depth_array[$depth - 1]];
1300  } else {
1301  $this->defaultNamespace[$pos] = false;
1302  }
1303 
1304  // get element prefix
1305  if ($prefix = $this->getPrefix($name)) {
1306  // get unqualified name
1307  $name = $this->getLocalPart($name);
1308  } else {
1309  $prefix = '';
1310  }
1311 
1312  // loop thru attributes, expanding, and registering namespace declarations
1313  if (count($attrs) > 0) {
1314  foreach ($attrs as $k => $v) {
1315  // if ns declarations, add to class level array of valid namespaces
1316  if (preg_match('/^xmlns/', $k)) {
1317  //$this->xdebug("$k: $v");
1318  //$this->xdebug('ns_prefix: '.$this->getPrefix($k));
1319  if ($ns_prefix = substr(strrchr($k, ':'), 1)) {
1320  //$this->xdebug("Add namespace[$ns_prefix] = $v");
1321  $this->namespaces[$ns_prefix] = $v;
1322  } else {
1323  $this->defaultNamespace[$pos] = $v;
1324  if (! $this->getPrefixFromNamespace($v)) {
1325  $this->namespaces['ns' . (count($this->namespaces)+1)] = $v;
1326  }
1327  }
1328  if ($v == 'http://www.w3.org/2001/XMLSchema' || $v == 'http://www.w3.org/1999/XMLSchema' || $v == 'http://www.w3.org/2000/10/XMLSchema') {
1329  $this->XMLSchemaVersion = $v;
1330  $this->namespaces['xsi'] = $v . '-instance';
1331  }
1332  }
1333  }
1334  foreach ($attrs as $k => $v) {
1335  // expand each attribute
1336  $k = strpos($k, ':') ? $this->expandQname($k) : $k;
1337  $v = strpos($v, ':') ? $this->expandQname($v) : $v;
1338  $eAttrs[$k] = $v;
1339  }
1340  $attrs = $eAttrs;
1341  } else {
1342  $attrs = array();
1343  }
1344  // find status, register data
1345  switch ($name) {
1346  case 'all': // (optional) compositor content for a complexType
1347  case 'choice':
1348  case 'group':
1349  case 'sequence':
1350  //$this->xdebug("compositor $name for currentComplexType: $this->currentComplexType and currentElement: $this->currentElement");
1351  $this->complexTypes[$this->currentComplexType]['compositor'] = $name;
1352  //if($name == 'all' || $name == 'sequence'){
1353  // $this->complexTypes[$this->currentComplexType]['phpType'] = 'struct';
1354  //}
1355  break;
1356  case 'attribute': // complexType attribute
1357  //$this->xdebug("parsing attribute $attrs[name] $attrs[ref] of value: ".$attrs['http://schemas.xmlsoap.org/wsdl/:arrayType']);
1358  $this->xdebug("parsing attribute:");
1359  $this->appendDebug($this->varDump($attrs));
1360  if (!isset($attrs['form'])) {
1361  $attrs['form'] = $this->schemaInfo['attributeFormDefault'];
1362  }
1363  if (isset($attrs['http://schemas.xmlsoap.org/wsdl/:arrayType'])) {
1364  $v = $attrs['http://schemas.xmlsoap.org/wsdl/:arrayType'];
1365  if (!strpos($v, ':')) {
1366  // no namespace in arrayType attribute value...
1367  if ($this->defaultNamespace[$pos]) {
1368  // ...so use the default
1369  $attrs['http://schemas.xmlsoap.org/wsdl/:arrayType'] = $this->defaultNamespace[$pos] . ':' . $attrs['http://schemas.xmlsoap.org/wsdl/:arrayType'];
1370  }
1371  }
1372  }
1373  if (isset($attrs['name'])) {
1374  $this->attributes[$attrs['name']] = $attrs;
1375  $aname = $attrs['name'];
1376  } elseif (isset($attrs['ref']) && $attrs['ref'] == 'http://schemas.xmlsoap.org/soap/encoding/:arrayType') {
1377  if (isset($attrs['http://schemas.xmlsoap.org/wsdl/:arrayType'])) {
1378  $aname = $attrs['http://schemas.xmlsoap.org/wsdl/:arrayType'];
1379  } else {
1380  $aname = '';
1381  }
1382  } elseif (isset($attrs['ref'])) {
1383  $aname = $attrs['ref'];
1384  $this->attributes[$attrs['ref']] = $attrs;
1385  }
1386 
1387  if ($this->currentComplexType) { // This should *always* be
1388  $this->complexTypes[$this->currentComplexType]['attrs'][$aname] = $attrs;
1389  }
1390  // arrayType attribute
1391  if (isset($attrs['http://schemas.xmlsoap.org/wsdl/:arrayType']) || $this->getLocalPart($aname) == 'arrayType') {
1392  $this->complexTypes[$this->currentComplexType]['phpType'] = 'array';
1393  $prefix = $this->getPrefix($aname);
1394  if (isset($attrs['http://schemas.xmlsoap.org/wsdl/:arrayType'])) {
1395  $v = $attrs['http://schemas.xmlsoap.org/wsdl/:arrayType'];
1396  } else {
1397  $v = '';
1398  }
1399  if (strpos($v, '[,]')) {
1400  $this->complexTypes[$this->currentComplexType]['multidimensional'] = true;
1401  }
1402  $v = substr($v, 0, strpos($v, '[')); // clip the []
1403  if (!strpos($v, ':') && isset($this->typemap[$this->XMLSchemaVersion][$v])) {
1404  $v = $this->XMLSchemaVersion . ':' . $v;
1405  }
1406  $this->complexTypes[$this->currentComplexType]['arrayType'] = $v;
1407  }
1408  break;
1409  case 'complexContent': // (optional) content for a complexType
1410  break;
1411  case 'complexType':
1412  array_push($this->complexTypeStack, $this->currentComplexType);
1413  if (isset($attrs['name'])) {
1414  // TODO: what is the scope of named complexTypes that appear
1415  // nested within other c complexTypes?
1416  $this->xdebug('processing named complexType ' . $attrs['name']);
1417  //$this->currentElement = false;
1418  $this->currentComplexType = $attrs['name'];
1419  $this->complexTypes[$this->currentComplexType] = $attrs;
1420  $this->complexTypes[$this->currentComplexType]['typeClass'] = 'complexType';
1421  // This is for constructs like
1422  // <complexType name="ListOfString" base="soap:Array">
1423  // <sequence>
1424  // <element name="string" type="xsd:string"
1425  // minOccurs="0" maxOccurs="unbounded" />
1426  // </sequence>
1427  // </complexType>
1428  if (isset($attrs['base']) && preg_match('/:Array$/', $attrs['base'])) {
1429  $this->xdebug('complexType is unusual array');
1430  $this->complexTypes[$this->currentComplexType]['phpType'] = 'array';
1431  } else {
1432  $this->complexTypes[$this->currentComplexType]['phpType'] = 'struct';
1433  }
1434  } else {
1435  $name = $this->CreateTypeName($this->currentElement);
1436  $this->xdebug('processing unnamed complexType for element ' . $this->currentElement . ' named ' . $name);
1437  $this->currentComplexType = $name;
1438  //$this->currentElement = false;
1439  $this->complexTypes[$this->currentComplexType] = $attrs;
1440  $this->complexTypes[$this->currentComplexType]['typeClass'] = 'complexType';
1441  // This is for constructs like
1442  // <complexType name="ListOfString" base="soap:Array">
1443  // <sequence>
1444  // <element name="string" type="xsd:string"
1445  // minOccurs="0" maxOccurs="unbounded" />
1446  // </sequence>
1447  // </complexType>
1448  if (isset($attrs['base']) && preg_match('/:Array$/', $attrs['base'])) {
1449  $this->xdebug('complexType is unusual array');
1450  $this->complexTypes[$this->currentComplexType]['phpType'] = 'array';
1451  } else {
1452  $this->complexTypes[$this->currentComplexType]['phpType'] = 'struct';
1453  }
1454  }
1455  break;
1456  case 'element':
1457  array_push($this->elementStack, $this->currentElement);
1458  if (!isset($attrs['form'])) {
1459  $attrs['form'] = $this->schemaInfo['elementFormDefault'];
1460  }
1461  if (isset($attrs['type'])) {
1462  $this->xdebug("processing typed element " . $attrs['name'] . " of type " . $attrs['type']);
1463  if (! $this->getPrefix($attrs['type'])) {
1464  if ($this->defaultNamespace[$pos]) {
1465  $attrs['type'] = $this->defaultNamespace[$pos] . ':' . $attrs['type'];
1466  $this->xdebug('used default namespace to make type ' . $attrs['type']);
1467  }
1468  }
1469  // This is for constructs like
1470  // <complexType name="ListOfString" base="soap:Array">
1471  // <sequence>
1472  // <element name="string" type="xsd:string"
1473  // minOccurs="0" maxOccurs="unbounded" />
1474  // </sequence>
1475  // </complexType>
1476  if ($this->currentComplexType && $this->complexTypes[$this->currentComplexType]['phpType'] == 'array') {
1477  $this->xdebug('arrayType for unusual array is ' . $attrs['type']);
1478  $this->complexTypes[$this->currentComplexType]['arrayType'] = $attrs['type'];
1479  }
1480  $this->currentElement = $attrs['name'];
1481  $ename = $attrs['name'];
1482  } elseif (isset($attrs['ref'])) {
1483  $this->xdebug("processing element as ref to " . $attrs['ref']);
1484  $this->currentElement = "ref to " . $attrs['ref'];
1485  $ename = $this->getLocalPart($attrs['ref']);
1486  } else {
1487  $type = $this->CreateTypeName($this->currentComplexType . '_' . $attrs['name']);
1488  $this->xdebug("processing untyped element " . $attrs['name'] . ' type ' . $type);
1489  $this->currentElement = $attrs['name'];
1490  $attrs['type'] = $this->schemaTargetNamespace . ':' . $type;
1491  $ename = $attrs['name'];
1492  }
1493  if (isset($ename) && $this->currentComplexType) {
1494  $this->xdebug("add element $ename to complexType $this->currentComplexType");
1495  $this->complexTypes[$this->currentComplexType]['elements'][$ename] = $attrs;
1496  } elseif (!isset($attrs['ref'])) {
1497  $this->xdebug("add element $ename to elements array");
1498  $this->elements[ $attrs['name'] ] = $attrs;
1499  $this->elements[ $attrs['name'] ]['typeClass'] = 'element';
1500  }
1501  break;
1502  case 'enumeration': // restriction value list member
1503  $this->xdebug('enumeration ' . $attrs['value']);
1504  if ($this->currentSimpleType) {
1505  $this->simpleTypes[$this->currentSimpleType]['enumeration'][] = $attrs['value'];
1506  } elseif ($this->currentComplexType) {
1507  $this->complexTypes[$this->currentComplexType]['enumeration'][] = $attrs['value'];
1508  }
1509  break;
1510  case 'extension': // simpleContent or complexContent type extension
1511  $this->xdebug('extension ' . $attrs['base']);
1512  if ($this->currentComplexType) {
1513  $this->complexTypes[$this->currentComplexType]['extensionBase'] = $attrs['base'];
1514  }
1515  break;
1516  case 'import':
1517  if (isset($attrs['schemaLocation'])) {
1518  //$this->xdebug('import namespace ' . $attrs['namespace'] . ' from ' . $attrs['schemaLocation']);
1519  $this->imports[$attrs['namespace']][] = array('location' => $attrs['schemaLocation'], 'loaded' => false);
1520  } else {
1521  //$this->xdebug('import namespace ' . $attrs['namespace']);
1522  $this->imports[$attrs['namespace']][] = array('location' => '', 'loaded' => true);
1523  if (! $this->getPrefixFromNamespace($attrs['namespace'])) {
1524  $this->namespaces['ns' . (count($this->namespaces)+1)] = $attrs['namespace'];
1525  }
1526  }
1527  break;
1528  case 'list': // simpleType value list
1529  break;
1530  case 'restriction': // simpleType, simpleContent or complexContent value restriction
1531  $this->xdebug('restriction ' . $attrs['base']);
1532  if ($this->currentSimpleType) {
1533  $this->simpleTypes[$this->currentSimpleType]['type'] = $attrs['base'];
1534  } elseif ($this->currentComplexType) {
1535  $this->complexTypes[$this->currentComplexType]['restrictionBase'] = $attrs['base'];
1536  if (strstr($attrs['base'], ':') == ':Array') {
1537  $this->complexTypes[$this->currentComplexType]['phpType'] = 'array';
1538  }
1539  }
1540  break;
1541  case 'schema':
1542  $this->schemaInfo = $attrs;
1543  $this->schemaInfo['schemaVersion'] = $this->getNamespaceFromPrefix($prefix);
1544  if (isset($attrs['targetNamespace'])) {
1545  $this->schemaTargetNamespace = $attrs['targetNamespace'];
1546  }
1547  if (!isset($attrs['elementFormDefault'])) {
1548  $this->schemaInfo['elementFormDefault'] = 'unqualified';
1549  }
1550  if (!isset($attrs['attributeFormDefault'])) {
1551  $this->schemaInfo['attributeFormDefault'] = 'unqualified';
1552  }
1553  break;
1554  case 'simpleContent': // (optional) content for a complexType
1555  break;
1556  case 'simpleType':
1557  array_push($this->simpleTypeStack, $this->currentSimpleType);
1558  if (isset($attrs['name'])) {
1559  $this->xdebug("processing simpleType for name " . $attrs['name']);
1560  $this->currentSimpleType = $attrs['name'];
1561  $this->simpleTypes[ $attrs['name'] ] = $attrs;
1562  $this->simpleTypes[ $attrs['name'] ]['typeClass'] = 'simpleType';
1563  $this->simpleTypes[ $attrs['name'] ]['phpType'] = 'scalar';
1564  } else {
1565  $name = $this->CreateTypeName($this->currentComplexType . '_' . $this->currentElement);
1566  $this->xdebug('processing unnamed simpleType for element ' . $this->currentElement . ' named ' . $name);
1567  $this->currentSimpleType = $name;
1568  //$this->currentElement = false;
1569  $this->simpleTypes[$this->currentSimpleType] = $attrs;
1570  $this->simpleTypes[$this->currentSimpleType]['phpType'] = 'scalar';
1571  }
1572  break;
1573  case 'union': // simpleType type list
1574  break;
1575  default:
1576  //$this->xdebug("do not have anything to do for element $name");
1577  }
1578  }
1579 
1587  public function schemaEndElement($parser, $name)
1588  {
1589  // bring depth down a notch
1590  $this->depth--;
1591  // position of current element is equal to the last value left in depth_array for my depth
1592  if (isset($this->depth_array[$this->depth])) {
1593  $pos = $this->depth_array[$this->depth];
1594  }
1595  // get element prefix
1596  if ($prefix = $this->getPrefix($name)) {
1597  // get unqualified name
1598  $name = $this->getLocalPart($name);
1599  } else {
1600  $prefix = '';
1601  }
1602  // move on...
1603  if ($name == 'complexType') {
1604  $this->xdebug('done processing complexType ' . ($this->currentComplexType ? $this->currentComplexType : '(unknown)'));
1605  $this->currentComplexType = array_pop($this->complexTypeStack);
1606  //$this->currentElement = false;
1607  }
1608  if ($name == 'element') {
1609  $this->xdebug('done processing element ' . ($this->currentElement ? $this->currentElement : '(unknown)'));
1610  $this->currentElement = array_pop($this->elementStack);
1611  }
1612  if ($name == 'simpleType') {
1613  $this->xdebug('done processing simpleType ' . ($this->currentSimpleType ? $this->currentSimpleType : '(unknown)'));
1614  $this->currentSimpleType = array_pop($this->simpleTypeStack);
1615  }
1616  }
1617 
1625  public function schemaCharacterData($parser, $data)
1626  {
1627  $pos = $this->depth_array[$this->depth - 1];
1628  $this->message[$pos]['cdata'] .= $data;
1629  }
1630 
1636  public function serializeSchema()
1637  {
1638  $schemaPrefix = $this->getPrefixFromNamespace($this->XMLSchemaVersion);
1639  $xml = '';
1640  // imports
1641  if (sizeof($this->imports) > 0) {
1642  foreach ($this->imports as $ns => $list) {
1643  foreach ($list as $ii) {
1644  if ($ii['location'] != '') {
1645  $xml .= " <$schemaPrefix:import location=\"" . $ii['location'] . '" namespace="' . $ns . "\" />\n";
1646  } else {
1647  $xml .= " <$schemaPrefix:import namespace=\"" . $ns . "\" />\n";
1648  }
1649  }
1650  }
1651  }
1652  // complex types
1653  foreach ($this->complexTypes as $typeName => $attrs) {
1654  $contentStr = '';
1655  // serialize child elements
1656  if (isset($attrs['elements']) && (count($attrs['elements']) > 0)) {
1657  foreach ($attrs['elements'] as $element => $eParts) {
1658  if (isset($eParts['ref'])) {
1659  $contentStr .= " <$schemaPrefix:element ref=\"$element\"/>\n";
1660  } else {
1661  $contentStr .= " <$schemaPrefix:element name=\"$element\" type=\"" . $this->contractQName($eParts['type']) . "\"";
1662  foreach ($eParts as $aName => $aValue) {
1663  // handle, e.g., abstract, default, form, minOccurs, maxOccurs, nillable
1664  if ($aName != 'name' && $aName != 'type') {
1665  $contentStr .= " $aName=\"$aValue\"";
1666  }
1667  }
1668  $contentStr .= "/>\n";
1669  }
1670  }
1671  // compositor wraps elements
1672  if (isset($attrs['compositor']) && ($attrs['compositor'] != '')) {
1673  $contentStr = " <$schemaPrefix:$attrs[compositor]>\n" . $contentStr . " </$schemaPrefix:$attrs[compositor]>\n";
1674  }
1675  }
1676  // attributes
1677  if (isset($attrs['attrs']) && (count($attrs['attrs']) >= 1)) {
1678  foreach ($attrs['attrs'] as $attr => $aParts) {
1679  $contentStr .= " <$schemaPrefix:attribute";
1680  foreach ($aParts as $a => $v) {
1681  if ($a == 'ref' || $a == 'type') {
1682  $contentStr .= " $a=\"" . $this->contractQName($v) . '"';
1683  } elseif ($a == 'http://schemas.xmlsoap.org/wsdl/:arrayType') {
1684  $this->usedNamespaces['wsdl'] = $this->namespaces['wsdl'];
1685  $contentStr .= ' wsdl:arrayType="' . $this->contractQName($v) . '"';
1686  } else {
1687  $contentStr .= " $a=\"$v\"";
1688  }
1689  }
1690  $contentStr .= "/>\n";
1691  }
1692  }
1693  // if restriction
1694  if (isset($attrs['restrictionBase']) && $attrs['restrictionBase'] != '') {
1695  $contentStr = " <$schemaPrefix:restriction base=\"" . $this->contractQName($attrs['restrictionBase']) . "\">\n" . $contentStr . " </$schemaPrefix:restriction>\n";
1696  // complex or simple content
1697  if ((isset($attrs['elements']) && count($attrs['elements']) > 0) || (isset($attrs['attrs']) && count($attrs['attrs']) > 0)) {
1698  $contentStr = " <$schemaPrefix:complexContent>\n" . $contentStr . " </$schemaPrefix:complexContent>\n";
1699  }
1700  }
1701  // finalize complex type
1702  if ($contentStr != '') {
1703  $contentStr = " <$schemaPrefix:complexType name=\"$typeName\">\n" . $contentStr . " </$schemaPrefix:complexType>\n";
1704  } else {
1705  $contentStr = " <$schemaPrefix:complexType name=\"$typeName\"/>\n";
1706  }
1707  $xml .= $contentStr;
1708  }
1709  // simple types
1710  if (isset($this->simpleTypes) && count($this->simpleTypes) > 0) {
1711  foreach ($this->simpleTypes as $typeName => $eParts) {
1712  $xml .= " <$schemaPrefix:simpleType name=\"$typeName\">\n <$schemaPrefix:restriction base=\"" . $this->contractQName($eParts['type']) . "\">\n";
1713  if (isset($eParts['enumeration'])) {
1714  foreach ($eParts['enumeration'] as $e) {
1715  $xml .= " <$schemaPrefix:enumeration value=\"$e\"/>\n";
1716  }
1717  }
1718  $xml .= " </$schemaPrefix:restriction>\n </$schemaPrefix:simpleType>";
1719  }
1720  }
1721  // elements
1722  if (isset($this->elements) && count($this->elements) > 0) {
1723  foreach ($this->elements as $element => $eParts) {
1724  $xml .= " <$schemaPrefix:element name=\"$element\" type=\"" . $this->contractQName($eParts['type']) . "\"/>\n";
1725  }
1726  }
1727  // attributes
1728  if (isset($this->attributes) && count($this->attributes) > 0) {
1729  foreach ($this->attributes as $attr => $aParts) {
1730  $xml .= " <$schemaPrefix:attribute name=\"$attr\" type=\"" . $this->contractQName($aParts['type']) . "\"\n/>";
1731  }
1732  }
1733  // finish 'er up
1734  $attr = '';
1735  foreach ($this->schemaInfo as $k => $v) {
1736  if ($k == 'elementFormDefault' || $k == 'attributeFormDefault') {
1737  $attr .= " $k=\"$v\"";
1738  }
1739  }
1740  $el = "<$schemaPrefix:schema$attr targetNamespace=\"$this->schemaTargetNamespace\"\n";
1741  foreach (array_diff($this->usedNamespaces, $this->enclosingNamespaces) as $nsp => $ns) {
1742  $el .= " xmlns:$nsp=\"$ns\"";
1743  }
1744  $xml = $el . ">\n" . $xml . "</$schemaPrefix:schema>\n";
1745  return $xml;
1746  }
1747 
1754  public function xdebug($string)
1755  {
1756  $this->debug('<' . $this->schemaTargetNamespace . '> ' . $string);
1757  }
1758 
1771  public function getPHPType($type, $ns)
1772  {
1773  if (isset($this->typemap[$ns][$type])) {
1774  //print "found type '$type' and ns $ns in typemap<br>";
1775  return $this->typemap[$ns][$type];
1776  } elseif (isset($this->complexTypes[$type])) {
1777  //print "getting type '$type' and ns $ns from complexTypes array<br>";
1778  return $this->complexTypes[$type]['phpType'];
1779  }
1780  return false;
1781  }
1782 
1805  public function getTypeDef($type)
1806  {
1807  //$this->debug("in getTypeDef for type $type");
1808  if (substr($type, -1) == '^') {
1809  $is_element = 1;
1810  $type = substr($type, 0, -1);
1811  } else {
1812  $is_element = 0;
1813  }
1814 
1815  if ((! $is_element) && isset($this->complexTypes[$type])) {
1816  $this->xdebug("in getTypeDef, found complexType $type");
1817  return $this->complexTypes[$type];
1818  } elseif ((! $is_element) && isset($this->simpleTypes[$type])) {
1819  $this->xdebug("in getTypeDef, found simpleType $type");
1820  if (!isset($this->simpleTypes[$type]['phpType'])) {
1821  // get info for type to tack onto the simple type
1822  // TODO: can this ever really apply (i.e. what is a simpleType really?)
1823  $uqType = substr($this->simpleTypes[$type]['type'], strrpos($this->simpleTypes[$type]['type'], ':') + 1);
1824  $ns = substr($this->simpleTypes[$type]['type'], 0, strrpos($this->simpleTypes[$type]['type'], ':'));
1825  $etype = $this->getTypeDef($uqType);
1826  if ($etype) {
1827  $this->xdebug("in getTypeDef, found type for simpleType $type:");
1828  $this->xdebug($this->varDump($etype));
1829  if (isset($etype['phpType'])) {
1830  $this->simpleTypes[$type]['phpType'] = $etype['phpType'];
1831  }
1832  if (isset($etype['elements'])) {
1833  $this->simpleTypes[$type]['elements'] = $etype['elements'];
1834  }
1835  }
1836  }
1837  return $this->simpleTypes[$type];
1838  } elseif (isset($this->elements[$type])) {
1839  $this->xdebug("in getTypeDef, found element $type");
1840  if (!isset($this->elements[$type]['phpType'])) {
1841  // get info for type to tack onto the element
1842  $uqType = substr($this->elements[$type]['type'], strrpos($this->elements[$type]['type'], ':') + 1);
1843  $ns = substr($this->elements[$type]['type'], 0, strrpos($this->elements[$type]['type'], ':'));
1844  $etype = $this->getTypeDef($uqType);
1845  if ($etype) {
1846  $this->xdebug("in getTypeDef, found type for element $type:");
1847  $this->xdebug($this->varDump($etype));
1848  if (isset($etype['phpType'])) {
1849  $this->elements[$type]['phpType'] = $etype['phpType'];
1850  }
1851  if (isset($etype['elements'])) {
1852  $this->elements[$type]['elements'] = $etype['elements'];
1853  }
1854  } elseif ($ns == 'http://www.w3.org/2001/XMLSchema') {
1855  $this->xdebug("in getTypeDef, element $type is an XSD type");
1856  $this->elements[$type]['phpType'] = 'scalar';
1857  }
1858  }
1859  return $this->elements[$type];
1860  } elseif (isset($this->attributes[$type])) {
1861  $this->xdebug("in getTypeDef, found attribute $type");
1862  return $this->attributes[$type];
1863  } elseif (preg_match('/_ContainedType$/', $type)) {
1864  $this->xdebug("in getTypeDef, have an untyped element $type");
1865  $typeDef['typeClass'] = 'simpleType';
1866  $typeDef['phpType'] = 'scalar';
1867  $typeDef['type'] = 'http://www.w3.org/2001/XMLSchema:string';
1868  return $typeDef;
1869  }
1870  $this->xdebug("in getTypeDef, did not find $type");
1871  return false;
1872  }
1873 
1882  public function serializeTypeDef($type)
1883  {
1884  //print "in sTD() for type $type<br>";
1885  if ($typeDef = $this->getTypeDef($type)) {
1886  $str .= '<' . $type;
1887  if (is_array($typeDef['attrs'])) {
1888  foreach ($typeDef['attrs'] as $attName => $data) {
1889  $str .= " $attName=\"{type = " . $data['type'] . "}\"";
1890  }
1891  }
1892  $str .= " xmlns=\"" . $this->schema['targetNamespace'] . "\"";
1893  if (count($typeDef['elements']) > 0) {
1894  $str .= ">";
1895  foreach ($typeDef['elements'] as $element => $eData) {
1896  $str .= $this->serializeTypeDef($element);
1897  }
1898  $str .= "</$type>";
1899  } elseif ($typeDef['typeClass'] == 'element') {
1900  $str .= "></$type>";
1901  } else {
1902  $str .= "/>";
1903  }
1904  return $str;
1905  }
1906  return false;
1907  }
1908 
1919  public function typeToForm($name, $type)
1920  {
1921  // get typedef
1922  if ($typeDef = $this->getTypeDef($type)) {
1923  // if struct
1924  if ($typeDef['phpType'] == 'struct') {
1925  $buffer .= '<table>';
1926  foreach ($typeDef['elements'] as $child => $childDef) {
1927  $buffer .= "
1928  <tr><td align='right'>$childDef[name] (type: " . $this->getLocalPart($childDef['type']) . "):</td>
1929  <td><input type='text' name='parameters[" . $name . "][$childDef[name]]'></td></tr>";
1930  }
1931  $buffer .= '</table>';
1932  // if array
1933  } elseif ($typeDef['phpType'] == 'array') {
1934  $buffer .= '<table>';
1935  for ($i=0;$i < 3; $i++) {
1936  $buffer .= "
1937  <tr><td align='right'>array item (type: $typeDef[arrayType]):</td>
1938  <td><input type='text' name='parameters[" . $name . "][]'></td></tr>";
1939  }
1940  $buffer .= '</table>';
1941  // if scalar
1942  } else {
1943  $buffer .= "<input type='text' name='parameters[$name]'>";
1944  }
1945  } else {
1946  $buffer .= "<input type='text' name='parameters[$name]'>";
1947  }
1948  return $buffer;
1949  }
1950 
1992  public function addComplexType($name, $typeClass='complexType', $phpType='array', $compositor='', $restrictionBase='', $elements=array(), $attrs=array(), $arrayType='')
1993  {
1994  $this->complexTypes[$name] = array(
1995  'name' => $name,
1996  'typeClass' => $typeClass,
1997  'phpType' => $phpType,
1998  'compositor'=> $compositor,
1999  'restrictionBase' => $restrictionBase,
2000  'elements' => $elements,
2001  'attrs' => $attrs,
2002  'arrayType' => $arrayType
2003  );
2004 
2005  $this->xdebug("addComplexType $name:");
2006  $this->appendDebug($this->varDump($this->complexTypes[$name]));
2007  }
2008 
2021  public function addSimpleType($name, $restrictionBase='', $typeClass='simpleType', $phpType='scalar', $enumeration=array())
2022  {
2023  $this->simpleTypes[$name] = array(
2024  'name' => $name,
2025  'typeClass' => $typeClass,
2026  'phpType' => $phpType,
2027  'type' => $restrictionBase,
2028  'enumeration' => $enumeration
2029  );
2030 
2031  $this->xdebug("addSimpleType $name:");
2032  $this->appendDebug($this->varDump($this->simpleTypes[$name]));
2033  }
2034 
2042  public function addElement($attrs)
2043  {
2044  if (! $this->getPrefix($attrs['type'])) {
2045  $attrs['type'] = $this->schemaTargetNamespace . ':' . $attrs['type'];
2046  }
2047  $this->elements[ $attrs['name'] ] = $attrs;
2048  $this->elements[ $attrs['name'] ]['typeClass'] = 'element';
2049 
2050  $this->xdebug("addElement " . $attrs['name']);
2051  $this->appendDebug($this->varDump($this->elements[ $attrs['name'] ]));
2052  }
2053 }
2054 
2059 {
2060 }
2061 
2062 ?><?php
2063 
2064 
2065 
2077 class soapval extends nusoap_base
2078 {
2085  public $name;
2092  public $type;
2099  public $value;
2106  public $element_ns;
2113  public $type_ns;
2120  public $attributes;
2121 
2133  public function __construct($name='soapval', $type=false, $value=-1, $element_ns=false, $type_ns=false, $attributes=false)
2134  {
2136  $this->name = $name;
2137  $this->type = $type;
2138  $this->value = $value;
2139  $this->element_ns = $element_ns;
2140  $this->type_ns = $type_ns;
2141  $this->attributes = $attributes;
2142  }
2143 
2151  public function serialize($use='encoded')
2152  {
2153  return $this->serialize_val($this->value, $this->name, $this->type, $this->element_ns, $this->type_ns, $this->attributes, $use, true);
2154  }
2155 
2162  public function decode()
2163  {
2164  return $this->value;
2165  }
2166 }
2167 
2168 
2169 
2170 ?><?php
2171 
2172 
2173 
2184 {
2185  public $fp;
2186  public $tryagain;
2187  public $url = '';
2188  public $uri = '';
2189  public $digest_uri = '';
2190  public $scheme = '';
2191  public $host = '';
2192  public $port = '';
2193  public $path = '';
2194  public $request_method = 'POST';
2195  public $protocol_version = '1.0';
2196  public $encoding = '';
2197  public $outgoing_headers = array();
2198  public $incoming_headers = array();
2199  public $incoming_cookies = array();
2200  public $outgoing_payload = '';
2201  public $incoming_payload = '';
2202  public $response_status_line; // HTTP response status line
2203  public $useSOAPAction = true;
2204  public $persistentConnection = false;
2205  public $ch = false; // cURL handle
2206  public $ch_options = array(); // cURL custom options
2207  public $use_curl = false; // force cURL use
2208  public $proxy = null; // proxy information (associative array)
2209  public $username = '';
2210  public $password = '';
2211  public $authtype = '';
2212  public $digestRequest = array();
2213  public $certRequest = array(); // keys must be cainfofile (optional), sslcertfile, sslkeyfile, passphrase, certpassword (optional), verifypeer (optional), verifyhost (optional)
2214  // cainfofile: certificate authority file, e.g. '$pathToPemFiles/rootca.pem'
2215  // sslcertfile: SSL certificate file, e.g. '$pathToPemFiles/mycert.pem'
2216  // sslkeyfile: SSL key file, e.g. '$pathToPemFiles/mykey.pem'
2217  // passphrase: SSL key password/passphrase
2218  // certpassword: SSL certificate password
2219  // verifypeer: default is 1
2220  // verifyhost: default is 1
2221 
2230  public function __construct($url, $curl_options = null, $use_curl = false)
2231  {
2233  $this->debug("ctor url=$url use_curl=$use_curl curl_options:");
2234  $this->appendDebug($this->varDump($curl_options));
2235  $this->setURL($url);
2236  if (is_array($curl_options)) {
2237  $this->ch_options = $curl_options;
2238  }
2239  $this->use_curl = $use_curl;
2240  preg_match('/\$Revisio' . 'n: ([^ ]+)/', $this->revision, $rev);
2241  // begin-patch php8
2242  $this->setHeader('User-Agent', $this->title . '/' . $this->version . ' (' . ($rev[1] ?? '1.1') . ')');
2243  }
2244 
2252  public function setCurlOption($option, $value)
2253  {
2254  $this->debug("setCurlOption option=$option, value=");
2255  $this->appendDebug($this->varDump($value));
2256  curl_setopt($this->ch, $option, $value);
2257  }
2258 
2266  public function setHeader($name, $value)
2267  {
2268  $this->outgoing_headers[$name] = $value;
2269  $this->debug("set header $name: $value");
2270  }
2271 
2278  public function unsetHeader($name)
2279  {
2280  if (isset($this->outgoing_headers[$name])) {
2281  $this->debug("unset header $name");
2282  unset($this->outgoing_headers[$name]);
2283  }
2284  }
2285 
2292  public function setURL($url)
2293  {
2294  $this->url = $url;
2295 
2296  $u = parse_url($url);
2297  foreach ($u as $k => $v) {
2298  $this->debug("parsed URL $k = $v");
2299  $this->$k = $v;
2300  }
2301 
2302  // add any GET params to path
2303  if (isset($u['query']) && $u['query'] != '') {
2304  $this->path .= '?' . $u['query'];
2305  }
2306 
2307  // set default port
2308  if (!isset($u['port'])) {
2309  if ($u['scheme'] == 'https') {
2310  $this->port = 443;
2311  } else {
2312  $this->port = 80;
2313  }
2314  }
2315 
2316  $this->uri = $this->path;
2317  $this->digest_uri = $this->uri;
2318 
2319  // build headers
2320  if (!isset($u['port'])) {
2321  $this->setHeader('Host', $this->host);
2322  } else {
2323  $this->setHeader('Host', $this->host . ':' . $this->port);
2324  }
2325 
2326  if (isset($u['user']) && $u['user'] != '') {
2327  $this->setCredentials(urldecode($u['user']), isset($u['pass']) ? urldecode($u['pass']) : '');
2328  }
2329  }
2330 
2337  public function io_method()
2338  {
2339  if ($this->use_curl || ($this->scheme == 'https') || ($this->scheme == 'http' && $this->authtype == 'ntlm') || ($this->scheme == 'http' && is_array($this->proxy) && $this->proxy['authtype'] == 'ntlm')) {
2340  return 'curl';
2341  }
2342  if (($this->scheme == 'http' || $this->scheme == 'ssl') && $this->authtype != 'ntlm' && (!is_array($this->proxy) || $this->proxy['authtype'] != 'ntlm')) {
2343  return 'socket';
2344  }
2345  return 'unknown';
2346  }
2347 
2356  public function connect($connection_timeout=0, $response_timeout=30)
2357  {
2358  // For PHP 4.3 with OpenSSL, change https scheme to ssl, then treat like
2359  // "regular" socket.
2360  // TODO: disabled for now because OpenSSL must be *compiled* in (not just
2361  // loaded), and until PHP5 stream_get_wrappers is not available.
2362  // if ($this->scheme == 'https') {
2363  // if (version_compare(phpversion(), '4.3.0') >= 0) {
2364  // if (extension_loaded('openssl')) {
2365  // $this->scheme = 'ssl';
2366  // $this->debug('Using SSL over OpenSSL');
2367  // }
2368  // }
2369  // }
2370  $this->debug("connect connection_timeout $connection_timeout, response_timeout $response_timeout, scheme $this->scheme, host $this->host, port $this->port");
2371  if ($this->io_method() == 'socket') {
2372  if (!is_array($this->proxy)) {
2373  $host = $this->host;
2374  $port = $this->port;
2375  } else {
2376  $host = $this->proxy['host'];
2377  $port = $this->proxy['port'];
2378  }
2379 
2380  // use persistent connection
2381  if ($this->persistentConnection && isset($this->fp) && is_resource($this->fp)) {
2382  if (!feof($this->fp)) {
2383  $this->debug('Re-use persistent connection');
2384  return true;
2385  }
2386  fclose($this->fp);
2387  $this->debug('Closed persistent connection at EOF');
2388  }
2389 
2390  // munge host if using OpenSSL
2391  if ($this->scheme == 'ssl') {
2392  $host = 'ssl://' . $host;
2393  }
2394  $this->debug('calling fsockopen with host ' . $host . ' connection_timeout ' . $connection_timeout);
2395 
2396  // open socket
2397  if ($connection_timeout > 0) {
2398  $this->fp = @fsockopen($host, $this->port, $this->errno, $this->error_str, $connection_timeout);
2399  } else {
2400  $this->fp = @fsockopen($host, $this->port, $this->errno, $this->error_str);
2401  }
2402 
2403  // test pointer
2404  if (!$this->fp) {
2405  $msg = 'Couldn\'t open socket connection to server ' . $this->url;
2406  if ($this->errno) {
2407  $msg .= ', Error (' . $this->errno . '): ' . $this->error_str;
2408  } else {
2409  $msg .= ' prior to connect(). This is often a problem looking up the host name.';
2410  }
2411  $this->debug($msg);
2412  $this->setError($msg);
2413  return false;
2414  }
2415 
2416  // set response timeout
2417  $this->debug('set response timeout to ' . $response_timeout);
2418  socket_set_timeout($this->fp, $response_timeout);
2419 
2420  $this->debug('socket connected');
2421  return true;
2422  } elseif ($this->io_method() == 'curl') {
2423  if (!extension_loaded('curl')) {
2424  // $this->setError('cURL Extension, or OpenSSL extension w/ PHP version >= 4.3 is required for HTTPS');
2425  $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.');
2426  return false;
2427  }
2428  // Avoid warnings when PHP does not have these options
2429  if (defined('CURLOPT_CONNECTIONTIMEOUT')) {
2430  $CURLOPT_CONNECTIONTIMEOUT = CURLOPT_CONNECTIONTIMEOUT;
2431  } else {
2432  $CURLOPT_CONNECTIONTIMEOUT = 78;
2433  }
2434  if (defined('CURLOPT_HTTPAUTH')) {
2435  $CURLOPT_HTTPAUTH = CURLOPT_HTTPAUTH;
2436  } else {
2437  $CURLOPT_HTTPAUTH = 107;
2438  }
2439  if (defined('CURLOPT_PROXYAUTH')) {
2440  $CURLOPT_PROXYAUTH = CURLOPT_PROXYAUTH;
2441  } else {
2442  $CURLOPT_PROXYAUTH = 111;
2443  }
2444  if (defined('CURLAUTH_BASIC')) {
2445  $CURLAUTH_BASIC = CURLAUTH_BASIC;
2446  } else {
2447  $CURLAUTH_BASIC = 1;
2448  }
2449  if (defined('CURLAUTH_DIGEST')) {
2450  $CURLAUTH_DIGEST = CURLAUTH_DIGEST;
2451  } else {
2452  $CURLAUTH_DIGEST = 2;
2453  }
2454  if (defined('CURLAUTH_NTLM')) {
2455  $CURLAUTH_NTLM = CURLAUTH_NTLM;
2456  } else {
2457  $CURLAUTH_NTLM = 8;
2458  }
2459 
2460  $this->debug('connect using cURL');
2461  // init CURL
2462  $this->ch = curl_init();
2463  // set url
2464  $hostURL = ($this->port != '') ? "$this->scheme://$this->host:$this->port" : "$this->scheme://$this->host";
2465  // add path
2466  $hostURL .= $this->path;
2467  $this->setCurlOption(CURLOPT_URL, $hostURL);
2468  // follow location headers (re-directs)
2469  if (ini_get('safe_mode') || ini_get('open_basedir')) {
2470  $this->debug('safe_mode or open_basedir set, so do not set CURLOPT_FOLLOWLOCATION');
2471  $this->debug('safe_mode = ');
2472  $this->appendDebug($this->varDump(ini_get('safe_mode')));
2473  $this->debug('open_basedir = ');
2474  $this->appendDebug($this->varDump(ini_get('open_basedir')));
2475  } else {
2476  $this->setCurlOption(CURLOPT_FOLLOWLOCATION, 1);
2477  }
2478  // ask for headers in the response output
2479  $this->setCurlOption(CURLOPT_HEADER, 1);
2480  // ask for the response output as the return value
2481  $this->setCurlOption(CURLOPT_RETURNTRANSFER, 1);
2482  // encode
2483  // We manage this ourselves through headers and encoding
2484  // if(function_exists('gzuncompress')){
2485  // $this->setCurlOption(CURLOPT_ENCODING, 'deflate');
2486  // }
2487  // persistent connection
2488  if ($this->persistentConnection) {
2489  // I believe the following comment is now bogus, having applied to
2490  // the code when it used CURLOPT_CUSTOMREQUEST to send the request.
2491  // The way we send data, we cannot use persistent connections, since
2492  // there will be some "junk" at the end of our request.
2493  //$this->setCurlOption(CURL_HTTP_VERSION_1_1, true);
2494  $this->persistentConnection = false;
2495  $this->setHeader('Connection', 'close');
2496  }
2497  // set timeouts
2498  if ($connection_timeout != 0) {
2499  $this->setCurlOption($CURLOPT_CONNECTIONTIMEOUT, $connection_timeout);
2500  }
2501  if ($response_timeout != 0) {
2502  $this->setCurlOption(CURLOPT_TIMEOUT, $response_timeout);
2503  }
2504 
2505  if ($this->scheme == 'https') {
2506  $this->debug('set cURL SSL verify options');
2507  // recent versions of cURL turn on peer/host checking by default,
2508  // while PHP binaries are not compiled with a default location for the
2509  // CA cert bundle, so disable peer/host checking.
2510  //$this->setCurlOption(CURLOPT_CAINFO, 'f:\php-4.3.2-win32\extensions\curl-ca-bundle.crt');
2511  $this->setCurlOption(CURLOPT_SSL_VERIFYPEER, 0);
2512  $this->setCurlOption(CURLOPT_SSL_VERIFYHOST, 0);
2513 
2514  // support client certificates (thanks Tobias Boes, Doug Anarino, Eryan Ariobowo)
2515  if ($this->authtype == 'certificate') {
2516  $this->debug('set cURL certificate options');
2517  if (isset($this->certRequest['cainfofile'])) {
2518  $this->setCurlOption(CURLOPT_CAINFO, $this->certRequest['cainfofile']);
2519  }
2520  if (isset($this->certRequest['verifypeer'])) {
2521  $this->setCurlOption(CURLOPT_SSL_VERIFYPEER, $this->certRequest['verifypeer']);
2522  } else {
2523  $this->setCurlOption(CURLOPT_SSL_VERIFYPEER, 1);
2524  }
2525  if (isset($this->certRequest['verifyhost'])) {
2526  $this->setCurlOption(CURLOPT_SSL_VERIFYHOST, $this->certRequest['verifyhost']);
2527  } else {
2528  $this->setCurlOption(CURLOPT_SSL_VERIFYHOST, 1);
2529  }
2530  if (isset($this->certRequest['sslcertfile'])) {
2531  $this->setCurlOption(CURLOPT_SSLCERT, $this->certRequest['sslcertfile']);
2532  }
2533  if (isset($this->certRequest['sslkeyfile'])) {
2534  $this->setCurlOption(CURLOPT_SSLKEY, $this->certRequest['sslkeyfile']);
2535  }
2536  if (isset($this->certRequest['passphrase'])) {
2537  $this->setCurlOption(CURLOPT_SSLKEYPASSWD, $this->certRequest['passphrase']);
2538  }
2539  if (isset($this->certRequest['certpassword'])) {
2540  $this->setCurlOption(CURLOPT_SSLCERTPASSWD, $this->certRequest['certpassword']);
2541  }
2542  }
2543  }
2544  if ($this->authtype && ($this->authtype != 'certificate')) {
2545  if ($this->username) {
2546  $this->debug('set cURL username/password');
2547  $this->setCurlOption(CURLOPT_USERPWD, "$this->username:$this->password");
2548  }
2549  if ($this->authtype == 'basic') {
2550  $this->debug('set cURL for Basic authentication');
2551  $this->setCurlOption($CURLOPT_HTTPAUTH, $CURLAUTH_BASIC);
2552  }
2553  if ($this->authtype == 'digest') {
2554  $this->debug('set cURL for digest authentication');
2555  $this->setCurlOption($CURLOPT_HTTPAUTH, $CURLAUTH_DIGEST);
2556  }
2557  if ($this->authtype == 'ntlm') {
2558  $this->debug('set cURL for NTLM authentication');
2559  $this->setCurlOption($CURLOPT_HTTPAUTH, $CURLAUTH_NTLM);
2560  }
2561  }
2562  if (is_array($this->proxy)) {
2563  $this->debug('set cURL proxy options');
2564  if ($this->proxy['port'] != '') {
2565  $this->setCurlOption(CURLOPT_PROXY, $this->proxy['host'] . ':' . $this->proxy['port']);
2566  } else {
2567  $this->setCurlOption(CURLOPT_PROXY, $this->proxy['host']);
2568  }
2569  if ($this->proxy['username'] || $this->proxy['password']) {
2570  $this->debug('set cURL proxy authentication options');
2571  $this->setCurlOption(CURLOPT_PROXYUSERPWD, $this->proxy['username'] . ':' . $this->proxy['password']);
2572  if ($this->proxy['authtype'] == 'basic') {
2573  $this->setCurlOption($CURLOPT_PROXYAUTH, $CURLAUTH_BASIC);
2574  }
2575  if ($this->proxy['authtype'] == 'ntlm') {
2576  $this->setCurlOption($CURLOPT_PROXYAUTH, $CURLAUTH_NTLM);
2577  }
2578  }
2579  }
2580  $this->debug('cURL connection set up');
2581  return true;
2582  } else {
2583  $this->setError('Unknown scheme ' . $this->scheme);
2584  $this->debug('Unknown scheme ' . $this->scheme);
2585  return false;
2586  }
2587  }
2588 
2599  public function send($data, $timeout=0, $response_timeout=30, $cookies=null)
2600  {
2601  $this->debug('entered send() with data of length: ' . strlen($data));
2602 
2603  $this->tryagain = true;
2604  $tries = 0;
2605  while ($this->tryagain) {
2606  $this->tryagain = false;
2607  if ($tries++ < 2) {
2608  // make connnection
2609  if (!$this->connect($timeout, $response_timeout)) {
2610  return false;
2611  }
2612 
2613  // send request
2614  if (!$this->sendRequest($data, $cookies)) {
2615  return false;
2616  }
2617 
2618  // get response
2619  $respdata = $this->getResponse();
2620  } else {
2621  $this->setError("Too many tries to get an OK response ($this->response_status_line)");
2622  }
2623  }
2624  $this->debug('end of send()');
2625  return $respdata;
2626  }
2627 
2628 
2640  public function sendHTTPS($data, $timeout=0, $response_timeout=30, $cookies=null)
2641  {
2642  return $this->send($data, $timeout, $response_timeout, $cookies);
2643  }
2644 
2655  public function setCredentials($username, $password, $authtype = 'basic', $digestRequest = array(), $certRequest = array())
2656  {
2657  $this->debug("setCredentials username=$username authtype=$authtype digestRequest=");
2658  $this->appendDebug($this->varDump($digestRequest));
2659  $this->debug("certRequest=");
2660  $this->appendDebug($this->varDump($certRequest));
2661  // cf. RFC 2617
2662  if ($authtype == 'basic') {
2663  $this->setHeader('Authorization', 'Basic ' . base64_encode(str_replace(':', '', $username) . ':' . $password));
2664  } elseif ($authtype == 'digest') {
2665  if (isset($digestRequest['nonce'])) {
2666  $digestRequest['nc'] = isset($digestRequest['nc']) ? $digestRequest['nc']++ : 1;
2667 
2668  // calculate the Digest hashes (calculate code based on digest implementation found at: http://www.rassoc.com/gregr/weblog/stories/2002/07/09/webServicesSecurityHttpDigestAuthenticationWithoutActiveDirectory.html)
2669 
2670  // A1 = unq(username-value) ":" unq(realm-value) ":" passwd
2671  $A1 = $username . ':' . (isset($digestRequest['realm']) ? $digestRequest['realm'] : '') . ':' . $password;
2672 
2673  // H(A1) = MD5(A1)
2674  $HA1 = md5($A1);
2675 
2676  // A2 = Method ":" digest-uri-value
2677  $A2 = $this->request_method . ':' . $this->digest_uri;
2678 
2679  // H(A2)
2680  $HA2 = md5($A2);
2681 
2682  // KD(secret, data) = H(concat(secret, ":", data))
2683  // if qop == auth:
2684  // request-digest = <"> < KD ( H(A1), unq(nonce-value)
2685  // ":" nc-value
2686  // ":" unq(cnonce-value)
2687  // ":" unq(qop-value)
2688  // ":" H(A2)
2689  // ) <">
2690  // if qop is missing,
2691  // request-digest = <"> < KD ( H(A1), unq(nonce-value) ":" H(A2) ) > <">
2692 
2693  $unhashedDigest = '';
2694  $nonce = isset($digestRequest['nonce']) ? $digestRequest['nonce'] : '';
2695  $cnonce = $nonce;
2696  if ($digestRequest['qop'] != '') {
2697  $unhashedDigest = $HA1 . ':' . $nonce . ':' . sprintf("%08d", $digestRequest['nc']) . ':' . $cnonce . ':' . $digestRequest['qop'] . ':' . $HA2;
2698  } else {
2699  $unhashedDigest = $HA1 . ':' . $nonce . ':' . $HA2;
2700  }
2701 
2702  $hashedDigest = md5($unhashedDigest);
2703 
2704  $opaque = '';
2705  if (isset($digestRequest['opaque'])) {
2706  $opaque = ', opaque="' . $digestRequest['opaque'] . '"';
2707  }
2708 
2709  $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 . '"');
2710  }
2711  } elseif ($authtype == 'certificate') {
2712  $this->certRequest = $certRequest;
2713  $this->debug('Authorization header not set for certificate');
2714  } elseif ($authtype == 'ntlm') {
2715  // do nothing
2716  $this->debug('Authorization header not set for ntlm');
2717  }
2718  $this->username = $username;
2719  $this->password = $password;
2720  $this->authtype = $authtype;
2721  $this->digestRequest = $digestRequest;
2722  }
2723 
2730  public function setSOAPAction($soapaction)
2731  {
2732  $this->setHeader('SOAPAction', '"' . $soapaction . '"');
2733  }
2734 
2741  public function setEncoding($enc='gzip, deflate')
2742  {
2743  if (function_exists('gzdeflate')) {
2744  $this->protocol_version = '1.1';
2745  $this->setHeader('Accept-Encoding', $enc);
2746  if (!isset($this->outgoing_headers['Connection'])) {
2747  $this->setHeader('Connection', 'close');
2748  $this->persistentConnection = false;
2749  }
2750  #set_magic_quotes_runtime(0);
2751  // deprecated
2752  $this->encoding = $enc;
2753  }
2754  }
2755 
2766  public function setProxy($proxyhost, $proxyport, $proxyusername = '', $proxypassword = '', $proxyauthtype = 'basic')
2767  {
2768  if ($proxyhost) {
2769  $this->proxy = array(
2770  'host' => $proxyhost,
2771  'port' => $proxyport,
2772  'username' => $proxyusername,
2773  'password' => $proxypassword,
2774  'authtype' => $proxyauthtype
2775  );
2776  if ($proxyusername != '' && $proxypassword != '' && $proxyauthtype = 'basic') {
2777  $this->setHeader('Proxy-Authorization', ' Basic ' . base64_encode($proxyusername . ':' . $proxypassword));
2778  }
2779  } else {
2780  $this->debug('remove proxy');
2781  $proxy = null;
2782  unsetHeader('Proxy-Authorization');
2783  }
2784  }
2785 
2786 
2795  public function isSkippableCurlHeader(&$data)
2796  {
2797  $skipHeaders = array( 'HTTP/1.1 100',
2798  'HTTP/1.0 301',
2799  'HTTP/1.1 301',
2800  'HTTP/1.0 302',
2801  'HTTP/1.1 302',
2802  'HTTP/1.0 401',
2803  'HTTP/1.1 401',
2804  'HTTP/1.0 200 Connection established');
2805  foreach ($skipHeaders as $hd) {
2806  $prefix = substr($data, 0, strlen($hd));
2807  if ($prefix == $hd) {
2808  return true;
2809  }
2810  }
2811 
2812  return false;
2813  }
2814 
2825  public function decodeChunked($buffer, $lb)
2826  {
2827  // length := 0
2828  $length = 0;
2829  $new = '';
2830 
2831  // read chunk-size, chunk-extension (if any) and CRLF
2832  // get the position of the linebreak
2833  $chunkend = strpos($buffer, $lb);
2834  if ($chunkend == false) {
2835  $this->debug('no linebreak found in decodeChunked');
2836  return $new;
2837  }
2838  $temp = substr($buffer, 0, $chunkend);
2839  $chunk_size = hexdec(trim($temp));
2840  $chunkstart = $chunkend + strlen($lb);
2841  // while (chunk-size > 0) {
2842  while ($chunk_size > 0) {
2843  $this->debug("chunkstart: $chunkstart chunk_size: $chunk_size");
2844  $chunkend = strpos($buffer, $lb, $chunkstart + $chunk_size);
2845 
2846  // Just in case we got a broken connection
2847  if ($chunkend == false) {
2848  $chunk = substr($buffer, $chunkstart);
2849  // append chunk-data to entity-body
2850  $new .= $chunk;
2851  $length += strlen($chunk);
2852  break;
2853  }
2854 
2855  // read chunk-data and CRLF
2856  $chunk = substr($buffer, $chunkstart, $chunkend-$chunkstart);
2857  // append chunk-data to entity-body
2858  $new .= $chunk;
2859  // length := length + chunk-size
2860  $length += strlen($chunk);
2861  // read chunk-size and CRLF
2862  $chunkstart = $chunkend + strlen($lb);
2863 
2864  $chunkend = strpos($buffer, $lb, $chunkstart) + strlen($lb);
2865  if ($chunkend == false) {
2866  break; //Just in case we got a broken connection
2867  }
2868  $temp = substr($buffer, $chunkstart, $chunkend-$chunkstart);
2869  $chunk_size = hexdec(trim($temp));
2870  $chunkstart = $chunkend;
2871  }
2872  return $new;
2873  }
2874 
2883  public function buildPayload($data, $cookie_str = '')
2884  {
2885  // Note: for cURL connections, $this->outgoing_payload is ignored,
2886  // as is the Content-Length header, but these are still created as
2887  // debugging guides.
2888 
2889  // add content-length header
2890  $this->setHeader('Content-Length', strlen($data));
2891 
2892  // start building outgoing payload:
2893  if ($this->proxy) {
2894  $uri = $this->url;
2895  } else {
2896  $uri = $this->uri;
2897  }
2898  $req = "$this->request_method $uri HTTP/$this->protocol_version";
2899  $this->debug("HTTP request: $req");
2900  $this->outgoing_payload = "$req\r\n";
2901 
2902  // loop thru headers, serializing
2903  foreach ($this->outgoing_headers as $k => $v) {
2904  $hdr = $k . ': ' . $v;
2905  $this->debug("HTTP header: $hdr");
2906  $this->outgoing_payload .= "$hdr\r\n";
2907  }
2908 
2909  // add any cookies
2910  if ($cookie_str != '') {
2911  $hdr = 'Cookie: ' . $cookie_str;
2912  $this->debug("HTTP header: $hdr");
2913  $this->outgoing_payload .= "$hdr\r\n";
2914  }
2915 
2916  // header/body separator
2917  $this->outgoing_payload .= "\r\n";
2918 
2919  // add data
2920  $this->outgoing_payload .= $data;
2921  }
2922 
2931  public function sendRequest($data, $cookies = null)
2932  {
2933  // build cookie string
2934  $cookie_str = $this->getCookiesForRequest($cookies, (($this->scheme == 'ssl') || ($this->scheme == 'https')));
2935 
2936  // build payload
2937  $this->buildPayload($data, $cookie_str);
2938 
2939  if ($this->io_method() == 'socket') {
2940  // send payload
2941  if (!fputs($this->fp, $this->outgoing_payload, strlen($this->outgoing_payload))) {
2942  $this->setError('couldn\'t write message data to socket');
2943  $this->debug('couldn\'t write message data to socket');
2944  return false;
2945  }
2946  $this->debug('wrote data to socket, length = ' . strlen($this->outgoing_payload));
2947  return true;
2948  } elseif ($this->io_method() == 'curl') {
2949  // set payload
2950  // cURL does say this should only be the verb, and in fact it
2951  // turns out that the URI and HTTP version are appended to this, which
2952  // some servers refuse to work with (so we no longer use this method!)
2953  //$this->setCurlOption(CURLOPT_CUSTOMREQUEST, $this->outgoing_payload);
2954  $curl_headers = array();
2955  foreach ($this->outgoing_headers as $k => $v) {
2956  if ($k == 'Connection' || $k == 'Content-Length' || $k == 'Host' || $k == 'Authorization' || $k == 'Proxy-Authorization') {
2957  $this->debug("Skip cURL header $k: $v");
2958  } else {
2959  $curl_headers[] = "$k: $v";
2960  }
2961  }
2962  if ($cookie_str != '') {
2963  $curl_headers[] = 'Cookie: ' . $cookie_str;
2964  }
2965  $this->setCurlOption(CURLOPT_HTTPHEADER, $curl_headers);
2966  $this->debug('set cURL HTTP headers');
2967  if ($this->request_method == "POST") {
2968  $this->setCurlOption(CURLOPT_POST, 1);
2969  $this->setCurlOption(CURLOPT_POSTFIELDS, $data);
2970  $this->debug('set cURL POST data');
2971  } else {
2972  }
2973  // insert custom user-set cURL options
2974  foreach ($this->ch_options as $key => $val) {
2975  $this->setCurlOption($key, $val);
2976  }
2977 
2978  $this->debug('set cURL payload');
2979  return true;
2980  }
2981  }
2982 
2989  public function getResponse()
2990  {
2991  $this->incoming_payload = '';
2992 
2993  if ($this->io_method() == 'socket') {
2994  // loop until headers have been retrieved
2995  $data = '';
2996  while (!isset($lb)) {
2997  // We might EOF during header read.
2998  if (feof($this->fp)) {
2999  $this->incoming_payload = $data;
3000  $this->debug('found no headers before EOF after length ' . strlen($data));
3001  $this->debug("received before EOF:\n" . $data);
3002  $this->setError('server failed to send headers');
3003  return false;
3004  }
3005 
3006  $tmp = fgets($this->fp, 256);
3007  $tmplen = strlen($tmp);
3008  $this->debug("read line of $tmplen bytes: " . trim($tmp));
3009 
3010  if ($tmplen == 0) {
3011  $this->incoming_payload = $data;
3012  $this->debug('socket read of headers timed out after length ' . strlen($data));
3013  $this->debug("read before timeout: " . $data);
3014  $this->setError('socket read of headers timed out');
3015  return false;
3016  }
3017 
3018  $data .= $tmp;
3019  $pos = strpos($data, "\r\n\r\n");
3020  if ($pos > 1) {
3021  $lb = "\r\n";
3022  } else {
3023  $pos = strpos($data, "\n\n");
3024  if ($pos > 1) {
3025  $lb = "\n";
3026  }
3027  }
3028  // remove 100 headers
3029  if (isset($lb) && preg_match('/^HTTP\/1.1 100/', $data)) {
3030  unset($lb);
3031  $data = '';
3032  }//
3033  }
3034  // store header data
3035  $this->incoming_payload .= $data;
3036  $this->debug('found end of headers after length ' . strlen($data));
3037  // process headers
3038  $header_data = trim(substr($data, 0, $pos));
3039  $header_array = explode($lb, $header_data);
3040  $this->incoming_headers = array();
3041  $this->incoming_cookies = array();
3042  foreach ($header_array as $header_line) {
3043  $arr = explode(':', $header_line, 2);
3044  if (count($arr) > 1) {
3045  $header_name = strtolower(trim($arr[0]));
3046  $this->incoming_headers[$header_name] = trim($arr[1]);
3047  if ($header_name == 'set-cookie') {
3048  // TODO: allow multiple cookies from parseCookie
3049  $cookie = $this->parseCookie(trim($arr[1]));
3050  if ($cookie) {
3051  $this->incoming_cookies[] = $cookie;
3052  $this->debug('found cookie: ' . $cookie['name'] . ' = ' . $cookie['value']);
3053  } else {
3054  $this->debug('did not find cookie in ' . trim($arr[1]));
3055  }
3056  }
3057  } elseif (isset($header_name)) {
3058  // append continuation line to previous header
3059  $this->incoming_headers[$header_name] .= $lb . ' ' . $header_line;
3060  }
3061  }
3062 
3063  // loop until msg has been received
3064  if (isset($this->incoming_headers['transfer-encoding']) && strtolower($this->incoming_headers['transfer-encoding']) == 'chunked') {
3065  $content_length = 2147483647; // ignore any content-length header
3066  $chunked = true;
3067  $this->debug("want to read chunked content");
3068  } elseif (isset($this->incoming_headers['content-length'])) {
3069  $content_length = $this->incoming_headers['content-length'];
3070  $chunked = false;
3071  $this->debug("want to read content of length $content_length");
3072  } else {
3073  $content_length = 2147483647;
3074  $chunked = false;
3075  $this->debug("want to read content to EOF");
3076  }
3077  $data = '';
3078  do {
3079  if ($chunked) {
3080  $tmp = fgets($this->fp, 256);
3081  $tmplen = strlen($tmp);
3082  $this->debug("read chunk line of $tmplen bytes");
3083  if ($tmplen == 0) {
3084  $this->incoming_payload = $data;
3085  $this->debug('socket read of chunk length timed out after length ' . strlen($data));
3086  $this->debug("read before timeout:\n" . $data);
3087  $this->setError('socket read of chunk length timed out');
3088  return false;
3089  }
3090  $content_length = hexdec(trim($tmp));
3091  $this->debug("chunk length $content_length");
3092  }
3093  $strlen = 0;
3094  while (($strlen < $content_length) && (!feof($this->fp))) {
3095  $readlen = min(8192, $content_length - $strlen);
3096  $tmp = fread($this->fp, $readlen);
3097  $tmplen = strlen($tmp);
3098  $this->debug("read buffer of $tmplen bytes");
3099  if (($tmplen == 0) && (!feof($this->fp))) {
3100  $this->incoming_payload = $data;
3101  $this->debug('socket read of body timed out after length ' . strlen($data));
3102  $this->debug("read before timeout:\n" . $data);
3103  $this->setError('socket read of body timed out');
3104  return false;
3105  }
3106  $strlen += $tmplen;
3107  $data .= $tmp;
3108  }
3109  if ($chunked && ($content_length > 0)) {
3110  $tmp = fgets($this->fp, 256);
3111  $tmplen = strlen($tmp);
3112  $this->debug("read chunk terminator of $tmplen bytes");
3113  if ($tmplen == 0) {
3114  $this->incoming_payload = $data;
3115  $this->debug('socket read of chunk terminator timed out after length ' . strlen($data));
3116  $this->debug("read before timeout:\n" . $data);
3117  $this->setError('socket read of chunk terminator timed out');
3118  return false;
3119  }
3120  }
3121  } while ($chunked && ($content_length > 0) && (!feof($this->fp)));
3122  if (feof($this->fp)) {
3123  $this->debug('read to EOF');
3124  }
3125  $this->debug('read body of length ' . strlen($data));
3126  $this->incoming_payload .= $data;
3127  $this->debug('received a total of ' . strlen($this->incoming_payload) . ' bytes of data from server');
3128 
3129  // close filepointer
3130  if (
3131  (isset($this->incoming_headers['connection']) && strtolower($this->incoming_headers['connection']) == 'close') ||
3132  (! $this->persistentConnection) || feof($this->fp)) {
3133  fclose($this->fp);
3134  $this->fp = false;
3135  $this->debug('closed socket');
3136  }
3137 
3138  // connection was closed unexpectedly
3139  if ($this->incoming_payload == '') {
3140  $this->setError('no response from server');
3141  return false;
3142  }
3143 
3144  // decode transfer-encoding
3145  // if(isset($this->incoming_headers['transfer-encoding']) && strtolower($this->incoming_headers['transfer-encoding']) == 'chunked'){
3146  // if(!$data = $this->decodeChunked($data, $lb)){
3147  // $this->setError('Decoding of chunked data failed');
3148  // return false;
3149  // }
3150  //print "<pre>\nde-chunked:\n---------------\n$data\n\n---------------\n</pre>";
3151  // set decoded payload
3152  // $this->incoming_payload = $header_data.$lb.$lb.$data;
3153  // }
3154  } elseif ($this->io_method() == 'curl') {
3155  // send and receive
3156  $this->debug('send and receive with cURL');
3157  $this->incoming_payload = curl_exec($this->ch);
3158  $data = $this->incoming_payload;
3159 
3160  $cErr = curl_error($this->ch);
3161  if ($cErr != '') {
3162  $err = 'cURL ERROR: ' . curl_errno($this->ch) . ': ' . $cErr . '<br>';
3163  // TODO: there is a PHP bug that can cause this to SEGV for CURLINFO_CONTENT_TYPE
3164  foreach (curl_getinfo($this->ch) as $k => $v) {
3165  $err .= "$k: $v<br>";
3166  }
3167  $this->debug($err);
3168  $this->setError($err);
3169  curl_close($this->ch);
3170  return false;
3171  } else {
3172  //echo '<pre>';
3173  //var_dump(curl_getinfo($this->ch));
3174  //echo '</pre>';
3175  }
3176  // close curl
3177  $this->debug('No cURL error, closing cURL');
3178  curl_close($this->ch);
3179 
3180  // try removing skippable headers
3181  $savedata = $data;
3182  while ($this->isSkippableCurlHeader($data)) {
3183  $this->debug("Found HTTP header to skip");
3184  if ($pos = strpos($data, "\r\n\r\n")) {
3185  $data = ltrim(substr($data, $pos));
3186  } elseif ($pos = strpos($data, "\n\n")) {
3187  $data = ltrim(substr($data, $pos));
3188  }
3189  }
3190 
3191  if ($data == '') {
3192  // have nothing left; just remove 100 header(s)
3193  $data = $savedata;
3194  while (preg_match('/^HTTP\/1.1 100/', $data)) {
3195  if ($pos = strpos($data, "\r\n\r\n")) {
3196  $data = ltrim(substr($data, $pos));
3197  } elseif ($pos = strpos($data, "\n\n")) {
3198  $data = ltrim(substr($data, $pos));
3199  }
3200  }
3201  }
3202 
3203  // separate content from HTTP headers
3204  if ($pos = strpos($data, "\r\n\r\n")) {
3205  $lb = "\r\n";
3206  } elseif ($pos = strpos($data, "\n\n")) {
3207  $lb = "\n";
3208  } else {
3209  $this->debug('no proper separation of headers and document');
3210  $this->setError('no proper separation of headers and document');
3211  return false;
3212  }
3213  $header_data = trim(substr($data, 0, $pos));
3214  $header_array = explode($lb, $header_data);
3215  $data = ltrim(substr($data, $pos));
3216  $this->debug('found proper separation of headers and document');
3217  $this->debug('cleaned data, stringlen: ' . strlen($data));
3218  // clean headers
3219  foreach ($header_array as $header_line) {
3220  $arr = explode(':', $header_line, 2);
3221  if (count($arr) > 1) {
3222  $header_name = strtolower(trim($arr[0]));
3223  $this->incoming_headers[$header_name] = trim($arr[1]);
3224  if ($header_name == 'set-cookie') {
3225  // TODO: allow multiple cookies from parseCookie
3226  $cookie = $this->parseCookie(trim($arr[1]));
3227  if ($cookie) {
3228  $this->incoming_cookies[] = $cookie;
3229  $this->debug('found cookie: ' . $cookie['name'] . ' = ' . $cookie['value']);
3230  } else {
3231  $this->debug('did not find cookie in ' . trim($arr[1]));
3232  }
3233  }
3234  } elseif (isset($header_name)) {
3235  // append continuation line to previous header
3236  $this->incoming_headers[$header_name] .= $lb . ' ' . $header_line;
3237  }
3238  }
3239  }
3240 
3241  $this->response_status_line = $header_array[0];
3242  $arr = explode(' ', $this->response_status_line, 3);
3243  $http_version = $arr[0];
3244  $http_status = intval($arr[1]);
3245  $http_reason = count($arr) > 2 ? $arr[2] : '';
3246 
3247  // see if we need to resend the request with http digest authentication
3248  if (isset($this->incoming_headers['location']) && ($http_status == 301 || $http_status == 302)) {
3249  $this->debug("Got $http_status $http_reason with Location: " . $this->incoming_headers['location']);
3250  $this->setURL($this->incoming_headers['location']);
3251  $this->tryagain = true;
3252  return false;
3253  }
3254 
3255  // see if we need to resend the request with http digest authentication
3256  if (isset($this->incoming_headers['www-authenticate']) && $http_status == 401) {
3257  $this->debug("Got 401 $http_reason with WWW-Authenticate: " . $this->incoming_headers['www-authenticate']);
3258  if (strstr($this->incoming_headers['www-authenticate'], "Digest ")) {
3259  $this->debug('Server wants digest authentication');
3260  // remove "Digest " from our elements
3261  $digestString = str_replace('Digest ', '', $this->incoming_headers['www-authenticate']);
3262 
3263  // parse elements into array
3264  $digestElements = explode(',', $digestString);
3265  foreach ($digestElements as $val) {
3266  $tempElement = explode('=', trim($val), 2);
3267  $digestRequest[$tempElement[0]] = str_replace("\"", '', $tempElement[1]);
3268  }
3269 
3270  // should have (at least) qop, realm, nonce
3271  if (isset($digestRequest['nonce'])) {
3272  $this->setCredentials($this->username, $this->password, 'digest', $digestRequest);
3273  $this->tryagain = true;
3274  return false;
3275  }
3276  }
3277  $this->debug('HTTP authentication failed');
3278  $this->setError('HTTP authentication failed');
3279  return false;
3280  }
3281 
3282  if (
3283  ($http_status >= 300 && $http_status <= 307) ||
3284  ($http_status >= 400 && $http_status <= 417) ||
3285  ($http_status >= 501 && $http_status <= 505)
3286  ) {
3287  $this->setError("Unsupported HTTP response status $http_status $http_reason (soapclient->response has contents of the response)");
3288  return false;
3289  }
3290 
3291  // decode content-encoding
3292  if (isset($this->incoming_headers['content-encoding']) && $this->incoming_headers['content-encoding'] != '') {
3293  if (strtolower($this->incoming_headers['content-encoding']) == 'deflate' || strtolower($this->incoming_headers['content-encoding']) == 'gzip') {
3294  // if decoding works, use it. else assume data wasn't gzencoded
3295  if (function_exists('gzinflate')) {
3296  //$timer->setMarker('starting decoding of gzip/deflated content');
3297  // IIS 5 requires gzinflate instead of gzuncompress (similar to IE 5 and gzdeflate v. gzcompress)
3298  // this means there are no Zlib headers, although there should be
3299  $this->debug('The gzinflate function exists');
3300  $datalen = strlen($data);
3301  if ($this->incoming_headers['content-encoding'] == 'deflate') {
3302  if ($degzdata = @gzinflate($data)) {
3303  $data = $degzdata;
3304  $this->debug('The payload has been inflated to ' . strlen($data) . ' bytes');
3305  if (strlen($data) < $datalen) {
3306  // test for the case that the payload has been compressed twice
3307  $this->debug('The inflated payload is smaller than the gzipped one; try again');
3308  if ($degzdata = @gzinflate($data)) {
3309  $data = $degzdata;
3310  $this->debug('The payload has been inflated again to ' . strlen($data) . ' bytes');
3311  }
3312  }
3313  } else {
3314  $this->debug('Error using gzinflate to inflate the payload');
3315  $this->setError('Error using gzinflate to inflate the payload');
3316  }
3317  } elseif ($this->incoming_headers['content-encoding'] == 'gzip') {
3318  if ($degzdata = @gzinflate(substr($data, 10))) { // do our best
3319  $data = $degzdata;
3320  $this->debug('The payload has been un-gzipped to ' . strlen($data) . ' bytes');
3321  if (strlen($data) < $datalen) {
3322  // test for the case that the payload has been compressed twice
3323  $this->debug('The un-gzipped payload is smaller than the gzipped one; try again');
3324  if ($degzdata = @gzinflate(substr($data, 10))) {
3325  $data = $degzdata;
3326  $this->debug('The payload has been un-gzipped again to ' . strlen($data) . ' bytes');
3327  }
3328  }
3329  } else {
3330  $this->debug('Error using gzinflate to un-gzip the payload');
3331  $this->setError('Error using gzinflate to un-gzip the payload');
3332  }
3333  }
3334  //$timer->setMarker('finished decoding of gzip/deflated content');
3335  //print "<xmp>\nde-inflated:\n---------------\n$data\n-------------\n</xmp>";
3336  // set decoded payload
3337  $this->incoming_payload = $header_data . $lb . $lb . $data;
3338  } else {
3339  $this->debug('The server sent compressed data. Your php install must have the Zlib extension compiled in to support this.');
3340  $this->setError('The server sent compressed data. Your php install must have the Zlib extension compiled in to support this.');
3341  }
3342  } else {
3343  $this->debug('Unsupported Content-Encoding ' . $this->incoming_headers['content-encoding']);
3344  $this->setError('Unsupported Content-Encoding ' . $this->incoming_headers['content-encoding']);
3345  }
3346  } else {
3347  $this->debug('No Content-Encoding header');
3348  }
3349 
3350  if (strlen($data) == 0) {
3351  $this->debug('no data after headers!');
3352  $this->setError('no data present after HTTP headers');
3353  return false;
3354  }
3355 
3356  return $data;
3357  }
3358 
3366  public function setContentType($type, $charset = false)
3367  {
3368  $this->setHeader('Content-Type', $type . ($charset ? '; charset=' . $charset : ''));
3369  }
3370 
3377  public function usePersistentConnection()
3378  {
3379  if (isset($this->outgoing_headers['Accept-Encoding'])) {
3380  return false;
3381  }
3382  $this->protocol_version = '1.1';
3383  $this->persistentConnection = true;
3384  $this->setHeader('Connection', 'Keep-Alive');
3385  return true;
3386  }
3387 
3395  /*
3396  * TODO: allow a Set-Cookie string to be parsed into multiple cookies
3397  */
3398  public function parseCookie($cookie_str)
3399  {
3400  $cookie_str = str_replace('; ', ';', $cookie_str) . ';';
3401  // begin-patch php8
3402  //$data = split(';', $cookie_str);
3403  $data = explode(';', $cookie_str);
3404  $value_str = $data[0];
3405 
3406  $cookie_param = 'domain=';
3407  $start = strpos($cookie_str, $cookie_param);
3408  if ($start > 0) {
3409  $domain = substr($cookie_str, $start + strlen($cookie_param));
3410  $domain = substr($domain, 0, strpos($domain, ';'));
3411  } else {
3412  $domain = '';
3413  }
3414 
3415  $cookie_param = 'expires=';
3416  $start = strpos($cookie_str, $cookie_param);
3417  if ($start > 0) {
3418  $expires = substr($cookie_str, $start + strlen($cookie_param));
3419  $expires = substr($expires, 0, strpos($expires, ';'));
3420  } else {
3421  $expires = '';
3422  }
3423 
3424  $cookie_param = 'path=';
3425  $start = strpos($cookie_str, $cookie_param);
3426  if ($start > 0) {
3427  $path = substr($cookie_str, $start + strlen($cookie_param));
3428  $path = substr($path, 0, strpos($path, ';'));
3429  } else {
3430  $path = '/';
3431  }
3432 
3433  $cookie_param = ';secure;';
3434  if (strpos($cookie_str, $cookie_param) !== false) {
3435  $secure = true;
3436  } else {
3437  $secure = false;
3438  }
3439 
3440  $sep_pos = strpos($value_str, '=');
3441 
3442  if ($sep_pos) {
3443  $name = substr($value_str, 0, $sep_pos);
3444  $value = substr($value_str, $sep_pos + 1);
3445  $cookie= array( 'name' => $name,
3446  'value' => $value,
3447  'domain' => $domain,
3448  'path' => $path,
3449  'expires' => $expires,
3450  'secure' => $secure
3451  );
3452  return $cookie;
3453  }
3454  return false;
3455  }
3456 
3465  public function getCookiesForRequest($cookies, $secure=false)
3466  {
3467  $cookie_str = '';
3468  if ((! is_null($cookies)) && (is_array($cookies))) {
3469  foreach ($cookies as $cookie) {
3470  if (! is_array($cookie)) {
3471  continue;
3472  }
3473  $this->debug("check cookie for validity: " . $cookie['name'] . '=' . $cookie['value']);
3474  if ((isset($cookie['expires'])) && (! empty($cookie['expires']))) {
3475  if (strtotime($cookie['expires']) <= time()) {
3476  $this->debug('cookie has expired');
3477  continue;
3478  }
3479  }
3480  if ((isset($cookie['domain'])) && (! empty($cookie['domain']))) {
3481  $domain = preg_quote($cookie['domain']);
3482  if (! preg_match("'.*$domain$'i", $this->host)) {
3483  $this->debug('cookie has different domain');
3484  continue;
3485  }
3486  }
3487  if ((isset($cookie['path'])) && (! empty($cookie['path']))) {
3488  $path = preg_quote($cookie['path']);
3489  if (! preg_match("'^$path.*'i", $this->path)) {
3490  $this->debug('cookie is for a different path');
3491  continue;
3492  }
3493  }
3494  if ((! $secure) && (isset($cookie['secure'])) && ($cookie['secure'])) {
3495  $this->debug('cookie is secure, transport is not');
3496  continue;
3497  }
3498  $cookie_str .= $cookie['name'] . '=' . $cookie['value'] . '; ';
3499  $this->debug('add cookie to Cookie-String: ' . $cookie['name'] . '=' . $cookie['value']);
3500  }
3501  }
3502  return $cookie_str;
3503  }
3504 }
3505 
3506 ?><?php
3507 
3508 
3509 
3521 {
3522  public $opData;
3528  public $headers = array();
3534  public $request = '';
3540  public $requestHeaders = '';
3546  public $requestHeader = null;
3552  public $document = '';
3558  public $requestSOAP = '';
3564  public $methodURI = '';
3570  public $methodname = '';
3576  public $methodparams = array();
3582  public $SOAPAction = '';
3588  public $xml_encoding = '';
3594  public $decode_utf8 = true;
3595  public $class;
3596 
3602  public $outgoing_headers = array();
3608  public $response = '';
3614  public $responseHeaders = '';
3620  public $responseSOAP = '';
3626  public $methodreturn = false;
3632  public $methodreturnisliteralxml = 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 {
4231  $payload = $this->responseSOAP;
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 
4402  public function getHTTPContentTypeCharset()
4403  {
4404  return $this->soap_defencoding;
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  public function addInternalPort(string $serviceName, string $url): void
4597  {
4598  $port = $this->wsdl->ports[$serviceName . 'Port'] ?? [
4599  'binding'=> $serviceName . 'Binding',
4600  'location'=> [],
4601  'bindingType'=>'http://schemas.xmlsoap.org/wsdl/soap/'
4602  ];
4603 
4604  $port['location'] = is_array($port['location']) ? array_merge($port['location'], [$url]) : [$port['location'], $url];
4605 
4606  $this->wsdl->ports[$serviceName . 'Port'] = $port;
4607  }
4608 }
4609 
4614 {
4615 }
4616 
4617 ?><?php
4618 
4619 
4620 
4630 class wsdl extends nusoap_base
4631 {
4632  // URL or filename of the root of this WSDL
4634  public $opStatus;
4636  public $wsdl;
4637  // define internal arrays of bindings, ports, operations, messages, etc.
4638  public $schemas = array();
4640  public $message = array();
4641  public $complexTypes = array();
4642  public $messages = array();
4645  public $portTypes = array();
4647  public $bindings = array();
4649  public $ports = array();
4651  public $opData = array();
4652  public $status = '';
4653  public $documentation = false;
4654  public $endpoint = '';
4655  // array of wsdl docs to import
4656  public $import = array();
4657  // parser vars
4658  public $parser;
4659  public $position = 0;
4660  public $depth = 0;
4661  public $depth_array = array();
4662  // for getting wsdl
4663  public $proxyhost = '';
4664  public $proxyport = '';
4665  public $proxyusername = '';
4666  public $proxypassword = '';
4667  public $timeout = 0;
4668  public $response_timeout = 30;
4669  public $curl_options = array(); // User-specified cURL options
4670  public $use_curl = false; // whether to always try to use cURL
4671  // for HTTP authentication
4672  public $username = ''; // Username for HTTP authentication
4673  public $password = ''; // Password for HTTP authentication
4674  public $authtype = ''; // Type of HTTP authentication
4675  public $certRequest = array(); // Certificate for HTTP SSL authentication
4676 
4691  public function __construct($wsdl = '', $proxyhost=false, $proxyport=false, $proxyusername=false, $proxypassword=false, $timeout=0, $response_timeout=30, $curl_options=null, $use_curl=false)
4692  {
4694  $this->debug("ctor wsdl=$wsdl timeout=$timeout response_timeout=$response_timeout");
4695  $this->proxyhost = $proxyhost;
4696  $this->proxyport = $proxyport;
4697  $this->proxyusername = $proxyusername;
4698  $this->proxypassword = $proxypassword;
4699  $this->timeout = $timeout;
4700  $this->response_timeout = $response_timeout;
4701  if (is_array($curl_options)) {
4702  $this->curl_options = $curl_options;
4703  }
4704  $this->use_curl = $use_curl;
4705  $this->fetchWSDL($wsdl);
4706  }
4707 
4713  public function fetchWSDL($wsdl)
4714  {
4715  $this->debug("parse and process WSDL path=$wsdl");
4716  $this->wsdl = $wsdl;
4717  // parse wsdl file
4718  if ($this->wsdl != "") {
4719  $this->parseWSDL($this->wsdl);
4720  }
4721  // imports
4722  // TODO: handle imports more properly, grabbing them in-line and nesting them
4723  $imported_urls = array();
4724  $imported = 1;
4725  while ($imported > 0) {
4726  $imported = 0;
4727  // Schema imports
4728  foreach ($this->schemas as $ns => $list) {
4729  foreach ($list as $xs) {
4730  $wsdlparts = parse_url($this->wsdl); // this is bogusly simple!
4731  foreach ($xs->imports as $ns2 => $list2) {
4732  for ($ii = 0; $ii < count($list2); $ii++) {
4733  if (! $list2[$ii]['loaded']) {
4734  $this->schemas[$ns]->imports[$ns2][$ii]['loaded'] = true;
4735  $url = $list2[$ii]['location'];
4736  if ($url != '') {
4737  $urlparts = parse_url($url);
4738  if (!isset($urlparts['host'])) {
4739  $url = $wsdlparts['scheme'] . '://' . $wsdlparts['host'] . (isset($wsdlparts['port']) ? ':' . $wsdlparts['port'] : '') .
4740  substr($wsdlparts['path'], 0, strrpos($wsdlparts['path'], '/') + 1) . $urlparts['path'];
4741  }
4742  if (! in_array($url, $imported_urls)) {
4743  $this->parseWSDL($url);
4744  $imported++;
4745  $imported_urls[] = $url;
4746  }
4747  } else {
4748  $this->debug("Unexpected scenario: empty URL for unloaded import");
4749  }
4750  }
4751  }
4752  }
4753  }
4754  }
4755  // WSDL imports
4756  $wsdlparts = parse_url($this->wsdl); // this is bogusly simple!
4757  foreach ($this->import as $ns => $list) {
4758  for ($ii = 0; $ii < count($list); $ii++) {
4759  if (! $list[$ii]['loaded']) {
4760  $this->import[$ns][$ii]['loaded'] = true;
4761  $url = $list[$ii]['location'];
4762  if ($url != '') {
4763  $urlparts = parse_url($url);
4764  if (!isset($urlparts['host'])) {
4765  $url = $wsdlparts['scheme'] . '://' . $wsdlparts['host'] . (isset($wsdlparts['port']) ? ':' . $wsdlparts['port'] : '') .
4766  substr($wsdlparts['path'], 0, strrpos($wsdlparts['path'], '/') + 1) . $urlparts['path'];
4767  }
4768  if (! in_array($url, $imported_urls)) {
4769  $this->parseWSDL($url);
4770  $imported++;
4771  $imported_urls[] = $url;
4772  }
4773  } else {
4774  $this->debug("Unexpected scenario: empty URL for unloaded import");
4775  }
4776  }
4777  }
4778  }
4779  }
4780  // add new data to operation data
4781  foreach ($this->bindings as $binding => $bindingData) {
4782  if (isset($bindingData['operations']) && is_array($bindingData['operations'])) {
4783  foreach ($bindingData['operations'] as $operation => $data) {
4784  $this->debug('post-parse data gathering for ' . $operation);
4785  $this->bindings[$binding]['operations'][$operation]['input'] =
4786  isset($this->bindings[$binding]['operations'][$operation]['input']) ?
4787  array_merge($this->bindings[$binding]['operations'][$operation]['input'], $this->portTypes[ $bindingData['portType'] ][$operation]['input']) :
4788  $this->portTypes[ $bindingData['portType'] ][$operation]['input'];
4789  $this->bindings[$binding]['operations'][$operation]['output'] =
4790  isset($this->bindings[$binding]['operations'][$operation]['output']) ?
4791  array_merge($this->bindings[$binding]['operations'][$operation]['output'], $this->portTypes[ $bindingData['portType'] ][$operation]['output']) :
4792  $this->portTypes[ $bindingData['portType'] ][$operation]['output'];
4793  if (isset($this->messages[ $this->bindings[$binding]['operations'][$operation]['input']['message'] ])) {
4794  $this->bindings[$binding]['operations'][$operation]['input']['parts'] = $this->messages[ $this->bindings[$binding]['operations'][$operation]['input']['message'] ];
4795  }
4796  if (isset($this->messages[ $this->bindings[$binding]['operations'][$operation]['output']['message'] ])) {
4797  $this->bindings[$binding]['operations'][$operation]['output']['parts'] = $this->messages[ $this->bindings[$binding]['operations'][$operation]['output']['message'] ];
4798  }
4799  // Set operation style if necessary, but do not override one already provided
4800  if (isset($bindingData['style']) && !isset($this->bindings[$binding]['operations'][$operation]['style'])) {
4801  $this->bindings[$binding]['operations'][$operation]['style'] = $bindingData['style'];
4802  }
4803  $this->bindings[$binding]['operations'][$operation]['transport'] = isset($bindingData['transport']) ? $bindingData['transport'] : '';
4804  $this->bindings[$binding]['operations'][$operation]['documentation'] = isset($this->portTypes[ $bindingData['portType'] ][$operation]['documentation']) ? $this->portTypes[ $bindingData['portType'] ][$operation]['documentation'] : '';
4805  $this->bindings[$binding]['operations'][$operation]['endpoint'] = isset($bindingData['endpoint']) ? $bindingData['endpoint'] : '';
4806  }
4807  }
4808  }
4809  }
4810 
4817  public function parseWSDL($wsdl = '')
4818  {
4819  $this->debug("parse WSDL at path=$wsdl");
4820 
4821  if ($wsdl == '') {
4822  $this->debug('no wsdl passed to parseWSDL()!!');
4823  $this->setError('no wsdl passed to parseWSDL()!!');
4824  return false;
4825  }
4826 
4827  // parse $wsdl for url format
4828  $wsdl_props = parse_url($wsdl);
4829 
4830  if (isset($wsdl_props['scheme']) && ($wsdl_props['scheme'] == 'http' || $wsdl_props['scheme'] == 'https')) {
4831  $this->debug('getting WSDL http(s) URL ' . $wsdl);
4832  // get wsdl
4833  $tr = new soap_transport_http($wsdl, $this->curl_options, $this->use_curl);
4834  $tr->request_method = 'GET';
4835  $tr->useSOAPAction = false;
4836  if ($this->proxyhost && $this->proxyport) {
4837  $tr->setProxy($this->proxyhost, $this->proxyport, $this->proxyusername, $this->proxypassword);
4838  }
4839  if ($this->authtype != '') {
4840  $tr->setCredentials($this->username, $this->password, $this->authtype, array(), $this->certRequest);
4841  }
4842  $tr->setEncoding('gzip, deflate');
4843  $wsdl_string = $tr->send('', $this->timeout, $this->response_timeout);
4844  //$this->debug("WSDL request\n" . $tr->outgoing_payload);
4845  //$this->debug("WSDL response\n" . $tr->incoming_payload);
4846  $this->appendDebug($tr->getDebug());
4847  // catch errors
4848  if ($err = $tr->getError()) {
4849  $errstr = 'HTTP ERROR: ' . $err;
4850  $this->debug($errstr);
4851  $this->setError($errstr);
4852  unset($tr);
4853  return false;
4854  }
4855  unset($tr);
4856  $this->debug("got WSDL URL");
4857  } else {
4858  // $wsdl is not http(s), so treat it as a file URL or plain file path
4859  if (isset($wsdl_props['scheme']) && ($wsdl_props['scheme'] == 'file') && isset($wsdl_props['path'])) {
4860  $path = isset($wsdl_props['host']) ? ($wsdl_props['host'] . ':' . $wsdl_props['path']) : $wsdl_props['path'];
4861  } else {
4862  $path = $wsdl;
4863  }
4864  $this->debug('getting WSDL file ' . $path);
4865  if ($fp = @fopen($path, 'r')) {
4866  $wsdl_string = '';
4867  while ($data = fread($fp, 32768)) {
4868  $wsdl_string .= $data;
4869  }
4870  fclose($fp);
4871  } else {
4872  $errstr = "Bad path to WSDL file $path";
4873  $this->debug($errstr);
4874  $this->setError($errstr);
4875  return false;
4876  }
4877  }
4878  $this->debug('Parse WSDL');
4879  // end new code added
4880  // Create an XML parser.
4881  $this->parser = xml_parser_create();
4882  // Set the options for parsing the XML data.
4883  // xml_parser_set_option($parser, XML_OPTION_SKIP_WHITE, 1);
4884  xml_parser_set_option($this->parser, XML_OPTION_CASE_FOLDING, 0);
4885  // Set the object for the parser.
4886  xml_set_object($this->parser, $this);
4887  // Set the element handlers for the parser.
4888  xml_set_element_handler($this->parser, 'start_element', 'end_element');
4889  xml_set_character_data_handler($this->parser, 'character_data');
4890  // Parse the XML file.
4891  if (!xml_parse($this->parser, $wsdl_string, true)) {
4892  // Display an error message.
4893  $errstr = sprintf(
4894  'XML error parsing WSDL from %s on line %d: %s',
4895  $wsdl,
4896  xml_get_current_line_number($this->parser),
4897  xml_error_string(xml_get_error_code($this->parser))
4898  );
4899  $this->debug($errstr);
4900  $this->debug("XML payload:\n" . $wsdl_string);
4901  $this->setError($errstr);
4902  return false;
4903  }
4904  // free the parser
4905  xml_parser_free($this->parser);
4906  $this->debug('Parsing WSDL done');
4907  // catch wsdl parse errors
4908  if ($this->getError()) {
4909  return false;
4910  }
4911  return true;
4912  }
4913 
4922  public function start_element($parser, $name, $attrs)
4923  {
4924  if ($this->status == 'schema') {
4925  $this->currentSchema->schemaStartElement($parser, $name, $attrs);
4926  $this->appendDebug($this->currentSchema->getDebug());
4927  $this->currentSchema->clearDebug();
4928  } elseif (preg_match('/schema$/', $name)) {
4929  $this->debug('Parsing WSDL schema');
4930  // $this->debug("startElement for $name ($attrs[name]). status = $this->status (".$this->getLocalPart($name).")");
4931  $this->status = 'schema';
4932  $this->currentSchema = new nusoap_xmlschema('', '', $this->namespaces);
4933  $this->currentSchema->schemaStartElement($parser, $name, $attrs);
4934  $this->appendDebug($this->currentSchema->getDebug());
4935  $this->currentSchema->clearDebug();
4936  } else {
4937  // position in the total number of elements, starting from 0
4938  $pos = $this->position++;
4939  $depth = $this->depth++;
4940  // set self as current value for this depth
4941  $this->depth_array[$depth] = $pos;
4942  $this->message[$pos] = array('cdata' => '');
4943  // process attributes
4944  if (count($attrs) > 0) {
4945  // register namespace declarations
4946  foreach ($attrs as $k => $v) {
4947  if (preg_match('/^xmlns/', $k)) {
4948  if ($ns_prefix = substr(strrchr($k, ':'), 1)) {
4949  $this->namespaces[$ns_prefix] = $v;
4950  } else {
4951  $this->namespaces['ns' . (count($this->namespaces) + 1)] = $v;
4952  }
4953  if ($v == 'http://www.w3.org/2001/XMLSchema' || $v == 'http://www.w3.org/1999/XMLSchema' || $v == 'http://www.w3.org/2000/10/XMLSchema') {
4954  $this->XMLSchemaVersion = $v;
4955  $this->namespaces['xsi'] = $v . '-instance';
4956  }
4957  }
4958  }
4959  // expand each attribute prefix to its namespace
4960  foreach ($attrs as $k => $v) {
4961  $k = strpos($k, ':') ? $this->expandQname($k) : $k;
4962  if ($k != 'location' && $k != 'soapAction' && $k != 'namespace') {
4963  $v = strpos($v, ':') ? $this->expandQname($v) : $v;
4964  }
4965  $eAttrs[$k] = $v;
4966  }
4967  $attrs = $eAttrs;
4968  } else {
4969  $attrs = array();
4970  }
4971  // get element prefix, namespace and name
4972  if (preg_match('/:/', $name)) {
4973  // get ns prefix
4974  $prefix = substr($name, 0, strpos($name, ':'));
4975  // get ns
4976  $namespace = isset($this->namespaces[$prefix]) ? $this->namespaces[$prefix] : '';
4977  // get unqualified name
4978  $name = substr(strstr($name, ':'), 1);
4979  }
4980  // process attributes, expanding any prefixes to namespaces
4981  // find status, register data
4982  switch ($this->status) {
4983  case 'message':
4984  if ($name == 'part') {
4985  if (isset($attrs['type'])) {
4986  $this->debug("msg " . $this->currentMessage . ": found part (with type) $attrs[name]: " . implode(',', $attrs));
4987  $this->messages[$this->currentMessage][$attrs['name']] = $attrs['type'];
4988  }
4989  if (isset($attrs['element'])) {
4990  $this->debug("msg " . $this->currentMessage . ": found part (with element) $attrs[name]: " . implode(',', $attrs));
4991  $this->messages[$this->currentMessage][$attrs['name']] = $attrs['element'] . '^';
4992  }
4993  }
4994  break;
4995  case 'portType':
4996  switch ($name) {
4997  case 'operation':
4998  $this->currentPortOperation = $attrs['name'];
4999  $this->debug("portType $this->currentPortType operation: $this->currentPortOperation");
5000  if (isset($attrs['parameterOrder'])) {
5001  $this->portTypes[$this->currentPortType][$attrs['name']]['parameterOrder'] = $attrs['parameterOrder'];
5002  }
5003  break;
5004  case 'documentation':
5005  $this->documentation = true;
5006  break;
5007  // merge input/output data
5008  default:
5009  $m = isset($attrs['message']) ? $this->getLocalPart($attrs['message']) : '';
5010  $this->portTypes[$this->currentPortType][$this->currentPortOperation][$name]['message'] = $m;
5011  break;
5012  }
5013  break;
5014  case 'binding':
5015  switch ($name) {
5016  case 'binding':
5017  // get ns prefix
5018  if (isset($attrs['style'])) {
5019  $this->bindings[$this->currentBinding]['prefix'] = $prefix;
5020  }
5021  $this->bindings[$this->currentBinding] = array_merge($this->bindings[$this->currentBinding], $attrs);
5022  break;
5023  case 'header':
5024  $this->bindings[$this->currentBinding]['operations'][$this->currentOperation][$this->opStatus]['headers'][] = $attrs;
5025  break;
5026  case 'operation':
5027  if (isset($attrs['soapAction'])) {
5028  $this->bindings[$this->currentBinding]['operations'][$this->currentOperation]['soapAction'] = $attrs['soapAction'];
5029  }
5030  if (isset($attrs['style'])) {
5031  $this->bindings[$this->currentBinding]['operations'][$this->currentOperation]['style'] = $attrs['style'];
5032  }
5033  if (isset($attrs['name'])) {
5034  $this->currentOperation = $attrs['name'];
5035  $this->debug("current binding operation: $this->currentOperation");
5036  $this->bindings[$this->currentBinding]['operations'][$this->currentOperation]['name'] = $attrs['name'];
5037  $this->bindings[$this->currentBinding]['operations'][$this->currentOperation]['binding'] = $this->currentBinding;
5038  $this->bindings[$this->currentBinding]['operations'][$this->currentOperation]['endpoint'] = isset($this->bindings[$this->currentBinding]['endpoint']) ? $this->bindings[$this->currentBinding]['endpoint'] : '';
5039  }
5040  break;
5041  case 'input':
5042  $this->opStatus = 'input';
5043  break;
5044  case 'output':
5045  $this->opStatus = 'output';
5046  break;
5047  case 'body':
5048  if (isset($this->bindings[$this->currentBinding]['operations'][$this->currentOperation][$this->opStatus])) {
5049  $this->bindings[$this->currentBinding]['operations'][$this->currentOperation][$this->opStatus] = array_merge($this->bindings[$this->currentBinding]['operations'][$this->currentOperation][$this->opStatus], $attrs);
5050  } else {
5051  $this->bindings[$this->currentBinding]['operations'][$this->currentOperation][$this->opStatus] = $attrs;
5052  }
5053  break;
5054  }
5055  break;
5056  case 'service':
5057  switch ($name) {
5058  case 'port':
5059  $this->currentPort = $attrs['name'];
5060  $this->debug('current port: ' . $this->currentPort);
5061  $this->ports[$this->currentPort]['binding'] = $this->getLocalPart($attrs['binding']);
5062 
5063  break;
5064  case 'address':
5065  $this->ports[$this->currentPort]['location'] = $attrs['location'];
5066  $this->ports[$this->currentPort]['bindingType'] = $namespace;
5067  $this->bindings[ $this->ports[$this->currentPort]['binding'] ]['bindingType'] = $namespace;
5068  $this->bindings[ $this->ports[$this->currentPort]['binding'] ]['endpoint'] = $attrs['location'];
5069  break;
5070  }
5071  break;
5072  }
5073  // set status
5074  switch ($name) {
5075  case 'import':
5076  if (isset($attrs['location'])) {
5077  $this->import[$attrs['namespace']][] = array('location' => $attrs['location'], 'loaded' => false);
5078  $this->debug('parsing import ' . $attrs['namespace'] . ' - ' . $attrs['location'] . ' (' . count($this->import[$attrs['namespace']]) . ')');
5079  } else {
5080  $this->import[$attrs['namespace']][] = array('location' => '', 'loaded' => true);
5081  if (! $this->getPrefixFromNamespace($attrs['namespace'])) {
5082  $this->namespaces['ns' . (count($this->namespaces)+1)] = $attrs['namespace'];
5083  }
5084  $this->debug('parsing import ' . $attrs['namespace'] . ' - [no location] (' . count($this->import[$attrs['namespace']]) . ')');
5085  }
5086  break;
5087  //wait for schema
5088  //case 'types':
5089  // $this->status = 'schema';
5090  // break;
5091  case 'message':
5092  $this->status = 'message';
5093  $this->messages[$attrs['name']] = array();
5094  $this->currentMessage = $attrs['name'];
5095  break;
5096  case 'portType':
5097  $this->status = 'portType';
5098  $this->portTypes[$attrs['name']] = array();
5099  $this->currentPortType = $attrs['name'];
5100  break;
5101  case "binding":
5102  if (isset($attrs['name'])) {
5103  // get binding name
5104  if (strpos($attrs['name'], ':')) {
5105  $this->currentBinding = $this->getLocalPart($attrs['name']);
5106  } else {
5107  $this->currentBinding = $attrs['name'];
5108  }
5109  $this->status = 'binding';
5110  $this->bindings[$this->currentBinding]['portType'] = $this->getLocalPart($attrs['type']);
5111  $this->debug("current binding: $this->currentBinding of portType: " . $attrs['type']);
5112  }
5113  break;
5114  case 'service':
5115  $this->serviceName = $attrs['name'];
5116  $this->status = 'service';
5117  $this->debug('current service: ' . $this->serviceName);
5118  break;
5119  case 'definitions':
5120  foreach ($attrs as $name => $value) {
5121  $this->wsdl_info[$name] = $value;
5122  }
5123  break;
5124  }
5125  }
5126  }
5127 
5135  public function end_element($parser, $name)
5136  {
5137  // unset schema status
5138  if (/*preg_match('/types$/', $name) ||*/ preg_match('/schema$/', $name)) {
5139  $this->status = "";
5140  $this->appendDebug($this->currentSchema->getDebug());
5141  $this->currentSchema->clearDebug();
5142  $this->schemas[$this->currentSchema->schemaTargetNamespace][] = $this->currentSchema;
5143  $this->debug('Parsing WSDL schema done');
5144  }
5145  if ($this->status == 'schema') {
5146  $this->currentSchema->schemaEndElement($parser, $name);
5147  } else {
5148  // bring depth down a notch
5149  $this->depth--;
5150  }
5151  // end documentation
5152  if ($this->documentation) {
5153  //TODO: track the node to which documentation should be assigned; it can be a part, message, etc.
5154  //$this->portTypes[$this->currentPortType][$this->currentPortOperation]['documentation'] = $this->documentation;
5155  $this->documentation = false;
5156  }
5157  }
5158 
5166  public function character_data($parser, $data)
5167  {
5168  $pos = isset($this->depth_array[$this->depth]) ? $this->depth_array[$this->depth] : 0;
5169  if (isset($this->message[$pos]['cdata'])) {
5170  $this->message[$pos]['cdata'] .= $data;
5171  }
5172  if ($this->documentation) {
5173  $this->documentation .= $data;
5174  }
5175  }
5176 
5186  public function setCredentials($username, $password, $authtype = 'basic', $certRequest = array())
5187  {
5188  $this->debug("setCredentials username=$username authtype=$authtype certRequest=");
5189  $this->appendDebug($this->varDump($certRequest));
5190  $this->username = $username;
5191  $this->password = $password;
5192  $this->authtype = $authtype;
5193  $this->certRequest = $certRequest;
5194  }
5195 
5196  public function getBindingData($binding)
5197  {
5198  if (is_array($this->bindings[$binding])) {
5199  return $this->bindings[$binding];
5200  }
5201  }
5202 
5210  public function getOperations($bindingType = 'soap')
5211  {
5212  $ops = array();
5213  if ($bindingType == 'soap') {
5214  $bindingType = 'http://schemas.xmlsoap.org/wsdl/soap/';
5215  } elseif ($bindingType == 'soap12') {
5216  $bindingType = 'http://schemas.xmlsoap.org/wsdl/soap12/';
5217  }
5218  // loop thru ports
5219  foreach ($this->ports as $port => $portData) {
5220  // binding type of port matches parameter
5221  if ($portData['bindingType'] == $bindingType) {
5222  //$this->debug("getOperations for port $port");
5223  //$this->debug("port data: " . $this->varDump($portData));
5224  //$this->debug("bindings: " . $this->varDump($this->bindings[ $portData['binding'] ]));
5225  // merge bindings
5226  if (isset($this->bindings[ $portData['binding'] ]['operations'])) {
5227  $ops = array_merge($ops, $this->bindings[ $portData['binding'] ]['operations']);
5228  }
5229  }
5230  }
5231  return $ops;
5232  }
5233 
5242  public function getOperationData($operation, $bindingType = 'soap')
5243  {
5244  if ($bindingType == 'soap') {
5245  $bindingType = 'http://schemas.xmlsoap.org/wsdl/soap/';
5246  } elseif ($bindingType == 'soap12') {
5247  $bindingType = 'http://schemas.xmlsoap.org/wsdl/soap12/';
5248  }
5249  // loop thru ports
5250  foreach ($this->ports as $port => $portData) {
5251  // binding type of port matches parameter
5252  if ($portData['bindingType'] == $bindingType) {
5253  // get binding
5254  //foreach($this->bindings[ $portData['binding'] ]['operations'] as $bOperation => $opData) {
5255  foreach (array_keys($this->bindings[ $portData['binding'] ]['operations']) as $bOperation) {
5256  // note that we could/should also check the namespace here
5257  if ($operation == $bOperation) {
5258  $opData = $this->bindings[ $portData['binding'] ]['operations'][$operation];
5259  return $opData;
5260  }
5261  }
5262  }
5263  }
5264  }
5265 
5274  public function getOperationDataForSoapAction($soapAction, $bindingType = 'soap')
5275  {
5276  if ($bindingType == 'soap') {
5277  $bindingType = 'http://schemas.xmlsoap.org/wsdl/soap/';
5278  } elseif ($bindingType == 'soap12') {
5279  $bindingType = 'http://schemas.xmlsoap.org/wsdl/soap12/';
5280  }
5281  // loop thru ports
5282  foreach ($this->ports as $port => $portData) {
5283  // binding type of port matches parameter
5284  if ($portData['bindingType'] == $bindingType) {
5285  // loop through operations for the binding
5286  foreach ($this->bindings[ $portData['binding'] ]['operations'] as $bOperation => $opData) {
5287  if ($opData['soapAction'] == $soapAction) {
5288  return $opData;
5289  }
5290  }
5291  }
5292  }
5293  }
5294 
5313  public function getTypeDef($type, $ns)
5314  {
5315  $this->debug("in getTypeDef: type=$type, ns=$ns");
5316  if ((! $ns) && isset($this->namespaces['tns'])) {
5317  $ns = $this->namespaces['tns'];
5318  $this->debug("in getTypeDef: type namespace forced to $ns");
5319  }
5320  if (!isset($this->schemas[$ns])) {
5321  foreach ($this->schemas as $ns0 => $schema0) {
5322  if (strcasecmp($ns, $ns0) == 0) {
5323  $this->debug("in getTypeDef: replacing schema namespace $ns with $ns0");
5324  $ns = $ns0;
5325  break;
5326  }
5327  }
5328  }
5329  if (isset($this->schemas[$ns])) {
5330  $this->debug("in getTypeDef: have schema for namespace $ns");
5331  for ($i = 0; $i < count($this->schemas[$ns]); $i++) {
5332  $xs = &$this->schemas[$ns][$i];
5333  $t = $xs->getTypeDef($type);
5334  //$this->appendDebug($xs->getDebug());
5335  //$xs->clearDebug();
5336  if ($t) {
5337  if (!isset($t['phpType'])) {
5338  // get info for type to tack onto the element
5339  $uqType = substr($t['type'], strrpos($t['type'], ':') + 1);
5340  $ns = substr($t['type'], 0, strrpos($t['type'], ':'));
5341  $etype = $this->getTypeDef($uqType, $ns);
5342  if ($etype) {
5343  $this->debug("found type for [element] $type:");
5344  $this->debug($this->varDump($etype));
5345  if (isset($etype['phpType'])) {
5346  $t['phpType'] = $etype['phpType'];
5347  }
5348  if (isset($etype['elements'])) {
5349  $t['elements'] = $etype['elements'];
5350  }
5351  if (isset($etype['attrs'])) {
5352  $t['attrs'] = $etype['attrs'];
5353  }
5354  }
5355  }
5356  return $t;
5357  }
5358  }
5359  } else {
5360  $this->debug("in getTypeDef: do not have schema for namespace $ns");
5361  }
5362  return false;
5363  }
5364 
5370  public function webDescription()
5371  {
5372  global $HTTP_SERVER_VARS;
5373 
5374  if (isset($_SERVER)) {
5375  $PHP_SELF = $_SERVER['PHP_SELF'];
5376  } elseif (isset($HTTP_SERVER_VARS)) {
5377  $PHP_SELF = $HTTP_SERVER_VARS['PHP_SELF'];
5378  } else {
5379  $this->setError("Neither _SERVER nor HTTP_SERVER_VARS is available");
5380  }
5381  // begin-patch: https://mantis.ilias.de/view.php?id=28866
5382  $PHP_SELF = htmlspecialchars($PHP_SELF, ENT_QUOTES | ENT_HTML5, 'UTF-8');
5383  // end-patch
5384 
5385  $b = '
5386  <html><head><title>NuSOAP: ' . $this->serviceName . '</title>
5387  <style type="text/css">
5388  body { font-family: arial; color: #000000; background-color: #ffffff; margin: 0px 0px 0px 0px; }
5389  p { font-family: arial; color: #000000; margin-top: 0px; margin-bottom: 12px; }
5390  pre { background-color: silver; padding: 5px; font-family: Courier New; font-size: x-small; color: #000000;}
5391  ul { margin-top: 10px; margin-left: 20px; }
5392  li { list-style-type: none; margin-top: 10px; color: #000000; }
5393  .content{
5394  margin-left: 0px; padding-bottom: 2em; }
5395  .nav {
5396  padding-top: 10px; padding-bottom: 10px; padding-left: 15px; font-size: .70em;
5397  margin-top: 10px; margin-left: 0px; color: #000000;
5398  background-color: #ccccff; width: 20%; margin-left: 20px; margin-top: 20px; }
5399  .title {
5400  font-family: arial; font-size: 26px; color: #ffffff;
5401  background-color: #999999; width: 105%; margin-left: 0px;
5402  padding-top: 10px; padding-bottom: 10px; padding-left: 15px;}
5403  .hidden {
5404  position: absolute; visibility: hidden; z-index: 200; left: 250px; top: 100px;
5405  font-family: arial; overflow: hidden; width: 600;
5406  padding: 20px; font-size: 10px; background-color: #999999;
5407  layer-background-color:#FFFFFF; }
5408  a,a:active { color: charcoal; font-weight: bold; }
5409  a:visited { color: #666666; font-weight: bold; }
5410  a:hover { color: cc3300; font-weight: bold; }
5411  </style>
5412  <script language="JavaScript" type="text/javascript">
5413  <!--
5414  // POP-UP CAPTIONS...
5415  function lib_bwcheck(){ //Browsercheck (needed)
5416  this.ver=navigator.appVersion
5417  this.agent=navigator.userAgent
5418  this.dom=document.getElementById?1:0
5419  this.opera5=this.agent.indexOf("Opera 5")>-1
5420  this.ie5=(this.ver.indexOf("MSIE 5")>-1 && this.dom && !this.opera5)?1:0;
5421  this.ie6=(this.ver.indexOf("MSIE 6")>-1 && this.dom && !this.opera5)?1:0;
5422  this.ie4=(document.all && !this.dom && !this.opera5)?1:0;
5423  this.ie=this.ie4||this.ie5||this.ie6
5424  this.mac=this.agent.indexOf("Mac")>-1
5425  this.ns6=(this.dom && parseInt(this.ver) >= 5) ?1:0;
5426  this.ns4=(document.layers && !this.dom)?1:0;
5427  this.bw=(this.ie6 || this.ie5 || this.ie4 || this.ns4 || this.ns6 || this.opera5)
5428  return this
5429  }
5430  var bw = new lib_bwcheck()
5431  //Makes crossbrowser object.
5432  function makeObj(obj){
5433  this.evnt=bw.dom? document.getElementById(obj):bw.ie4?document.all[obj]:bw.ns4?document.layers[obj]:0;
5434  if(!this.evnt) return false
5435  this.css=bw.dom||bw.ie4?this.evnt.style:bw.ns4?this.evnt:0;
5436  this.wref=bw.dom||bw.ie4?this.evnt:bw.ns4?this.css.document:0;
5437  this.writeIt=b_writeIt;
5438  return this
5439  }
5440  // A unit of measure that will be added when setting the position of a layer.
5441  //var px = bw.ns4||window.opera?"":"px";
5442  function b_writeIt(text){
5443  if (bw.ns4){this.wref.write(text);this.wref.close()}
5444  else this.wref.innerHTML = text
5445  }
5446  //Shows the messages
5447  var oDesc;
5448  function popup(divid){
5449  if(oDesc = new makeObj(divid)){
5450  oDesc.css.visibility = "visible"
5451  }
5452  }
5453  function popout(){ // Hides message
5454  if(oDesc) oDesc.css.visibility = "hidden"
5455  }
5456  //-->
5457  </script>
5458  </head>
5459  <body>
5460  <div class=content>
5461  <br><br>
5462  <div class=title>' . $this->serviceName . '</div>
5463  <div class=nav>
5464  <p>View the <a href="' . $PHP_SELF . '?wsdl">WSDL</a> for the service.
5465  Click on an operation name to view it&apos;s details.</p>
5466  <ul>';
5467  foreach ($this->getOperations() as $op => $data) {
5468  // begin-patch: https://mantis.ilias.de/view.php?id=28866
5469  if (isset($data['endpoint'])) {
5470  $data['endpoint'] = htmlspecialchars($data['endpoint'], ENT_QUOTES | ENT_HTML5, 'UTF-8');
5471  }
5472  // end-patch
5473  $b .= "<li><a href='#' onclick=\"popout();popup('$op')\">$op</a></li>";
5474  // create hidden div
5475  $b .= "<div id='$op' class='hidden'>
5476  <a href='#' onclick='popout()'><font color='#ffffff'>Close</font></a><br><br>";
5477  foreach ($data as $donnie => $marie) { // loop through opdata
5478  if ($donnie == 'input' || $donnie == 'output') { // show input/output data
5479  $b .= "<font color='white'>" . ucfirst($donnie) . ':</font><br>';
5480  foreach ($marie as $captain => $tenille) { // loop through data
5481  if ($captain == 'parts') { // loop thru parts
5482  $b .= "&nbsp;&nbsp;$captain:<br>";
5483  //if(is_array($tenille)){
5484  foreach ($tenille as $joanie => $chachi) {
5485  $b .= "&nbsp;&nbsp;&nbsp;&nbsp;$joanie: $chachi<br>";
5486  }
5487  //}
5488  } else {
5489  $b .= "&nbsp;&nbsp;$captain: $tenille<br>";
5490  }
5491  }
5492  } else {
5493  $b .= "<font color='white'>" . ucfirst($donnie) . ":</font> $marie<br>";
5494  }
5495  }
5496  $b .= '</div>';
5497  }
5498  $b .= '
5499  <ul>
5500  </div>
5501  </div></body></html>';
5502  return $b;
5503  }
5504 
5512  public function serialize($debug = 0)
5513  {
5514  $xml = '<?xml version="1.0" encoding="ISO-8859-1"?>';
5515  $xml .= "\n<definitions";
5516  foreach ($this->namespaces as $k => $v) {
5517  $xml .= " xmlns:$k=\"$v\"";
5518  }
5519  // 10.9.02 - add poulter fix for wsdl and tns declarations
5520  if (isset($this->namespaces['wsdl'])) {
5521  $xml .= " xmlns=\"" . $this->namespaces['wsdl'] . "\"";
5522  }
5523  if (isset($this->namespaces['tns'])) {
5524  $xml .= " targetNamespace=\"" . $this->namespaces['tns'] . "\"";
5525  }
5526  $xml .= '>';
5527  // imports
5528  if (sizeof($this->import) > 0) {
5529  foreach ($this->import as $ns => $list) {
5530  foreach ($list as $ii) {
5531  if ($ii['location'] != '') {
5532  $xml .= '<import location="' . $ii['location'] . '" namespace="' . $ns . '" />';
5533  } else {
5534  $xml .= '<import namespace="' . $ns . '" />';
5535  }
5536  }
5537  }
5538  }
5539  // types
5540  if (count($this->schemas)>=1) {
5541  $xml .= "\n<types>\n";
5542  foreach ($this->schemas as $ns => $list) {
5543  foreach ($list as $xs) {
5544  $xml .= $xs->serializeSchema();
5545  }
5546  }
5547  $xml .= '</types>';
5548  }
5549  // messages
5550  if (count($this->messages) >= 1) {
5551  foreach ($this->messages as $msgName => $msgParts) {
5552  $xml .= "\n<message name=\"" . $msgName . '">';
5553  if (is_array($msgParts)) {
5554  foreach ($msgParts as $partName => $partType) {
5555  // print 'serializing '.$partType.', sv: '.$this->XMLSchemaVersion.'<br>';
5556  if (strpos($partType, ':')) {
5557  $typePrefix = $this->getPrefixFromNamespace($this->getPrefix($partType));
5558  } elseif (isset($this->typemap[$this->namespaces['xsd']][$partType])) {
5559  // print 'checking typemap: '.$this->XMLSchemaVersion.'<br>';
5560  $typePrefix = 'xsd';
5561  } else {
5562  foreach ($this->typemap as $ns => $types) {
5563  if (isset($types[$partType])) {
5564  $typePrefix = $this->getPrefixFromNamespace($ns);
5565  }
5566  }
5567  if (!isset($typePrefix)) {
5568  die("$partType has no namespace!");
5569  }
5570  }
5571  $ns = $this->getNamespaceFromPrefix($typePrefix);
5572  $localPart = $this->getLocalPart($partType);
5573  $typeDef = $this->getTypeDef($localPart, $ns);
5574  if (($typeDef['typeClass'] ?? '') == 'element') {
5575  $elementortype = 'element';
5576  if (substr($localPart, -1) == '^') {
5577  $localPart = substr($localPart, 0, -1);
5578  }
5579  } else {
5580  $elementortype = 'type';
5581  }
5582  $xml .= "\n" . ' <part name="' . $partName . '" ' . $elementortype . '="' . $typePrefix . ':' . $localPart . '" />';
5583  }
5584  }
5585  $xml .= '</message>';
5586  }
5587  }
5588  // bindings & porttypes
5589  if (count($this->bindings) >= 1) {
5590  $binding_xml = '';
5591  $portType_xml = '';
5592  foreach ($this->bindings as $bindingName => $attrs) {
5593  $binding_xml .= "\n<binding name=\"" . $bindingName . '" type="tns:' . $attrs['portType'] . '">';
5594  $binding_xml .= "\n" . ' <soap:binding style="' . $attrs['style'] . '" transport="' . $attrs['transport'] . '"/>';
5595  $portType_xml .= "\n<portType name=\"" . $attrs['portType'] . '">';
5596  foreach ($attrs['operations'] as $opName => $opParts) {
5597  $binding_xml .= "\n" . ' <operation name="' . $opName . '">';
5598  $binding_xml .= "\n" . ' <soap:operation soapAction="' . $opParts['soapAction'] . '" style="' . $opParts['style'] . '"/>';
5599  if (isset($opParts['input']['encodingStyle']) && $opParts['input']['encodingStyle'] != '') {
5600  $enc_style = ' encodingStyle="' . $opParts['input']['encodingStyle'] . '"';
5601  } else {
5602  $enc_style = '';
5603  }
5604  $binding_xml .= "\n" . ' <input><soap:body use="' . $opParts['input']['use'] . '" namespace="' . $opParts['input']['namespace'] . '"' . $enc_style . '/></input>';
5605  if (isset($opParts['output']['encodingStyle']) && $opParts['output']['encodingStyle'] != '') {
5606  $enc_style = ' encodingStyle="' . $opParts['output']['encodingStyle'] . '"';
5607  } else {
5608  $enc_style = '';
5609  }
5610  $binding_xml .= "\n" . ' <output><soap:body use="' . $opParts['output']['use'] . '" namespace="' . $opParts['output']['namespace'] . '"' . $enc_style . '/></output>';
5611  $binding_xml .= "\n" . ' </operation>';
5612  $portType_xml .= "\n" . ' <operation name="' . $opParts['name'] . '"';
5613  if (isset($opParts['parameterOrder'])) {
5614  $portType_xml .= ' parameterOrder="' . $opParts['parameterOrder'] . '"';
5615  }
5616  $portType_xml .= '>';
5617  if (isset($opParts['documentation']) && $opParts['documentation'] != '') {
5618  $portType_xml .= "\n" . ' <documentation>' . htmlspecialchars($opParts['documentation']) . '</documentation>';
5619  }
5620  $portType_xml .= "\n" . ' <input message="tns:' . $opParts['input']['message'] . '"/>';
5621  $portType_xml .= "\n" . ' <output message="tns:' . $opParts['output']['message'] . '"/>';
5622  $portType_xml .= "\n" . ' </operation>';
5623  }
5624  $portType_xml .= "\n" . '</portType>';
5625  $binding_xml .= "\n" . '</binding>';
5626  }
5627  $xml .= $portType_xml . $binding_xml;
5628  }
5629  // services
5630  $xml .= "\n<service name=\"" . $this->serviceName . '">';
5631  $has_client = isset($_GET['client_id']);
5632  if (count($this->ports) >= 1) {
5633  foreach ($this->ports as $pName => $attrs) {
5634  $xml .= "\n" . ' <port name="' . $pName . '" binding="tns:' . $attrs['binding'] . '">';
5635  $locations = $attrs['location'];
5636  $locations = is_array($locations) ? $locations : [$locations];
5637  foreach ($locations as $location) {
5638  $address = $location . ($debug || $has_client ? "?" : "")
5639  . ($debug ? 'debug=1' : '') . ($debug && $has_client ? "&amp;" : "")
5640  . ($has_client ? 'client_id=' . $_GET['client_id'] : '');
5641  $xml .= "\n" . ' <soap:address location="' . $address . '"/>';
5642  }
5643  $xml .= "\n" . ' </port>';
5644  }
5645  }
5646 
5647  $xml .= "\n" . '</service>';
5648  return $xml . "\n</definitions>";
5649  }
5650 
5660  public function parametersMatchWrapped($type, &$parameters)
5661  {
5662  $this->debug("in parametersMatchWrapped type=$type, parameters=");
5663  $this->appendDebug($this->varDump($parameters));
5664 
5665  // split type into namespace:unqualified-type
5666  if (strpos($type, ':')) {
5667  $uqType = substr($type, strrpos($type, ':') + 1);
5668  $ns = substr($type, 0, strrpos($type, ':'));
5669  $this->debug("in parametersMatchWrapped: got a prefixed type: $uqType, $ns");
5670  if ($this->getNamespaceFromPrefix($ns)) {
5671  $ns = $this->getNamespaceFromPrefix($ns);
5672  $this->debug("in parametersMatchWrapped: expanded prefixed type: $uqType, $ns");
5673  }
5674  } else {
5675  // TODO: should the type be compared to types in XSD, and the namespace
5676  // set to XSD if the type matches?
5677  $this->debug("in parametersMatchWrapped: No namespace for type $type");
5678  $ns = '';
5679  $uqType = $type;
5680  }
5681 
5682  // get the type information
5683  if (!$typeDef = $this->getTypeDef($uqType, $ns)) {
5684  $this->debug("in parametersMatchWrapped: $type ($uqType) is not a supported type.");
5685  return false;
5686  }
5687  $this->debug("in parametersMatchWrapped: found typeDef=");
5688  $this->appendDebug($this->varDump($typeDef));
5689  if (substr($uqType, -1) == '^') {
5690  $uqType = substr($uqType, 0, -1);
5691  }
5692  $phpType = $typeDef['phpType'];
5693  $arrayType = (isset($typeDef['arrayType']) ? $typeDef['arrayType'] : '');
5694  $this->debug("in parametersMatchWrapped: uqType: $uqType, ns: $ns, phptype: $phpType, arrayType: $arrayType");
5695 
5696  // we expect a complexType or element of complexType
5697  if ($phpType != 'struct') {
5698  $this->debug("in parametersMatchWrapped: not a struct");
5699  return false;
5700  }
5701 
5702  // see whether the parameter names match the elements
5703  if (isset($typeDef['elements']) && is_array($typeDef['elements'])) {
5704  $elements = 0;
5705  $matches = 0;
5706  $change = false;
5707  if ($this->isArraySimpleOrStruct($parameters) == 'arraySimple' && count($parameters) == count($typeDef['elements'])) {
5708  $this->debug("in parametersMatchWrapped: (wrapped return value kludge) correct number of elements in simple array, so change array and wrap");
5709  $change = true;
5710  }
5711  foreach ($typeDef['elements'] as $name => $attrs) {
5712  if ($change) {
5713  $this->debug("in parametersMatchWrapped: change parameter $element to name $name");
5714  $parameters[$name] = $parameters[$elements];
5715  unset($parameters[$elements]);
5716  $matches++;
5717  } elseif (isset($parameters[$name])) {
5718  $this->debug("in parametersMatchWrapped: have parameter named $name");
5719  $matches++;
5720  } else {
5721  $this->debug("in parametersMatchWrapped: do not have parameter named $name");
5722  }
5723  $elements++;
5724  }
5725 
5726  $this->debug("in parametersMatchWrapped: $matches parameter names match $elements wrapped parameter names");
5727  if ($matches == 0) {
5728  return false;
5729  }
5730  return true;
5731  }
5732 
5733  // since there are no elements for the type, if the user passed no
5734  // parameters, the parameters match wrapped.
5735  $this->debug("in parametersMatchWrapped: no elements type $ns:$uqType");
5736  return count($parameters) == 0;
5737  }
5738 
5754  public function serializeRPCParameters($operation, $direction, $parameters, $bindingType = 'soap')
5755  {
5756  $this->debug("in serializeRPCParameters: operation=$operation, direction=$direction, XMLSchemaVersion=$this->XMLSchemaVersion, bindingType=$bindingType");
5757  $this->appendDebug('parameters=' . $this->varDump($parameters));
5758 
5759  if ($direction != 'input' && $direction != 'output') {
5760  $this->debug('The value of the \$direction argument needs to be either "input" or "output"');
5761  $this->setError('The value of the \$direction argument needs to be either "input" or "output"');
5762  return false;
5763  }
5764  if (!$opData = $this->getOperationData($operation, $bindingType)) {
5765  $this->debug('Unable to retrieve WSDL data for operation: ' . $operation . ' bindingType: ' . $bindingType);
5766  $this->setError('Unable to retrieve WSDL data for operation: ' . $operation . ' bindingType: ' . $bindingType);
5767  return false;
5768  }
5769  $this->debug('in serializeRPCParameters: opData:');
5770  $this->appendDebug($this->varDump($opData));
5771 
5772  // Get encoding style for output and set to current
5773  $encodingStyle = 'http://schemas.xmlsoap.org/soap/encoding/';
5774  if (($direction == 'input') && isset($opData['output']['encodingStyle']) && ($opData['output']['encodingStyle'] != $encodingStyle)) {
5775  $encodingStyle = $opData['output']['encodingStyle'];
5776  $enc_style = $encodingStyle;
5777  }
5778 
5779  // set input params
5780  $xml = '';
5781  if (isset($opData[$direction]['parts']) && sizeof($opData[$direction]['parts']) > 0) {
5782  $parts = &$opData[$direction]['parts'];
5783  $part_count = sizeof($parts);
5784  $style = $opData['style'];
5785  $use = $opData[$direction]['use'];
5786  $this->debug("have $part_count part(s) to serialize using $style/$use");
5787  if (is_array($parameters)) {
5788  $parametersArrayType = $this->isArraySimpleOrStruct($parameters);
5789  $parameter_count = count($parameters);
5790  $this->debug("have $parameter_count parameter(s) provided as $parametersArrayType to serialize");
5791  // check for Microsoft-style wrapped parameters
5792  if ($style == 'document' && $use == 'literal' && $part_count == 1 && isset($parts['parameters'])) {
5793  $this->debug('check whether the caller has wrapped the parameters');
5794  if ((($parametersArrayType == 'arrayStruct' || $parameter_count == 0) && !isset($parameters['parameters'])) || ($direction == 'output' && $parametersArrayType == 'arraySimple' && $parameter_count == 1)) {
5795  $this->debug('check whether caller\'s parameters match the wrapped ones');
5796  if ($this->parametersMatchWrapped($parts['parameters'], $parameters)) {
5797  $this->debug('wrap the parameters for the caller');
5798  $parameters = array('parameters' => $parameters);
5799  $parameter_count = 1;
5800  }
5801  }
5802  }
5803  foreach ($parts as $name => $type) {
5804  $this->debug("serializing part $name of type $type");
5805  // Track encoding style
5806  if (isset($opData[$direction]['encodingStyle']) && $encodingStyle != $opData[$direction]['encodingStyle']) {
5807  $encodingStyle = $opData[$direction]['encodingStyle'];
5808  $enc_style = $encodingStyle;
5809  } else {
5810  $enc_style = false;
5811  }
5812  // NOTE: add error handling here
5813  // if serializeType returns false, then catch global error and fault
5814  if ($parametersArrayType == 'arraySimple') {
5815  $p = array_shift($parameters);
5816  $this->debug('calling serializeType w/indexed param');
5817  $xml .= $this->serializeType($name, $type, $p, $use, $enc_style);
5818  } elseif (isset($parameters[$name])) {
5819  $this->debug('calling serializeType w/named param');
5820  $xml .= $this->serializeType($name, $type, $parameters[$name], $use, $enc_style);
5821  } else {
5822  // TODO: only send nillable
5823  $this->debug('calling serializeType w/null param');
5824  $xml .= $this->serializeType($name, $type, null, $use, $enc_style);
5825  }
5826  }
5827  } else {
5828  $this->debug('no parameters passed.');
5829  }
5830  }
5831  $this->debug("serializeRPCParameters returning: $xml");
5832  return $xml;
5833  }
5834 
5849  public function serializeParameters($operation, $direction, $parameters)
5850  {
5851  $this->debug("in serializeParameters: operation=$operation, direction=$direction, XMLSchemaVersion=$this->XMLSchemaVersion");
5852  $this->appendDebug('parameters=' . $this->varDump($parameters));
5853 
5854  if ($direction != 'input' && $direction != 'output') {
5855  $this->debug('The value of the \$direction argument needs to be either "input" or "output"');
5856  $this->setError('The value of the \$direction argument needs to be either "input" or "output"');
5857  return false;
5858  }
5859  if (!$opData = $this->getOperationData($operation)) {
5860  $this->debug('Unable to retrieve WSDL data for operation: ' . $operation);
5861  $this->setError('Unable to retrieve WSDL data for operation: ' . $operation);
5862  return false;
5863  }
5864  $this->debug('opData:');
5865  $this->appendDebug($this->varDump($opData));
5866 
5867  // Get encoding style for output and set to current
5868  $encodingStyle = 'http://schemas.xmlsoap.org/soap/encoding/';
5869  if (($direction == 'input') && isset($opData['output']['encodingStyle']) && ($opData['output']['encodingStyle'] != $encodingStyle)) {
5870  $encodingStyle = $opData['output']['encodingStyle'];
5871  $enc_style = $encodingStyle;
5872  }
5873 
5874  // set input params
5875  $xml = '';
5876  if (isset($opData[$direction]['parts']) && sizeof($opData[$direction]['parts']) > 0) {
5877  $use = $opData[$direction]['use'];
5878  $this->debug("use=$use");
5879  $this->debug('got ' . count($opData[$direction]['parts']) . ' part(s)');
5880  if (is_array($parameters)) {
5881  $parametersArrayType = $this->isArraySimpleOrStruct($parameters);
5882  $this->debug('have ' . $parametersArrayType . ' parameters');
5883  foreach ($opData[$direction]['parts'] as $name => $type) {
5884  $this->debug('serializing part "' . $name . '" of type "' . $type . '"');
5885  // Track encoding style
5886  if (isset($opData[$direction]['encodingStyle']) && $encodingStyle != $opData[$direction]['encodingStyle']) {
5887  $encodingStyle = $opData[$direction]['encodingStyle'];
5888  $enc_style = $encodingStyle;
5889  } else {
5890  $enc_style = false;
5891  }
5892  // NOTE: add error handling here
5893  // if serializeType returns false, then catch global error and fault
5894  if ($parametersArrayType == 'arraySimple') {
5895  $p = array_shift($parameters);
5896  $this->debug('calling serializeType w/indexed param');
5897  $xml .= $this->serializeType($name, $type, $p, $use, $enc_style);
5898  } elseif (isset($parameters[$name])) {
5899  $this->debug('calling serializeType w/named param');
5900  $xml .= $this->serializeType($name, $type, $parameters[$name], $use, $enc_style);
5901  } else {
5902  // TODO: only send nillable
5903  $this->debug('calling serializeType w/null param');
5904  $xml .= $this->serializeType($name, $type, null, $use, $enc_style);
5905  }
5906  }
5907  } else {
5908  $this->debug('no parameters passed.');
5909  }
5910  }
5911  $this->debug("serializeParameters returning: $xml");
5912  return $xml;
5913  }
5914 
5927  public function serializeType($name, $type, $value, $use='encoded', $encodingStyle=false, $unqualified=false)
5928  {
5929  $this->debug("in serializeType: name=$name, type=$type, use=$use, encodingStyle=$encodingStyle, unqualified=" . ($unqualified ? "unqualified" : "qualified"));
5930  $this->appendDebug("value=" . $this->varDump($value));
5931  if ($use == 'encoded' && $encodingStyle) {
5932  $encodingStyle = ' SOAP-ENV:encodingStyle="' . $encodingStyle . '"';
5933  }
5934 
5935  // if a soapval has been supplied, let its type override the WSDL
5936  if (is_object($value) && get_class($value) == 'soapval') {
5937  if ($value->type_ns) {
5938  $type = $value->type_ns . ':' . $value->type;
5939  $forceType = true;
5940  $this->debug("in serializeType: soapval overrides type to $type");
5941  } elseif ($value->type) {
5942  $type = $value->type;
5943  $forceType = true;
5944  $this->debug("in serializeType: soapval overrides type to $type");
5945  } else {
5946  $forceType = false;
5947  $this->debug("in serializeType: soapval does not override type");
5948  }
5949  $attrs = $value->attributes;
5950  $value = $value->value;
5951  $this->debug("in serializeType: soapval overrides value to $value");
5952  if ($attrs) {
5953  if (!is_array($value)) {
5954  $value['!'] = $value;
5955  }
5956  foreach ($attrs as $n => $v) {
5957  $value['!' . $n] = $v;
5958  }
5959  $this->debug("in serializeType: soapval provides attributes");
5960  }
5961  } else {
5962  $forceType = false;
5963  }
5964 
5965  $xml = '';
5966  if (strpos($type, ':')) {
5967  $uqType = substr($type, strrpos($type, ':') + 1);
5968  $ns = substr($type, 0, strrpos($type, ':'));
5969  $this->debug("in serializeType: got a prefixed type: $uqType, $ns");
5970  if ($this->getNamespaceFromPrefix($ns)) {
5971  $ns = $this->getNamespaceFromPrefix($ns);
5972  $this->debug("in serializeType: expanded prefixed type: $uqType, $ns");
5973  }
5974 
5975  if ($ns == $this->XMLSchemaVersion || $ns == 'http://schemas.xmlsoap.org/soap/encoding/') {
5976  $this->debug('in serializeType: type namespace indicates XML Schema or SOAP Encoding type');
5977  if ($unqualified && $use == 'literal') {
5978  $elementNS = " xmlns=\"\"";
5979  } else {
5980  $elementNS = '';
5981  }
5982  if (is_null($value)) {
5983  if ($use == 'literal') {
5984  // TODO: depends on minOccurs
5985  $xml = "<$name$elementNS/>";
5986  } else {
5987  // TODO: depends on nillable, which should be checked before calling this method
5988  $xml = "<$name$elementNS xsi:nil=\"true\" xsi:type=\"" . $this->getPrefixFromNamespace($ns) . ":$uqType\"/>";
5989  }
5990  $this->debug("in serializeType: returning: $xml");
5991  return $xml;
5992  }
5993  if ($uqType == 'Array') {
5994  // JBoss/Axis does this sometimes
5995  return $this->serialize_val($value, $name, false, false, false, false, $use);
5996  }
5997  if ($uqType == 'boolean') {
5998  if ((is_string($value) && $value == 'false') || (! $value)) {
5999  $value = 'false';
6000  } else {
6001  $value = 'true';
6002  }
6003  }
6004  if ($uqType == 'string' && gettype($value) == 'string') {
6005  $value = $this->expandEntities($value);
6006  }
6007  if (($uqType == 'long' || $uqType == 'unsignedLong') && gettype($value) == 'double') {
6008  $value = sprintf("%.0lf", $value);
6009  }
6010  // it's a scalar
6011  // TODO: what about null/nil values?
6012  // check type isn't a custom type extending xmlschema namespace
6013  if (!$this->getTypeDef($uqType, $ns)) {
6014  if ($use == 'literal') {
6015  if ($forceType) {
6016  $xml = "<$name$elementNS xsi:type=\"" . $this->getPrefixFromNamespace($ns) . ":$uqType\">$value</$name>";
6017  } else {
6018  $xml = "<$name$elementNS>$value</$name>";
6019  }
6020  } else {
6021  $xml = "<$name$elementNS xsi:type=\"" . $this->getPrefixFromNamespace($ns) . ":$uqType\"$encodingStyle>$value</$name>";
6022  }
6023  $this->debug("in serializeType: returning: $xml");
6024  return $xml;
6025  }
6026  $this->debug('custom type extends XML Schema or SOAP Encoding namespace (yuck)');
6027  } elseif ($ns == 'http://xml.apache.org/xml-soap') {
6028  $this->debug('in serializeType: appears to be Apache SOAP type');
6029  if ($uqType == 'Map') {
6030  $tt_prefix = $this->getPrefixFromNamespace('http://xml.apache.org/xml-soap');
6031  if (! $tt_prefix) {
6032  $this->debug('in serializeType: Add namespace for Apache SOAP type');
6033  $tt_prefix = 'ns' . rand(1000, 9999);
6034  $this->namespaces[$tt_prefix] = 'http://xml.apache.org/xml-soap';
6035  // force this to be added to usedNamespaces
6036  $tt_prefix = $this->getPrefixFromNamespace('http://xml.apache.org/xml-soap');
6037  }
6038  $contents = '';
6039  foreach ($value as $k => $v) {
6040  $this->debug("serializing map element: key $k, value $v");
6041  $contents .= '<item>';
6042  $contents .= $this->serialize_val($k, 'key', false, false, false, false, $use);
6043  $contents .= $this->serialize_val($v, 'value', false, false, false, false, $use);
6044  $contents .= '</item>';
6045  }
6046  if ($use == 'literal') {
6047  if ($forceType) {
6048  $xml = "<$name xsi:type=\"" . $tt_prefix . ":$uqType\">$contents</$name>";
6049  } else {
6050  $xml = "<$name>$contents</$name>";
6051  }
6052  } else {
6053  $xml = "<$name xsi:type=\"" . $tt_prefix . ":$uqType\"$encodingStyle>$contents</$name>";
6054  }
6055  $this->debug("in serializeType: returning: $xml");
6056  return $xml;
6057  }
6058  $this->debug('in serializeType: Apache SOAP type, but only support Map');
6059  }
6060  } else {
6061  // TODO: should the type be compared to types in XSD, and the namespace
6062  // set to XSD if the type matches?
6063  $this->debug("in serializeType: No namespace for type $type");
6064  $ns = '';
6065  $uqType = $type;
6066  }
6067  if (!$typeDef = $this->getTypeDef($uqType, $ns)) {
6068  $this->setError("$type ($uqType) is not a supported type.");
6069  $this->debug("in serializeType: $type ($uqType) is not a supported type.");
6070  return false;
6071  } else {
6072  $this->debug("in serializeType: found typeDef");
6073  $this->appendDebug('typeDef=' . $this->varDump($typeDef));
6074  if (substr($uqType, -1) == '^') {
6075  $uqType = substr($uqType, 0, -1);
6076  }
6077  }
6078  $phpType = $typeDef['phpType'];
6079  $this->debug("in serializeType: uqType: $uqType, ns: $ns, phptype: $phpType, arrayType: " . (isset($typeDef['arrayType']) ? $typeDef['arrayType'] : ''));
6080  // if php type == struct, map value to the <all> element names
6081  if ($phpType == 'struct') {
6082  if (isset($typeDef['typeClass']) && $typeDef['typeClass'] == 'element') {
6083  $elementName = $uqType;
6084  if (isset($typeDef['form']) && ($typeDef['form'] == 'qualified')) {
6085  $elementNS = " xmlns=\"$ns\"";
6086  } else {
6087  $elementNS = " xmlns=\"\"";
6088  }
6089  } else {
6090  $elementName = $name;
6091  if ($unqualified) {
6092  $elementNS = " xmlns=\"\"";
6093  } else {
6094  $elementNS = '';
6095  }
6096  }
6097  if (is_null($value)) {
6098  if ($use == 'literal') {
6099  // TODO: depends on minOccurs
6100  $xml = "<$elementName$elementNS/>";
6101  } else {
6102  $xml = "<$elementName$elementNS xsi:nil=\"true\" xsi:type=\"" . $this->getPrefixFromNamespace($ns) . ":$uqType\"/>";
6103  }
6104  $this->debug("in serializeType: returning: $xml");
6105  return $xml;
6106  }
6107  if (is_object($value)) {
6108  $value = get_object_vars($value);
6109  }
6110  if (is_array($value)) {
6111  $elementAttrs = $this->serializeComplexTypeAttributes($typeDef, $value, $ns, $uqType);
6112  if ($use == 'literal') {
6113  if ($forceType) {
6114  $xml = "<$elementName$elementNS$elementAttrs xsi:type=\"" . $this->getPrefixFromNamespace($ns) . ":$uqType\">";
6115  } else {
6116  $xml = "<$elementName$elementNS$elementAttrs>";
6117  }
6118  } else {
6119  $xml = "<$elementName$elementNS$elementAttrs xsi:type=\"" . $this->getPrefixFromNamespace($ns) . ":$uqType\"$encodingStyle>";
6120  }
6121 
6122  $xml .= $this->serializeComplexTypeElements($typeDef, $value, $ns, $uqType, $use, $encodingStyle);
6123  $xml .= "</$elementName>";
6124  } else {
6125  $this->debug("in serializeType: phpType is struct, but value is not an array");
6126  $this->setError("phpType is struct, but value is not an array: see debug output for details");
6127  $xml = '';
6128  }
6129  } elseif ($phpType == 'array') {
6130  if (isset($typeDef['form']) && ($typeDef['form'] == 'qualified')) {
6131  $elementNS = " xmlns=\"$ns\"";
6132  } else {
6133  if ($unqualified) {
6134  $elementNS = " xmlns=\"\"";
6135  } else {
6136  $elementNS = '';
6137  }
6138  }
6139  if (is_null($value)) {
6140  if ($use == 'literal') {
6141  // TODO: depends on minOccurs
6142  $xml = "<$name$elementNS/>";
6143  } else {
6144  $xml = "<$name$elementNS xsi:nil=\"true\" xsi:type=\"" .
6145  $this->getPrefixFromNamespace('http://schemas.xmlsoap.org/soap/encoding/') .
6146  ":Array\" " .
6147  $this->getPrefixFromNamespace('http://schemas.xmlsoap.org/soap/encoding/') .
6148  ':arrayType="' .
6149  $this->getPrefixFromNamespace($this->getPrefix($typeDef['arrayType'])) .
6150  ':' .
6151  $this->getLocalPart($typeDef['arrayType']) . "[0]\"/>";
6152  }
6153  $this->debug("in serializeType: returning: $xml");
6154  return $xml;
6155  }
6156  if (isset($typeDef['multidimensional'])) {
6157  $nv = array();
6158  foreach ($value as $v) {
6159  $cols = ',' . sizeof($v);
6160  $nv = array_merge($nv, $v);
6161  }
6162  $value = $nv;
6163  } else {
6164  $cols = '';
6165  }
6166  if (is_array($value) && sizeof($value) >= 1) {
6167  $rows = sizeof($value);
6168  $contents = '';
6169  foreach ($value as $k => $v) {
6170  $this->debug("serializing array element: $k, $v of type: $typeDef[arrayType]");
6171  //if (strpos($typeDef['arrayType'], ':') ) {
6172  if (!in_array($typeDef['arrayType'], $this->typemap['http://www.w3.org/2001/XMLSchema'])) {
6173  $contents .= $this->serializeType('item', $typeDef['arrayType'], $v, $use);
6174  } else {
6175  $contents .= $this->serialize_val($v, 'item', $typeDef['arrayType'], null, $this->XMLSchemaVersion, false, $use);
6176  }
6177  }
6178  } else {
6179  $rows = 0;
6180  $contents = null;
6181  }
6182  // TODO: for now, an empty value will be serialized as a zero element
6183  // array. Revisit this when coding the handling of null/nil values.
6184  if ($use == 'literal') {
6185  $xml = "<$name$elementNS>"
6186  . $contents
6187  . "</$name>";
6188  } else {
6189  $xml = "<$name$elementNS xsi:type=\"" . $this->getPrefixFromNamespace('http://schemas.xmlsoap.org/soap/encoding/') . ':Array" ' .
6190  $this->getPrefixFromNamespace('http://schemas.xmlsoap.org/soap/encoding/')
6191  . ':arrayType="'
6192  . $this->getPrefixFromNamespace($this->getPrefix($typeDef['arrayType']))
6193  . ":" . $this->getLocalPart($typeDef['arrayType']) . "[$rows$cols]\">"
6194  . $contents
6195  . "</$name>";
6196  }
6197  } elseif ($phpType == 'scalar') {
6198  if (isset($typeDef['form']) && ($typeDef['form'] == 'qualified')) {
6199  $elementNS = " xmlns=\"$ns\"";
6200  } else {
6201  if ($unqualified) {
6202  $elementNS = " xmlns=\"\"";
6203  } else {
6204  $elementNS = '';
6205  }
6206  }
6207  if ($use == 'literal') {
6208  if ($forceType) {
6209  $xml = "<$name$elementNS xsi:type=\"" . $this->getPrefixFromNamespace($ns) . ":$uqType\">$value</$name>";
6210  } else {
6211  $xml = "<$name$elementNS>$value</$name>";
6212  }
6213  } else {
6214  $xml = "<$name$elementNS xsi:type=\"" . $this->getPrefixFromNamespace($ns) . ":$uqType\"$encodingStyle>$value</$name>";
6215  }
6216  }
6217  $this->debug("in serializeType: returning: $xml");
6218  return $xml;
6219  }
6220 
6231  public function serializeComplexTypeAttributes($typeDef, $value, $ns, $uqType)
6232  {
6233  $xml = '';
6234  if (isset($typeDef['attrs']) && is_array($typeDef['attrs'])) {
6235  $this->debug("serialize attributes for XML Schema type $ns:$uqType");
6236  if (is_array($value)) {
6237  $xvalue = $value;
6238  } elseif (is_object($value)) {
6239  $xvalue = get_object_vars($value);
6240  } else {
6241  $this->debug("value is neither an array nor an object for XML Schema type $ns:$uqType");
6242  $xvalue = array();
6243  }
6244  foreach ($typeDef['attrs'] as $aName => $attrs) {
6245  if (isset($xvalue['!' . $aName])) {
6246  $xname = '!' . $aName;
6247  $this->debug("value provided for attribute $aName with key $xname");
6248  } elseif (isset($xvalue[$aName])) {
6249  $xname = $aName;
6250  $this->debug("value provided for attribute $aName with key $xname");
6251  } elseif (isset($attrs['default'])) {
6252  $xname = '!' . $aName;
6253  $xvalue[$xname] = $attrs['default'];
6254  $this->debug('use default value of ' . $xvalue[$aName] . ' for attribute ' . $aName);
6255  } else {
6256  $xname = '';
6257  $this->debug("no value provided for attribute $aName");
6258  }
6259  if ($xname) {
6260  $xml .= " $aName=\"" . $this->expandEntities($xvalue[$xname]) . "\"";
6261  }
6262  }
6263  } else {
6264  $this->debug("no attributes to serialize for XML Schema type $ns:$uqType");
6265  }
6266  if (isset($typeDef['extensionBase'])) {
6267  $ns = $this->getPrefix($typeDef['extensionBase']);
6268  $uqType = $this->getLocalPart($typeDef['extensionBase']);
6269  if ($this->getNamespaceFromPrefix($ns)) {
6270  $ns = $this->getNamespaceFromPrefix($ns);
6271  }
6272  if ($typeDef = $this->getTypeDef($uqType, $ns)) {
6273  $this->debug("serialize attributes for extension base $ns:$uqType");
6274  $xml .= $this->serializeComplexTypeAttributes($typeDef, $value, $ns, $uqType);
6275  } else {
6276  $this->debug("extension base $ns:$uqType is not a supported type");
6277  }
6278  }
6279  return $xml;
6280  }
6281 
6294  public function serializeComplexTypeElements($typeDef, $value, $ns, $uqType, $use='encoded', $encodingStyle=false)
6295  {
6296  $xml = '';
6297  if (isset($typeDef['elements']) && is_array($typeDef['elements'])) {
6298  $this->debug("in serializeComplexTypeElements, serialize elements for XML Schema type $ns:$uqType");
6299  if (is_array($value)) {
6300  $xvalue = $value;
6301  } elseif (is_object($value)) {
6302  $xvalue = get_object_vars($value);
6303  } else {
6304  $this->debug("value is neither an array nor an object for XML Schema type $ns:$uqType");
6305  $xvalue = array();
6306  }
6307  // toggle whether all elements are present - ideally should validate against schema
6308  if (count($typeDef['elements']) != count($xvalue)) {
6309  $optionals = true;
6310  }
6311  foreach ($typeDef['elements'] as $eName => $attrs) {
6312  if (!isset($xvalue[$eName])) {
6313  if (isset($attrs['default'])) {
6314  $xvalue[$eName] = $attrs['default'];
6315  $this->debug('use default value of ' . $xvalue[$eName] . ' for element ' . $eName);
6316  }
6317  }
6318  // if user took advantage of a minOccurs=0, then only serialize named parameters
6319  if (isset($optionals)
6320  && (!isset($xvalue[$eName]))
6321  && ((!isset($attrs['nillable'])) || $attrs['nillable'] != 'true')
6322  ) {
6323  if (isset($attrs['minOccurs']) && $attrs['minOccurs'] <> '0') {
6324  $this->debug("apparent error: no value provided for element $eName with minOccurs=" . $attrs['minOccurs']);
6325  }
6326  // do nothing
6327  $this->debug("no value provided for complexType element $eName and element is not nillable, so serialize nothing");
6328  } else {
6329  // get value
6330  if (isset($xvalue[$eName])) {
6331  $v = $xvalue[$eName];
6332  } else {
6333  $v = null;
6334  }
6335  if (isset($attrs['form'])) {
6336  $unqualified = ($attrs['form'] == 'unqualified');
6337  } else {
6338  $unqualified = false;
6339  }
6340  if (isset($attrs['maxOccurs']) && ($attrs['maxOccurs'] == 'unbounded' || $attrs['maxOccurs'] > 1) && isset($v) && is_array($v) && $this->isArraySimpleOrStruct($v) == 'arraySimple') {
6341  $vv = $v;
6342  foreach ($vv as $k => $v) {
6343  if (isset($attrs['type']) || isset($attrs['ref'])) {
6344  // serialize schema-defined type
6345  $xml .= $this->serializeType($eName, isset($attrs['type']) ? $attrs['type'] : $attrs['ref'], $v, $use, $encodingStyle, $unqualified);
6346  } else {
6347  // serialize generic type (can this ever really happen?)
6348  $this->debug("calling serialize_val() for $v, $eName, false, false, false, false, $use");
6349  $xml .= $this->serialize_val($v, $eName, false, false, false, false, $use);
6350  }
6351  }
6352  } else {
6353  if (isset($attrs['type']) || isset($attrs['ref'])) {
6354  // serialize schema-defined type
6355  $xml .= $this->serializeType($eName, isset($attrs['type']) ? $attrs['type'] : $attrs['ref'], $v, $use, $encodingStyle, $unqualified);
6356  } else {
6357  // serialize generic type (can this ever really happen?)
6358  $this->debug("calling serialize_val() for $v, $eName, false, false, false, false, $use");
6359  $xml .= $this->serialize_val($v, $eName, false, false, false, false, $use);
6360  }
6361  }
6362  }
6363  }
6364  } else {
6365  $this->debug("no elements to serialize for XML Schema type $ns:$uqType");
6366  }
6367  if (isset($typeDef['extensionBase'])) {
6368  $ns = $this->getPrefix($typeDef['extensionBase']);
6369  $uqType = $this->getLocalPart($typeDef['extensionBase']);
6370  if ($this->getNamespaceFromPrefix($ns)) {
6371  $ns = $this->getNamespaceFromPrefix($ns);
6372  }
6373  if ($typeDef = $this->getTypeDef($uqType, $ns)) {
6374  $this->debug("serialize elements for extension base $ns:$uqType");
6375  $xml .= $this->serializeComplexTypeElements($typeDef, $value, $ns, $uqType, $use, $encodingStyle);
6376  } else {
6377  $this->debug("extension base $ns:$uqType is not a supported type");
6378  }
6379  }
6380  return $xml;
6381  }
6382 
6397  public function addComplexType($name, $typeClass='complexType', $phpType='array', $compositor='', $restrictionBase='', $elements=array(), $attrs=array(), $arrayType='')
6398  {
6399  if (count($elements) > 0) {
6400  $eElements = array();
6401  foreach ($elements as $n => $e) {
6402  // expand each element
6403  $ee = array();
6404  foreach ($e as $k => $v) {
6405  $k = strpos($k, ':') ? $this->expandQname($k) : $k;
6406  $v = strpos($v, ':') ? $this->expandQname($v) : $v;
6407  $ee[$k] = $v;
6408  }
6409  $eElements[$n] = $ee;
6410  }
6411  $elements = $eElements;
6412  }
6413 
6414  if (count($attrs) > 0) {
6415  foreach ($attrs as $n => $a) {
6416  // expand each attribute
6417  foreach ($a as $k => $v) {
6418  $k = strpos($k, ':') ? $this->expandQname($k) : $k;
6419  $v = strpos($v, ':') ? $this->expandQname($v) : $v;
6420  $aa[$k] = $v;
6421  }
6422  $eAttrs[$n] = $aa;
6423  }
6424  $attrs = $eAttrs;
6425  }
6426 
6427  $restrictionBase = strpos($restrictionBase, ':') ? $this->expandQname($restrictionBase) : $restrictionBase;
6428  $arrayType = strpos($arrayType, ':') ? $this->expandQname($arrayType) : $arrayType;
6429 
6430  $typens = isset($this->namespaces['types']) ? $this->namespaces['types'] : $this->namespaces['tns'];
6431  $this->schemas[$typens][0]->addComplexType($name, $typeClass, $phpType, $compositor, $restrictionBase, $elements, $attrs, $arrayType);
6432  }
6433 
6445  public function addSimpleType($name, $restrictionBase='', $typeClass='simpleType', $phpType='scalar', $enumeration=array())
6446  {
6447  $restrictionBase = strpos($restrictionBase, ':') ? $this->expandQname($restrictionBase) : $restrictionBase;
6448 
6449  $typens = isset($this->namespaces['types']) ? $this->namespaces['types'] : $this->namespaces['tns'];
6450  $this->schemas[$typens][0]->addSimpleType($name, $restrictionBase, $typeClass, $phpType, $enumeration);
6451  }
6452 
6460  public function addElement($attrs)
6461  {
6462  $typens = isset($this->namespaces['types']) ? $this->namespaces['types'] : $this->namespaces['tns'];
6463  $this->schemas[$typens][0]->addElement($attrs);
6464  }
6465 
6480  public function addOperation($name, $in = false, $out = false, $namespace = false, $soapaction = false, $style = 'rpc', $use = 'encoded', $documentation = '', $encodingStyle = '')
6481  {
6482  if ($use == 'encoded' && $encodingStyle == '') {
6483  $encodingStyle = 'http://schemas.xmlsoap.org/soap/encoding/';
6484  }
6485 
6486  if ($style == 'document') {
6487  $elements = array();
6488  foreach ($in as $n => $t) {
6489  $elements[$n] = array('name' => $n, 'type' => $t);
6490  }
6491  $this->addComplexType($name . 'RequestType', 'complexType', 'struct', 'all', '', $elements);
6492  $this->addElement(array('name' => $name, 'type' => $name . 'RequestType'));
6493  $in = array('parameters' => 'tns:' . $name . '^');
6494 
6495  $elements = array();
6496  foreach ($out as $n => $t) {
6497  $elements[$n] = array('name' => $n, 'type' => $t);
6498  }
6499  $this->addComplexType($name . 'ResponseType', 'complexType', 'struct', 'all', '', $elements);
6500  $this->addElement(array('name' => $name . 'Response', 'type' => $name . 'ResponseType', 'form' => 'qualified'));
6501  $out = array('parameters' => 'tns:' . $name . 'Response' . '^');
6502  }
6503 
6504  // get binding
6505  $this->bindings[ $this->serviceName . 'Binding' ]['operations'][$name] =
6506  array(
6507  'name' => $name,
6508  'binding' => $this->serviceName . 'Binding',
6509  'endpoint' => $this->endpoint,
6510  'soapAction' => $soapaction,
6511  'style' => $style,
6512  'input' => array(
6513  'use' => $use,
6514  'namespace' => $namespace,
6515  'encodingStyle' => $encodingStyle,
6516  'message' => $name . 'Request',
6517  'parts' => $in),
6518  'output' => array(
6519  'use' => $use,
6520  'namespace' => $namespace,
6521  'encodingStyle' => $encodingStyle,
6522  'message' => $name . 'Response',
6523  'parts' => $out),
6524  'namespace' => $namespace,
6525  'transport' => 'http://schemas.xmlsoap.org/soap/http',
6526  'documentation' => $documentation);
6527  // add portTypes
6528  // add messages
6529  if ($in) {
6530  foreach ($in as $pName => $pType) {
6531  if (strpos($pType, ':')) {
6532  $pType = $this->getNamespaceFromPrefix($this->getPrefix($pType)) . ":" . $this->getLocalPart($pType);
6533  }
6534  $this->messages[$name . 'Request'][$pName] = $pType;
6535  }
6536  } else {
6537  $this->messages[$name . 'Request']= '0';
6538  }
6539  if ($out) {
6540  foreach ($out as $pName => $pType) {
6541  if (strpos($pType, ':')) {
6542  $pType = $this->getNamespaceFromPrefix($this->getPrefix($pType)) . ":" . $this->getLocalPart($pType);
6543  }
6544  $this->messages[$name . 'Response'][$pName] = $pType;
6545  }
6546  } else {
6547  $this->messages[$name . 'Response']= '0';
6548  }
6549  return true;
6550  }
6551 }
6552 ?><?php
6553 
6554 
6555 
6566 {
6568  public $parser;
6569  public $xml = '';
6570  public $xml_encoding = '';
6571  public $method = '';
6572  public $root_struct = '';
6573  public $root_struct_name = '';
6574  public $root_struct_namespace = '';
6575  public $root_header = '';
6576  public $document = ''; // incoming SOAP body (text)
6577  // determines where in the message we are (envelope,header,body,method)
6578  public $status = '';
6579  public $position = 0;
6580  public $depth = 0;
6581  public $default_namespace = '';
6582  public $namespaces = array();
6583  public $message = array();
6584  public $parent = '';
6585  public $fault = false;
6586  public $fault_code = '';
6587  public $fault_str = '';
6588  public $fault_detail = '';
6589  public $depth_array = array();
6590  public $debug_flag = true;
6591  public $soapresponse = null; // parsed SOAP Body
6592  public $soapheader = null; // parsed SOAP Header
6593  public $responseHeaders = ''; // incoming SOAP headers (text)
6594  public $body_position = 0;
6595  // for multiref parsing:
6596  // array of id => pos
6597  public $ids = array();
6598  // array of id => hrefs => pos
6599  public $multirefs = array();
6600  // toggle for auto-decoding element content
6601  public $decode_utf8 = true;
6602 
6612  public function __construct($xml, $encoding='UTF-8', $method='', $decode_utf8=true)
6613  {
6615  $this->xml = $xml;
6616  $this->xml_encoding = $encoding;
6617  $this->method = $method;
6618  $this->decode_utf8 = $decode_utf8;
6619 
6620  // Check whether content has been read.
6621  if (!empty($xml)) {
6622  // Check XML encoding
6623  $pos_xml = strpos($xml, '<?xml');
6624  if ($pos_xml !== false) {
6625  $xml_decl = substr($xml, $pos_xml, strpos($xml, '?>', $pos_xml + 2) - $pos_xml + 1);
6626  if (preg_match("/encoding=[\"']([^\"']*)[\"']/", $xml_decl, $res)) {
6627  $xml_encoding = $res[1];
6628  if (strtoupper($xml_encoding) != $encoding) {
6629  $err = "Charset from HTTP Content-Type '" . $encoding . "' does not match encoding from XML declaration '" . $xml_encoding . "'";
6630  $this->debug($err);
6631  if ($encoding != 'ISO-8859-1' || strtoupper($xml_encoding) != 'UTF-8') {
6632  $this->setError($err);
6633  return;
6634  }
6635  // when HTTP says ISO-8859-1 (the default) and XML says UTF-8 (the typical), assume the other endpoint is just sloppy and proceed
6636  } else {
6637  $this->debug('Charset from HTTP Content-Type matches encoding from XML declaration');
6638  }
6639  } else {
6640  $this->debug('No encoding specified in XML declaration');
6641  }
6642  } else {
6643  $this->debug('No XML declaration');
6644  }
6645  $this->debug('Entering nusoap_parser(), length=' . strlen($xml) . ', encoding=' . $encoding);
6646  // Create an XML parser - why not xml_parser_create_ns?
6647  $this->parser = xml_parser_create($this->xml_encoding);
6648  // Set the options for parsing the XML data.
6649  //xml_parser_set_option($parser, XML_OPTION_SKIP_WHITE, 1);
6650  xml_parser_set_option($this->parser, XML_OPTION_CASE_FOLDING, 0);
6651  xml_parser_set_option($this->parser, XML_OPTION_TARGET_ENCODING, $this->xml_encoding);
6652  // Set the object for the parser.
6653  xml_set_object($this->parser, $this);
6654  // Set the element handlers for the parser.
6655  xml_set_element_handler($this->parser, 'start_element', 'end_element');
6656  xml_set_character_data_handler($this->parser, 'character_data');
6657 
6658  // Parse the XML file.
6659  if (!xml_parse($this->parser, $xml, true)) {
6660  // Display an error message.
6661  $err = sprintf(
6662  'XML error parsing SOAP payload on line %d: %s',
6663  xml_get_current_line_number($this->parser),
6664  xml_error_string(xml_get_error_code($this->parser))
6665  );
6666  $this->debug($err);
6667  $this->debug("XML payload:\n" . $xml);
6668  $this->setError($err);
6669  } else {
6670  $this->debug('parsed successfully, found root struct: ' . $this->root_struct . ' of name ' . $this->root_struct_name);
6671  // get final value
6672  $this->soapresponse = $this->message[$this->root_struct]['result'];
6673  // get header value
6674  if ($this->root_header != '' && isset($this->message[$this->root_header]['result'])) {
6675  $this->soapheader = $this->message[$this->root_header]['result'];
6676  }
6677  // resolve hrefs/ids
6678  if (sizeof($this->multirefs) > 0) {
6679  foreach ($this->multirefs as $id => $hrefs) {
6680  $this->debug('resolving multirefs for id: ' . $id);
6681  $idVal = $this->buildVal($this->ids[$id]);
6682  if (is_array($idVal) && isset($idVal['!id'])) {
6683  unset($idVal['!id']);
6684  }
6685  foreach ($hrefs as $refPos => $ref) {
6686  $this->debug('resolving href at pos ' . $refPos);
6687  $this->multirefs[$id][$refPos] = $idVal;
6688  }
6689  }
6690  }
6691  }
6692  xml_parser_free($this->parser);
6693  } else {
6694  $this->debug('xml was empty, didn\'t parse!');
6695  $this->setError('xml was empty, didn\'t parse!');
6696  }
6697  }
6698 
6707  public function start_element($parser, $name, $attrs)
6708  {
6709  // position in a total number of elements, starting from 0
6710  // update class level pos
6711  $pos = $this->position++;
6712  // and set mine
6713  $this->message[$pos] = array('pos' => $pos,'children'=>'','cdata'=>'');
6714  // depth = how many levels removed from root?
6715  // set mine as current global depth and increment global depth value
6716  $this->message[$pos]['depth'] = $this->depth++;
6717 
6718  // else add self as child to whoever the current parent is
6719  if ($pos != 0) {
6720  $this->message[$this->parent]['children'] .= '|' . $pos;
6721  }
6722  // set my parent
6723  $this->message[$pos]['parent'] = $this->parent;
6724  // set self as current parent
6725  $this->parent = $pos;
6726  // set self as current value for this depth
6727  $this->depth_array[$this->depth] = $pos;
6728  // get element prefix
6729  if (strpos($name, ':')) {
6730  // get ns prefix
6731  $prefix = substr($name, 0, strpos($name, ':'));
6732  // get unqualified name
6733  $name = substr(strstr($name, ':'), 1);
6734  }
6735  // set status
6736  if ($name == 'Envelope') {
6737  $this->status = 'envelope';
6738  } elseif ($name == 'Header' && $this->status = 'envelope') {
6739  $this->root_header = $pos;
6740  $this->status = 'header';
6741  } elseif ($name == 'Body' && $this->status = 'envelope') {
6742  $this->status = 'body';
6743  $this->body_position = $pos;
6744  // set method
6745  } elseif ($this->status == 'body' && $pos == ($this->body_position+1)) {
6746  $this->status = 'method';
6747  $this->root_struct_name = $name;
6748  $this->root_struct = $pos;
6749  $this->message[$pos]['type'] = 'struct';
6750  $this->debug("found root struct $this->root_struct_name, pos $this->root_struct");
6751  }
6752  // set my status
6753  $this->message[$pos]['status'] = $this->status;
6754  // set name
6755  $this->message[$pos]['name'] = htmlspecialchars($name);
6756  // set attrs
6757  $this->message[$pos]['attrs'] = $attrs;
6758 
6759  // loop through atts, logging ns and type declarations
6760  $attstr = '';
6761  foreach ($attrs as $key => $value) {
6762  $key_prefix = $this->getPrefix($key);
6763  $key_localpart = $this->getLocalPart($key);
6764  // if ns declarations, add to class level array of valid namespaces
6765  if ($key_prefix == 'xmlns') {
6766  if (preg_match('/^http:\/\/www.w3.org\/[0-9]{4}\/XMLSchema$/', $value)) {
6767  $this->XMLSchemaVersion = $value;
6768  $this->namespaces['xsd'] = $this->XMLSchemaVersion;
6769  $this->namespaces['xsi'] = $this->XMLSchemaVersion . '-instance';
6770  }
6771  $this->namespaces[$key_localpart] = $value;
6772  // set method namespace
6773  if ($name == $this->root_struct_name) {
6774  $this->methodNamespace = $value;
6775  }
6776  // if it's a type declaration, set type
6777  } elseif ($key_localpart == 'type') {
6778  if (isset($this->message[$pos]['type']) && $this->message[$pos]['type'] == 'array') {
6779  // do nothing: already processed arrayType
6780  } else {
6781  $value_prefix = $this->getPrefix($value);
6782  $value_localpart = $this->getLocalPart($value);
6783  $this->message[$pos]['type'] = $value_localpart;
6784  $this->message[$pos]['typePrefix'] = $value_prefix;
6785  if (isset($this->namespaces[$value_prefix])) {
6786  $this->message[$pos]['type_namespace'] = $this->namespaces[$value_prefix];
6787  } elseif (isset($attrs['xmlns:' . $value_prefix])) {
6788  $this->message[$pos]['type_namespace'] = $attrs['xmlns:' . $value_prefix];
6789  }
6790  // should do something here with the namespace of specified type?
6791  }
6792  } elseif ($key_localpart == 'arrayType') {
6793  $this->message[$pos]['type'] = 'array';
6794  /* do arrayType ereg here
6795  [1] arrayTypeValue ::= atype asize
6796  [2] atype ::= QName rank*
6797  [3] rank ::= '[' (',')* ']'
6798  [4] asize ::= '[' length~ ']'
6799  [5] length ::= nextDimension* Digit+
6800  [6] nextDimension ::= Digit+ ','
6801  */
6802  $expr = '/([A-Za-z0-9_]+):([A-Za-z]+[A-Za-z0-9_]+)\[([0-9]+),?([0-9]*)\]/';
6803  if (preg_match($expr, $value, $regs)) {
6804  $this->message[$pos]['typePrefix'] = $regs[1];
6805  $this->message[$pos]['arrayTypePrefix'] = $regs[1];
6806  if (isset($this->namespaces[$regs[1]])) {
6807  $this->message[$pos]['arrayTypeNamespace'] = $this->namespaces[$regs[1]];
6808  } elseif (isset($attrs['xmlns:' . $regs[1]])) {
6809  $this->message[$pos]['arrayTypeNamespace'] = $attrs['xmlns:' . $regs[1]];
6810  }
6811  $this->message[$pos]['arrayType'] = $regs[2];
6812  $this->message[$pos]['arraySize'] = $regs[3];
6813  $this->message[$pos]['arrayCols'] = $regs[4];
6814  }
6815  // specifies nil value (or not)
6816  } elseif ($key_localpart == 'nil') {
6817  $this->message[$pos]['nil'] = ($value == 'true' || $value == '1');
6818  // some other attribute
6819  } elseif ($key != 'href' && $key != 'xmlns' && $key_localpart != 'encodingStyle' && $key_localpart != 'root') {
6820  $this->message[$pos]['xattrs']['!' . $key] = $value;
6821  }
6822 
6823  if ($key == 'xmlns') {
6824  $this->default_namespace = $value;
6825  }
6826  // log id
6827  if ($key == 'id') {
6828  $this->ids[$value] = $pos;
6829  }
6830  // root
6831  if ($key_localpart == 'root' && $value == 1) {
6832  $this->status = 'method';
6833  $this->root_struct_name = $name;
6834  $this->root_struct = $pos;
6835  $this->debug("found root struct $this->root_struct_name, pos $pos");
6836  }
6837  // for doclit
6838  $attstr .= " $key=\"$value\"";
6839  }
6840  // get namespace - must be done after namespace atts are processed
6841  if (isset($prefix)) {
6842  $this->message[$pos]['namespace'] = $this->namespaces[$prefix];
6843  $this->default_namespace = $this->namespaces[$prefix];
6844  } else {
6845  $this->message[$pos]['namespace'] = $this->default_namespace;
6846  }
6847  if ($this->status == 'header') {
6848  if ($this->root_header != $pos) {
6849  $this->responseHeaders .= "<" . (isset($prefix) ? $prefix . ':' : '') . "$name$attstr>";
6850  }
6851  } elseif ($this->root_struct_name != '') {
6852  $this->document .= "<" . (isset($prefix) ? $prefix . ':' : '') . "$name$attstr>";
6853  }
6854  }
6855 
6863  public function end_element($parser, $name)
6864  {
6865  // position of current element is equal to the last value left in depth_array for my depth
6866  $pos = $this->depth_array[$this->depth--];
6867 
6868  // get element prefix
6869  if (strpos($name, ':')) {
6870  // get ns prefix
6871  $prefix = substr($name, 0, strpos($name, ':'));
6872  // get unqualified name
6873  $name = substr(strstr($name, ':'), 1);
6874  }
6875 
6876  // build to native type
6877  if (isset($this->body_position) && $pos > $this->body_position) {
6878  // deal w/ multirefs
6879  if (isset($this->message[$pos]['attrs']['href'])) {
6880  // get id
6881  $id = substr($this->message[$pos]['attrs']['href'], 1);
6882  // add placeholder to href array
6883  $this->multirefs[$id][$pos] = 'placeholder';
6884  // add set a reference to it as the result value
6885  $this->message[$pos]['result'] =& $this->multirefs[$id][$pos];
6886  // build complexType values
6887  } elseif ($this->message[$pos]['children'] != '') {
6888  // if result has already been generated (struct/array)
6889  if (!isset($this->message[$pos]['result'])) {
6890  $this->message[$pos]['result'] = $this->buildVal($pos);
6891  }
6892  // build complexType values of attributes and possibly simpleContent
6893  } elseif (isset($this->message[$pos]['xattrs'])) {
6894  if (isset($this->message[$pos]['nil']) && $this->message[$pos]['nil']) {
6895  $this->message[$pos]['xattrs']['!'] = null;
6896  } elseif (isset($this->message[$pos]['cdata']) && trim($this->message[$pos]['cdata']) != '') {
6897  if (isset($this->message[$pos]['type'])) {
6898  $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'] : '');
6899  } else {
6900  $parent = $this->message[$pos]['parent'];
6901  if (isset($this->message[$parent]['type']) && ($this->message[$parent]['type'] == 'array') && isset($this->message[$parent]['arrayType'])) {
6902  $this->message[$pos]['xattrs']['!'] = $this->decodeSimple($this->message[$pos]['cdata'], $this->message[$parent]['arrayType'], isset($this->message[$parent]['arrayTypeNamespace']) ? $this->message[$parent]['arrayTypeNamespace'] : '');
6903  } else {
6904  $this->message[$pos]['xattrs']['!'] = $this->message[$pos]['cdata'];
6905  }
6906  }
6907  }
6908  $this->message[$pos]['result'] = $this->message[$pos]['xattrs'];
6909  // set value of simpleType (or nil complexType)
6910  } else {
6911  //$this->debug('adding data for scalar value '.$this->message[$pos]['name'].' of value '.$this->message[$pos]['cdata']);
6912  if (isset($this->message[$pos]['nil']) && $this->message[$pos]['nil']) {
6913  $this->message[$pos]['xattrs']['!'] = null;
6914  } elseif (isset($this->message[$pos]['type'])) {
6915  $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'] : '');
6916  } else {
6917  $parent = $this->message[$pos]['parent'];
6918  if (isset($this->message[$parent]['type']) && ($this->message[$parent]['type'] == 'array') && isset($this->message[$parent]['arrayType'])) {
6919  $this->message[$pos]['result'] = $this->decodeSimple($this->message[$pos]['cdata'], $this->message[$parent]['arrayType'], isset($this->message[$parent]['arrayTypeNamespace']) ? $this->message[$parent]['arrayTypeNamespace'] : '');
6920  } else {
6921  $this->message[$pos]['result'] = $this->message[$pos]['cdata'];
6922  }
6923  }
6924 
6925  /* add value to parent's result, if parent is struct/array
6926  $parent = $this->message[$pos]['parent'];
6927  if($this->message[$parent]['type'] != 'map'){
6928  if(strtolower($this->message[$parent]['type']) == 'array'){
6929  $this->message[$parent]['result'][] = $this->message[$pos]['result'];
6930  } else {
6931  $this->message[$parent]['result'][$this->message[$pos]['name']] = $this->message[$pos]['result'];
6932  }
6933  }
6934  */
6935  }
6936  }
6937 
6938  // for doclit
6939  if ($this->status == 'header') {
6940  if ($this->root_header != $pos) {
6941  $this->responseHeaders .= "</" . (isset($prefix) ? $prefix . ':' : '') . "$name>";
6942  }
6943  } elseif ($pos >= $this->root_struct) {
6944  $this->document .= "</" . (isset($prefix) ? $prefix . ':' : '') . "$name>";
6945  }
6946  // switch status
6947  if ($pos == $this->root_struct) {
6948  $this->status = 'body';
6949  $this->root_struct_namespace = $this->message[$pos]['namespace'];
6950  } elseif ($name == 'Body') {
6951  $this->status = 'envelope';
6952  } elseif ($name == 'Header') {
6953  $this->status = 'envelope';
6954  } elseif ($name == 'Envelope') {
6955  //
6956  }
6957  // set parent back to my parent
6958  $this->parent = $this->message[$pos]['parent'];
6959  }
6960 
6968  public function character_data($parser, $data)
6969  {
6970  $pos = $this->depth_array[$this->depth];
6971  if ($this->xml_encoding=='UTF-8') {
6972  // TODO: add an option to disable this for folks who want
6973  // raw UTF-8 that, e.g., might not map to iso-8859-1
6974  // TODO: this can also be handled with xml_parser_set_option($this->parser, XML_OPTION_TARGET_ENCODING, "ISO-8859-1");
6975  if ($this->decode_utf8) {
6976  $data = utf8_decode($data);
6977  }
6978  }
6979  $this->message[$pos]['cdata'] .= $data;
6980  // for doclit
6981  if ($this->status == 'header') {
6982  $this->responseHeaders .= $data;
6983  } else {
6984  $this->document .= $data;
6985  }
6986  }
6987 
6995  public function get_response()
6996  {
6997  return $this->soapresponse;
6998  }
6999 
7006  public function get_soapbody()
7007  {
7008  return $this->soapresponse;
7009  }
7010 
7017  public function get_soapheader()
7018  {
7019  return $this->soapheader;
7020  }
7021 
7028  public function getHeaders()
7029  {
7030  return $this->responseHeaders;
7031  }
7032 
7042  public function decodeSimple($value, $type, $typens)
7043  {
7044  // TODO: use the namespace!
7045  if ((!isset($type)) || $type == 'string' || $type == 'long' || $type == 'unsignedLong') {
7046  return (string) $value;
7047  }
7048  if ($type == 'int' || $type == 'integer' || $type == 'short' || $type == 'byte') {
7049  return (int) $value;
7050  }
7051  if ($type == 'float' || $type == 'double' || $type == 'decimal') {
7052  return (float) $value;
7053  }
7054  if ($type == 'boolean') {
7055  if (strtolower($value) == 'false' || strtolower($value) == 'f') {
7056  return false;
7057  }
7058  return (bool) $value;
7059  }
7060  if ($type == 'base64' || $type == 'base64Binary') {
7061  $this->debug('Decode base64 value');
7062  return base64_decode($value);
7063  }
7064  // obscure numeric types
7065  if ($type == 'nonPositiveInteger' || $type == 'negativeInteger'
7066  || $type == 'nonNegativeInteger' || $type == 'positiveInteger'
7067  || $type == 'unsignedInt'
7068  || $type == 'unsignedShort' || $type == 'unsignedByte') {
7069  return (int) $value;
7070  }
7071  // bogus: parser treats array with no elements as a simple type
7072  if ($type == 'array') {
7073  return array();
7074  }
7075  // everything else
7076  return (string) $value;
7077  }
7078 
7087  public function buildVal($pos)
7088  {
7089  if (!isset($this->message[$pos]['type'])) {
7090  $this->message[$pos]['type'] = '';
7091  }
7092  $this->debug('in buildVal() for ' . $this->message[$pos]['name'] . "(pos $pos) of type " . $this->message[$pos]['type']);
7093  // if there are children...
7094  if ($this->message[$pos]['children'] != '') {
7095  $this->debug('in buildVal, there are children');
7096  $children = explode('|', $this->message[$pos]['children']);
7097  array_shift($children); // knock off empty
7098  // md array
7099  if (isset($this->message[$pos]['arrayCols']) && $this->message[$pos]['arrayCols'] != '') {
7100  $r=0; // rowcount
7101  $c=0; // colcount
7102  foreach ($children as $child_pos) {
7103  $this->debug("in buildVal, got an MD array element: $r, $c");
7104  $params[$r][] = $this->message[$child_pos]['result'];
7105  $c++;
7106  if ($c == $this->message[$pos]['arrayCols']) {
7107  $c = 0;
7108  $r++;
7109  }
7110  }
7111  // array
7112  } elseif ($this->message[$pos]['type'] == 'array' || $this->message[$pos]['type'] == 'Array') {
7113  $this->debug('in buildVal, adding array ' . $this->message[$pos]['name']);
7114  foreach ($children as $child_pos) {
7115  $params[] = &$this->message[$child_pos]['result'];
7116  }
7117  // apache Map type: java hashtable
7118  } elseif ($this->message[$pos]['type'] == 'Map' && $this->message[$pos]['type_namespace'] == 'http://xml.apache.org/xml-soap') {
7119  $this->debug('in buildVal, Java Map ' . $this->message[$pos]['name']);
7120  foreach ($children as $child_pos) {
7121  $kv = explode("|", $this->message[$child_pos]['children']);
7122  $params[$this->message[$kv[1]]['result']] = &$this->message[$kv[2]]['result'];
7123  }
7124  // generic compound type
7125  //} elseif($this->message[$pos]['type'] == 'SOAPStruct' || $this->message[$pos]['type'] == 'struct') {
7126  } else {
7127  // Apache Vector type: treat as an array
7128  $this->debug('in buildVal, adding Java Vector or generic compound type ' . $this->message[$pos]['name']);
7129  if ($this->message[$pos]['type'] == 'Vector' && $this->message[$pos]['type_namespace'] == 'http://xml.apache.org/xml-soap') {
7130  $notstruct = 1;
7131  } else {
7132  $notstruct = 0;
7133  }
7134  //
7135  foreach ($children as $child_pos) {
7136  if ($notstruct) {
7137  $params[] = &$this->message[$child_pos]['result'];
7138  } else {
7139  if (isset($params[$this->message[$child_pos]['name']])) {
7140  // de-serialize repeated element name into an array
7141  if ((!is_array($params[$this->message[$child_pos]['name']])) || (!isset($params[$this->message[$child_pos]['name']][0]))) {
7142  $params[$this->message[$child_pos]['name']] = array($params[$this->message[$child_pos]['name']]);
7143  }
7144  $params[$this->message[$child_pos]['name']][] = &$this->message[$child_pos]['result'];
7145  } else {
7146  $params[$this->message[$child_pos]['name']] = &$this->message[$child_pos]['result'];
7147  }
7148  }
7149  }
7150  }
7151  if (isset($this->message[$pos]['xattrs'])) {
7152  $this->debug('in buildVal, handling attributes');
7153  foreach ($this->message[$pos]['xattrs'] as $n => $v) {
7154  $params[$n] = $v;
7155  }
7156  }
7157  // handle simpleContent
7158  if (isset($this->message[$pos]['cdata']) && trim($this->message[$pos]['cdata']) != '') {
7159  $this->debug('in buildVal, handling simpleContent');
7160  if (isset($this->message[$pos]['type'])) {
7161  $params['!'] = $this->decodeSimple($this->message[$pos]['cdata'], $this->message[$pos]['type'], isset($this->message[$pos]['type_namespace']) ? $this->message[$pos]['type_namespace'] : '');
7162  } else {
7163  $parent = $this->message[$pos]['parent'];
7164  if (isset($this->message[$parent]['type']) && ($this->message[$parent]['type'] == 'array') && isset($this->message[$parent]['arrayType'])) {
7165  $params['!'] = $this->decodeSimple($this->message[$pos]['cdata'], $this->message[$parent]['arrayType'], isset($this->message[$parent]['arrayTypeNamespace']) ? $this->message[$parent]['arrayTypeNamespace'] : '');
7166  } else {
7167  $params['!'] = $this->message[$pos]['cdata'];
7168  }
7169  }
7170  }
7171  $ret = is_array($params) ? $params : array();
7172  $this->debug('in buildVal, return:');
7173  $this->appendDebug($this->varDump($ret));
7174  return $ret;
7175  } else {
7176  $this->debug('in buildVal, no children, building scalar');
7177  $cdata = isset($this->message[$pos]['cdata']) ? $this->message[$pos]['cdata'] : '';
7178  if (isset($this->message[$pos]['type'])) {
7179  $ret = $this->decodeSimple($cdata, $this->message[$pos]['type'], isset($this->message[$pos]['type_namespace']) ? $this->message[$pos]['type_namespace'] : '');
7180  $this->debug("in buildVal, return: $ret");
7181  return $ret;
7182  }
7183  $parent = $this->message[$pos]['parent'];
7184  if (isset($this->message[$parent]['type']) && ($this->message[$parent]['type'] == 'array') && isset($this->message[$parent]['arrayType'])) {
7185  $ret = $this->decodeSimple($cdata, $this->message[$parent]['arrayType'], isset($this->message[$parent]['arrayTypeNamespace']) ? $this->message[$parent]['arrayTypeNamespace'] : '');
7186  $this->debug("in buildVal, return: $ret");
7187  return $ret;
7188  }
7189  $ret = $this->message[$pos]['cdata'];
7190  $this->debug("in buildVal, return: $ret");
7191  return $ret;
7192  }
7193  }
7194 }
7195 
7200 {
7201 }
7202 
7203 ?><?php
7204 
7205 
7206 
7228 {
7229  public $return;
7230  public $wsdl;
7231  public $wsdlFile;
7232  public $opData;
7233  public $operation;
7234  public $username = ''; // Username for HTTP authentication
7235  public $password = ''; // Password for HTTP authentication
7236  public $authtype = ''; // Type of HTTP authentication
7237  public $certRequest = array(); // Certificate for HTTP SSL authentication
7238  public $requestHeaders = false; // SOAP headers in request (text)
7239  public $responseHeaders = ''; // SOAP headers from response (incomplete namespace resolution) (text)
7240  public $responseHeader = null; // SOAP Header from response (parsed)
7241  public $document = ''; // SOAP body response portion (incomplete namespace resolution) (text)
7242  public $endpoint;
7243  public $forceEndpoint = ''; // overrides WSDL endpoint
7244  public $proxyhost = '';
7245  public $proxyport = '';
7246  public $proxyusername = '';
7247  public $proxypassword = '';
7248  public $xml_encoding = ''; // character set encoding of incoming (response) messages
7249  public $http_encoding = false;
7250  public $timeout = 0; // HTTP connection timeout
7251  public $response_timeout = 30; // HTTP response timeout
7252  public $endpointType = ''; // soap|wsdl, empty for WSDL initialization error
7253  public $persistentConnection = false;
7254  public $defaultRpcParams = false; // This is no longer used
7255  public $request = ''; // HTTP request
7256  public $response = ''; // HTTP response
7257  public $responseData = ''; // SOAP payload of response
7258  public $cookies = array(); // Cookies from response or for request
7259  public $decode_utf8 = true; // toggles whether the parser decodes element content w/ utf8_decode()
7260  public $operations = array(); // WSDL operations, empty for WSDL initialization error
7261  public $curl_options = array(); // User-specified cURL options
7262  public $bindingType = ''; // WSDL operation binding type
7263  public $use_curl = false; // whether to always try to use cURL
7264 
7265  /*
7266  * fault related variables
7267  */
7272  public $fault;
7277  public $faultcode;
7288 
7303  public function __construct($endpoint, $wsdl = false, $proxyhost = false, $proxyport = false, $proxyusername = false, $proxypassword = false, $timeout = 0, $response_timeout = 30)
7304  {
7306  $this->endpoint = $endpoint;
7307  $this->proxyhost = $proxyhost;
7308  $this->proxyport = $proxyport;
7309  $this->proxyusername = $proxyusername;
7310  $this->proxypassword = $proxypassword;
7311  $this->timeout = $timeout;
7312  $this->response_timeout = $response_timeout;
7313 
7314  $this->debug("ctor wsdl=$wsdl timeout=$timeout response_timeout=$response_timeout");
7315  $this->appendDebug('endpoint=' . $this->varDump($endpoint));
7316 
7317  // make values
7318  if ($wsdl) {
7319  if (is_object($endpoint) && (get_class($endpoint) == 'wsdl')) {
7320  $this->wsdl = $endpoint;
7321  $this->endpoint = $this->wsdl->wsdl;
7322  $this->wsdlFile = $this->endpoint;
7323  $this->debug('existing wsdl instance created from ' . $this->endpoint);
7324  $this->checkWSDL();
7325  } else {
7326  $this->wsdlFile = $this->endpoint;
7327  $this->wsdl = null;
7328  $this->debug('will use lazy evaluation of wsdl from ' . $this->endpoint);
7329  }
7330  $this->endpointType = 'wsdl';
7331  } else {
7332  $this->debug("instantiate SOAP with endpoint at $endpoint");
7333  $this->endpointType = 'soap';
7334  }
7335  }
7336 
7362  public function call($operation, $params=array(), $namespace='http://tempuri.org', $soapAction='', $headers=false, $rpcParams=null, $style='rpc', $use='encoded')
7363  {
7364  $this->operation = $operation;
7365  $this->fault = false;
7366  $this->setError('');
7367  $this->request = '';
7368  $this->response = '';
7369  $this->responseData = '';
7370  $this->faultstring = '';
7371  $this->faultcode = '';
7372  $this->opData = array();
7373 
7374  $this->debug("call: operation=$operation, namespace=$namespace, soapAction=$soapAction, rpcParams=$rpcParams, style=$style, use=$use, endpointType=$this->endpointType");
7375  $this->appendDebug('params=' . $this->varDump($params));
7376  $this->appendDebug('headers=' . $this->varDump($headers));
7377  if ($headers) {
7378  $this->requestHeaders = $headers;
7379  }
7380  if ($this->endpointType == 'wsdl' && is_null($this->wsdl)) {
7381  $this->loadWSDL();
7382  if ($this->getError()) {
7383  return false;
7384  }
7385  }
7386  // serialize parameters
7387  if ($this->endpointType == 'wsdl' && $opData = $this->getOperationData($operation)) {
7388  // use WSDL for operation
7389  $this->opData = $opData;
7390  $this->debug("found operation");
7391  $this->appendDebug('opData=' . $this->varDump($opData));
7392  if (isset($opData['soapAction'])) {
7393  $soapAction = $opData['soapAction'];
7394  }
7395  if (! $this->forceEndpoint) {
7396  $this->endpoint = $opData['endpoint'];
7397  } else {
7398  $this->endpoint = $this->forceEndpoint;
7399  }
7400  $namespace = isset($opData['input']['namespace']) ? $opData['input']['namespace'] : $namespace;
7401  $style = $opData['style'];
7402  $use = $opData['input']['use'];
7403  // add ns to ns array
7404  if ($namespace != '' && !isset($this->wsdl->namespaces[$namespace])) {
7405  $nsPrefix = 'ns' . rand(1000, 9999);
7406  $this->wsdl->namespaces[$nsPrefix] = $namespace;
7407  }
7408  $nsPrefix = $this->wsdl->getPrefixFromNamespace($namespace);
7409  // serialize payload
7410  if (is_string($params)) {
7411  $this->debug("serializing param string for WSDL operation $operation");
7412  $payload = $params;
7413  } elseif (is_array($params)) {
7414  $this->debug("serializing param array for WSDL operation $operation");
7415  $payload = $this->wsdl->serializeRPCParameters($operation, 'input', $params, $this->bindingType);
7416  } else {
7417  $this->debug('params must be array or string');
7418  $this->setError('params must be array or string');
7419  return false;
7420  }
7421  $usedNamespaces = $this->wsdl->usedNamespaces;
7422  if (isset($opData['input']['encodingStyle'])) {
7423  $encodingStyle = $opData['input']['encodingStyle'];
7424  } else {
7425  $encodingStyle = '';
7426  }
7427  $this->appendDebug($this->wsdl->getDebug());
7428  $this->wsdl->clearDebug();
7429  if ($errstr = $this->wsdl->getError()) {
7430  $this->debug('got wsdl error: ' . $errstr);
7431  $this->setError('wsdl error: ' . $errstr);
7432  return false;
7433  }
7434  } elseif ($this->endpointType == 'wsdl') {
7435  // operation not in WSDL
7436  $this->appendDebug($this->wsdl->getDebug());
7437  $this->wsdl->clearDebug();
7438  $this->setError('operation ' . $operation . ' not present.');
7439  $this->debug("operation '$operation' not present.");
7440  return false;
7441  } else {
7442  // no WSDL
7443  //$this->namespaces['ns1'] = $namespace;
7444  $nsPrefix = 'ns' . rand(1000, 9999);
7445  // serialize
7446  $payload = '';
7447  if (is_string($params)) {
7448  $this->debug("serializing param string for operation $operation");
7449  $payload = $params;
7450  } elseif (is_array($params)) {
7451  $this->debug("serializing param array for operation $operation");
7452  foreach ($params as $k => $v) {
7453  $payload .= $this->serialize_val($v, $k, false, false, false, false, $use);
7454  }
7455  } else {
7456  $this->debug('params must be array or string');
7457  $this->setError('params must be array or string');
7458  return false;
7459  }
7460  $usedNamespaces = array();
7461  if ($use == 'encoded') {
7462  $encodingStyle = 'http://schemas.xmlsoap.org/soap/encoding/';
7463  } else {
7464  $encodingStyle = '';
7465  }
7466  }
7467  // wrap RPC calls with method element
7468  if ($style == 'rpc') {
7469  if ($use == 'literal') {
7470  $this->debug("wrapping RPC request with literal method element");
7471  if ($namespace) {
7472  // 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
7473  $payload = "<$nsPrefix:$operation xmlns:$nsPrefix=\"$namespace\">" .
7474  $payload .
7475  "</$nsPrefix:$operation>";
7476  } else {
7477  $payload = "<$operation>" . $payload . "</$operation>";
7478  }
7479  } else {
7480  $this->debug("wrapping RPC request with encoded method element");
7481  if ($namespace) {
7482  $payload = "<$nsPrefix:$operation xmlns:$nsPrefix=\"$namespace\">" .
7483  $payload .
7484  "</$nsPrefix:$operation>";
7485  } else {
7486  $payload = "<$operation>" .
7487  $payload .
7488  "</$operation>";
7489  }
7490  }
7491  }
7492  // serialize envelope
7493  $soapmsg = $this->serializeEnvelope($payload, $this->requestHeaders, $usedNamespaces, $style, $use, $encodingStyle);
7494  $this->debug("endpoint=$this->endpoint, soapAction=$soapAction, namespace=$namespace, style=$style, use=$use, encodingStyle=$encodingStyle");
7495  $this->debug('SOAP message length=' . strlen($soapmsg) . ' contents (max 1000 bytes)=' . substr($soapmsg, 0, 1000));
7496  // send
7497  $return = $this->send($this->getHTTPBody($soapmsg), $soapAction, $this->timeout, $this->response_timeout);
7498  if ($errstr = $this->getError()) {
7499  $this->debug('Error: ' . $errstr);
7500  return false;
7501  } else {
7502  $this->return = $return;
7503  $this->debug('sent message successfully and got a(n) ' . gettype($return));
7504  $this->appendDebug('return=' . $this->varDump($return));
7505 
7506  // fault?
7507  if (is_array($return) && isset($return['faultcode'])) {
7508  $this->debug('got fault');
7509  $this->setError($return['faultcode'] . ': ' . $return['faultstring']);
7510  $this->fault = true;
7511  foreach ($return as $k => $v) {
7512  $this->$k = $v;
7513  $this->debug("$k = $v<br>");
7514  }
7515  return $return;
7516  } elseif ($style == 'document') {
7517  // NOTE: if the response is defined to have multiple parts (i.e. unwrapped),
7518  // we are only going to return the first part here...sorry about that
7519  return $return;
7520  } else {
7521  // array of return values
7522  if (is_array($return)) {
7523  // multiple 'out' parameters, which we return wrapped up
7524  // in the array
7525  if (sizeof($return) > 1) {
7526  return $return;
7527  }
7528  // single 'out' parameter (normally the return value)
7529  $return = array_shift($return);
7530  $this->debug('return shifted value: ');
7531  $this->appendDebug($this->varDump($return));
7532  return $return;
7533  // nothing returned (ie, echoVoid)
7534  } else {
7535  return "";
7536  }
7537  }
7538  }
7539  }
7540 
7546  public function checkWSDL()
7547  {
7548  $this->appendDebug($this->wsdl->getDebug());
7549  $this->wsdl->clearDebug();
7550  $this->debug('checkWSDL');
7551  // catch errors
7552  if ($errstr = $this->wsdl->getError()) {
7553  $this->debug('got wsdl error: ' . $errstr);
7554  $this->setError('wsdl error: ' . $errstr);
7555  } elseif ($this->operations = $this->wsdl->getOperations('soap')) {
7556  $this->bindingType = 'soap';
7557  $this->debug('got ' . count($this->operations) . ' operations from wsdl ' . $this->wsdlFile . ' for binding type ' . $this->bindingType);
7558  } elseif ($this->operations = $this->wsdl->getOperations('soap12')) {
7559  $this->bindingType = 'soap12';
7560  $this->debug('got ' . count($this->operations) . ' operations from wsdl ' . $this->wsdlFile . ' for binding type ' . $this->bindingType);
7561  $this->debug('**************** WARNING: SOAP 1.2 BINDING *****************');
7562  } else {
7563  $this->debug('getOperations returned false');
7564  $this->setError('no operations defined in the WSDL document!');
7565  }
7566  }
7567 
7573  public function loadWSDL()
7574  {
7575  $this->debug('instantiating wsdl class with doc: ' . $this->wsdlFile);
7576  $this->wsdl = new wsdl('', $this->proxyhost, $this->proxyport, $this->proxyusername, $this->proxypassword, $this->timeout, $this->response_timeout, $this->curl_options, $this->use_curl);
7577  $this->wsdl->setCredentials($this->username, $this->password, $this->authtype, $this->certRequest);
7578  $this->wsdl->fetchWSDL($this->wsdlFile);
7579  $this->checkWSDL();
7580  }
7581 
7589  public function getOperationData($operation)
7590  {
7591  if ($this->endpointType == 'wsdl' && is_null($this->wsdl)) {
7592  $this->loadWSDL();
7593  if ($this->getError()) {
7594  return false;
7595  }
7596  }
7597  if (isset($this->operations[$operation])) {
7598  return $this->operations[$operation];
7599  }
7600  $this->debug("No data for operation: $operation");
7601  }
7602 
7617  public function send($msg, $soapaction = '', $timeout=0, $response_timeout=30)
7618  {
7619  $this->checkCookies();
7620  // detect transport
7621  switch (true) {
7622  // http(s)
7623  case preg_match('/^http/', $this->endpoint):
7624  $this->debug('transporting via HTTP');
7625  if ($this->persistentConnection == true && is_object($this->persistentConnection)) {
7626  $http =& $this->persistentConnection;
7627  } else {
7628  $http = new soap_transport_http($this->endpoint, $this->curl_options, $this->use_curl);
7629  if ($this->persistentConnection) {
7630  $http->usePersistentConnection();
7631  }
7632  }
7633  $http->setContentType($this->getHTTPContentType(), $this->getHTTPContentTypeCharset());
7634  $http->setSOAPAction($soapaction);
7635  if ($this->proxyhost && $this->proxyport) {
7636  $http->setProxy($this->proxyhost, $this->proxyport, $this->proxyusername, $this->proxypassword);
7637  }
7638  if ($this->authtype != '') {
7639  $http->setCredentials($this->username, $this->password, $this->authtype, array(), $this->certRequest);
7640  }
7641  if ($this->http_encoding != '') {
7642  $http->setEncoding($this->http_encoding);
7643  }
7644  $this->debug('sending message, length=' . strlen($msg));
7645  if (preg_match('/^http:/', $this->endpoint)) {
7646  //if(strpos($this->endpoint,'http:')){
7647  $this->responseData = $http->send($msg, $timeout, $response_timeout, $this->cookies);
7648  } elseif (preg_match('/^https/', $this->endpoint)) {
7649  //} elseif(strpos($this->endpoint,'https:')){
7650  //if(phpversion() == '4.3.0-dev'){
7651  //$response = $http->send($msg,$timeout,$response_timeout);
7652  //$this->request = $http->outgoing_payload;
7653  //$this->response = $http->incoming_payload;
7654  //} else
7655  $this->responseData = $http->sendHTTPS($msg, $timeout, $response_timeout, $this->cookies);
7656  } else {
7657  $this->setError('no http/s in endpoint url');
7658  }
7659  $this->request = $http->outgoing_payload;
7660  $this->response = $http->incoming_payload;
7661  $this->appendDebug($http->getDebug());
7662  $this->UpdateCookies($http->incoming_cookies);
7663 
7664  // save transport object if using persistent connections
7665  if ($this->persistentConnection) {
7666  $http->clearDebug();
7667  if (!is_object($this->persistentConnection)) {
7668  $this->persistentConnection = $http;
7669  }
7670  }
7671 
7672  if ($err = $http->getError()) {
7673  $this->setError('HTTP Error: ' . $err);
7674  return false;
7675  } elseif ($this->getError()) {
7676  return false;
7677  } else {
7678  $this->debug('got response, length=' . strlen($this->responseData) . ' type=' . $http->incoming_headers['content-type']);
7679  return $this->parseResponse($http->incoming_headers, $this->responseData);
7680  }
7681  break;
7682  default:
7683  $this->setError('no transport found, or selected transport is not yet supported!');
7684  return false;
7685  break;
7686  }
7687  }
7688 
7697  public function parseResponse($headers, $data)
7698  {
7699  $this->debug('Entering parseResponse() for data of length ' . strlen($data) . ' headers:');
7700  $this->appendDebug($this->varDump($headers));
7701  if (!strstr($headers['content-type'], 'text/xml')) {
7702  $this->setError('Response not of type text/xml: ' . $headers['content-type']);
7703  return false;
7704  }
7705  if (strpos($headers['content-type'], '=')) {
7706  $enc = str_replace('"', '', substr(strstr($headers["content-type"], '='), 1));
7707  $this->debug('Got response encoding: ' . $enc);
7708  if (preg_match('/^(ISO-8859-1|US-ASCII|UTF-8)$/i', $enc)) {
7709  $this->xml_encoding = strtoupper($enc);
7710  } else {
7711  $this->xml_encoding = 'US-ASCII';
7712  }
7713  } else {
7714  // should be US-ASCII for HTTP 1.0 or ISO-8859-1 for HTTP 1.1
7715  $this->xml_encoding = 'ISO-8859-1';
7716  }
7717  $this->debug('Use encoding: ' . $this->xml_encoding . ' when creating nusoap_parser');
7718  $parser = new nusoap_parser($data, $this->xml_encoding, $this->operation, $this->decode_utf8);
7719  // add parser debug data to our debug
7720  $this->appendDebug($parser->getDebug());
7721  // if parse errors
7722  if ($errstr = $parser->getError()) {
7723  $this->setError($errstr);
7724  // destroy the parser object
7725  unset($parser);
7726  return false;
7727  } else {
7728  // get SOAP headers
7729  $this->responseHeaders = $parser->getHeaders();
7730  // get SOAP headers
7731  $this->responseHeader = $parser->get_soapheader();
7732  // get decoded message
7733  $return = $parser->get_soapbody();
7734  // add document for doclit support
7735  $this->document = $parser->document;
7736  // destroy the parser object
7737  unset($parser);
7738  // return decode message
7739  return $return;
7740  }
7741  }
7742 
7750  public function setCurlOption($option, $value)
7751  {
7752  $this->debug("setCurlOption option=$option, value=");
7753  $this->appendDebug($this->varDump($value));
7754  $this->curl_options[$option] = $value;
7755  }
7756 
7763  public function setEndpoint($endpoint)
7764  {
7765  $this->debug("setEndpoint(\"$endpoint\")");
7766  $this->forceEndpoint = $endpoint;
7767  }
7768 
7775  public function setHeaders($headers)
7776  {
7777  $this->debug("setHeaders headers=");
7778  $this->appendDebug($this->varDump($headers));
7779  $this->requestHeaders = $headers;
7780  }
7781 
7788  public function getHeaders()
7789  {
7790  return $this->responseHeaders;
7791  }
7792 
7799  public function getHeader()
7800  {
7801  return $this->responseHeader;
7802  }
7803 
7813  public function setHTTPProxy($proxyhost, $proxyport, $proxyusername = '', $proxypassword = '')
7814  {
7815  $this->proxyhost = $proxyhost;
7816  $this->proxyport = $proxyport;
7817  $this->proxyusername = $proxyusername;
7818  $this->proxypassword = $proxypassword;
7819  }
7820 
7830  public function setCredentials($username, $password, $authtype = 'basic', $certRequest = array())
7831  {
7832  $this->debug("setCredentials username=$username authtype=$authtype certRequest=");
7833  $this->appendDebug($this->varDump($certRequest));
7834  $this->username = $username;
7835  $this->password = $password;
7836  $this->authtype = $authtype;
7837  $this->certRequest = $certRequest;
7838  }
7839 
7846  public function setHTTPEncoding($enc='gzip, deflate')
7847  {
7848  $this->debug("setHTTPEncoding(\"$enc\")");
7849  $this->http_encoding = $enc;
7850  }
7851 
7858  public function setUseCURL($use)
7859  {
7860  $this->debug("setUseCURL($use)");
7861  $this->use_curl = $use;
7862  }
7863 
7870  {
7871  $this->debug("useHTTPPersistentConnection");
7872  $this->persistentConnection = true;
7873  }
7874 
7886  public function getDefaultRpcParams()
7887  {
7888  return $this->defaultRpcParams;
7889  }
7890 
7902  public function setDefaultRpcParams($rpcParams)
7903  {
7904  $this->defaultRpcParams = $rpcParams;
7905  }
7906 
7914  public function getProxy()
7915  {
7916  $r = rand();
7917  $evalStr = $this->_getProxyClassCode($r);
7918  //$this->debug("proxy class: $evalStr");
7919  if ($this->getError()) {
7920  $this->debug("Error from _getProxyClassCode, so return NULL");
7921  return null;
7922  }
7923  // eval the class
7924  eval($evalStr);
7925  // instantiate proxy object
7926  eval("\$proxy = new nusoap_proxy_$r('');");
7927  // transfer current wsdl data to the proxy thereby avoiding parsing the wsdl twice
7928  $proxy->endpointType = 'wsdl';
7929  $proxy->wsdlFile = $this->wsdlFile;
7930  $proxy->wsdl = $this->wsdl;
7931  $proxy->operations = $this->operations;
7932  $proxy->defaultRpcParams = $this->defaultRpcParams;
7933  // transfer other state
7934  $proxy->soap_defencoding = $this->soap_defencoding;
7935  $proxy->username = $this->username;
7936  $proxy->password = $this->password;
7937  $proxy->authtype = $this->authtype;
7938  $proxy->certRequest = $this->certRequest;
7939  $proxy->requestHeaders = $this->requestHeaders;
7940  $proxy->endpoint = $this->endpoint;
7941  $proxy->forceEndpoint = $this->forceEndpoint;
7942  $proxy->proxyhost = $this->proxyhost;
7943  $proxy->proxyport = $this->proxyport;
7944  $proxy->proxyusername = $this->proxyusername;
7945  $proxy->proxypassword = $this->proxypassword;
7946  $proxy->http_encoding = $this->http_encoding;
7947  $proxy->timeout = $this->timeout;
7948  $proxy->response_timeout = $this->response_timeout;
7949  $proxy->persistentConnection = &$this->persistentConnection;
7950  $proxy->decode_utf8 = $this->decode_utf8;
7951  $proxy->curl_options = $this->curl_options;
7952  $proxy->bindingType = $this->bindingType;
7953  $proxy->use_curl = $this->use_curl;
7954  return $proxy;
7955  }
7956 
7963  public function _getProxyClassCode($r)
7964  {
7965  $this->debug("in getProxy endpointType=$this->endpointType");
7966  $this->appendDebug("wsdl=" . $this->varDump($this->wsdl));
7967  if ($this->endpointType != 'wsdl') {
7968  $evalStr = 'A proxy can only be created for a WSDL client';
7969  $this->setError($evalStr);
7970  $evalStr = "echo \"$evalStr\";";
7971  return $evalStr;
7972  }
7973  if ($this->endpointType == 'wsdl' && is_null($this->wsdl)) {
7974  $this->loadWSDL();
7975  if ($this->getError()) {
7976  return "echo \"" . $this->getError() . "\";";
7977  }
7978  }
7979  $evalStr = '';
7980  foreach ($this->operations as $operation => $opData) {
7981  if ($operation != '') {
7982  // create param string and param comment string
7983  if (sizeof($opData['input']['parts']) > 0) {
7984  $paramStr = '';
7985  $paramArrayStr = '';
7986  $paramCommentStr = '';
7987  foreach ($opData['input']['parts'] as $name => $type) {
7988  $paramStr .= "\$$name, ";
7989  $paramArrayStr .= "'$name' => \$$name, ";
7990  $paramCommentStr .= "$type \$$name, ";
7991  }
7992  $paramStr = substr($paramStr, 0, strlen($paramStr)-2);
7993  $paramArrayStr = substr($paramArrayStr, 0, strlen($paramArrayStr)-2);
7994  $paramCommentStr = substr($paramCommentStr, 0, strlen($paramCommentStr)-2);
7995  } else {
7996  $paramStr = '';
7997  $paramArrayStr = '';
7998  $paramCommentStr = 'void';
7999  }
8000  $opData['namespace'] = !isset($opData['namespace']) ? 'http://testuri.com' : $opData['namespace'];
8001  $evalStr .= "// $paramCommentStr
8002  function " . str_replace('.', '__', $operation) . "($paramStr) {
8003  \$params = array($paramArrayStr);
8004  return \$this->call('$operation', \$params, '" . $opData['namespace'] . "', '" . (isset($opData['soapAction']) ? $opData['soapAction'] : '') . "');
8005  }
8006  ";
8007  unset($paramStr);
8008  unset($paramCommentStr);
8009  }
8010  }
8011  $evalStr = 'class nusoap_proxy_' . $r . ' extends nusoap_client {
8012  ' . $evalStr . '
8013 }';
8014  return $evalStr;
8015  }
8016 
8023  public function getProxyClassCode()
8024  {
8025  $r = rand();
8026  return $this->_getProxyClassCode($r);
8027  }
8028 
8036  public function getHTTPBody($soapmsg)
8037  {
8038  return $soapmsg;
8039  }
8040 
8049  public function getHTTPContentType()
8050  {
8051  return 'text/xml';
8052  }
8053 
8063  public function getHTTPContentTypeCharset()
8064  {
8065  return $this->soap_defencoding;
8066  }
8067 
8068  /*
8069  * whether or not parser should decode utf8 element content
8070  *
8071  * @return always returns true
8072  * @access public
8073  */
8074  public function decodeUTF8($bool)
8075  {
8076  $this->decode_utf8 = $bool;
8077  return true;
8078  }
8079 
8088  public function setCookie($name, $value)
8089  {
8090  if (strlen($name) == 0) {
8091  return false;
8092  }
8093  $this->cookies[] = array('name' => $name, 'value' => $value);
8094  return true;
8095  }
8096 
8103  public function getCookies()
8104  {
8105  return $this->cookies;
8106  }
8107 
8114  public function checkCookies()
8115  {
8116  if (sizeof($this->cookies) == 0) {
8117  return true;
8118  }
8119  $this->debug('checkCookie: check ' . sizeof($this->cookies) . ' cookies');
8120  $curr_cookies = $this->cookies;
8121  $this->cookies = array();
8122  foreach ($curr_cookies as $cookie) {
8123  if (! is_array($cookie)) {
8124  $this->debug('Remove cookie that is not an array');
8125  continue;
8126  }
8127  if ((isset($cookie['expires'])) && (! empty($cookie['expires']))) {
8128  if (strtotime($cookie['expires']) > time()) {
8129  $this->cookies[] = $cookie;
8130  } else {
8131  $this->debug('Remove expired cookie ' . $cookie['name']);
8132  }
8133  } else {
8134  $this->cookies[] = $cookie;
8135  }
8136  }
8137  $this->debug('checkCookie: ' . sizeof($this->cookies) . ' cookies left in array');
8138  return true;
8139  }
8140 
8148  public function UpdateCookies($cookies)
8149  {
8150  if (sizeof($this->cookies) == 0) {
8151  // no existing cookies: take whatever is new
8152  if (sizeof($cookies) > 0) {
8153  $this->debug('Setting new cookie(s)');
8154  $this->cookies = $cookies;
8155  }
8156  return true;
8157  }
8158  if (sizeof($cookies) == 0) {
8159  // no new cookies: keep what we've got
8160  return true;
8161  }
8162  // merge
8163  foreach ($cookies as $newCookie) {
8164  if (!is_array($newCookie)) {
8165  continue;
8166  }
8167  if ((!isset($newCookie['name'])) || (!isset($newCookie['value']))) {
8168  continue;
8169  }
8170  $newName = $newCookie['name'];
8171 
8172  $found = false;
8173  for ($i = 0; $i < count($this->cookies); $i++) {
8174  $cookie = $this->cookies[$i];
8175  if (!is_array($cookie)) {
8176  continue;
8177  }
8178  if (!isset($cookie['name'])) {
8179  continue;
8180  }
8181  if ($newName != $cookie['name']) {
8182  continue;
8183  }
8184  $newDomain = isset($newCookie['domain']) ? $newCookie['domain'] : 'NODOMAIN';
8185  $domain = isset($cookie['domain']) ? $cookie['domain'] : 'NODOMAIN';
8186  if ($newDomain != $domain) {
8187  continue;
8188  }
8189  $newPath = isset($newCookie['path']) ? $newCookie['path'] : 'NOPATH';
8190  $path = isset($cookie['path']) ? $cookie['path'] : 'NOPATH';
8191  if ($newPath != $path) {
8192  continue;
8193  }
8194  $this->cookies[$i] = $newCookie;
8195  $found = true;
8196  $this->debug('Update cookie ' . $newName . '=' . $newCookie['value']);
8197  break;
8198  }
8199  if (! $found) {
8200  $this->debug('Add cookie ' . $newName . '=' . $newCookie['value']);
8201  $this->cookies[] = $newCookie;
8202  }
8203  }
8204  return true;
8205  }
8206 }
8207 
8208 if (!extension_loaded('soap')) {
8212  class soapclient extends nusoap_client
8213  {
8214  }
8215 }
8216 ?>
serialize($use='encoded')
return serialized value
Definition: nusoap.php:2151
connect($connection_timeout=0, $response_timeout=30)
establish an HTTP connection
Definition: nusoap.php:2356
if($err=$client->getError()) $namespace
addSimpleType($name, $restrictionBase='', $typeClass='simpleType', $phpType='scalar', $enumeration=array())
adds an XML Schema simple type to the WSDL types
Definition: nusoap.php:6445
appendDebug($string)
adds debug data to the instance debug string without formatting
Definition: nusoap.php:303
$currentBinding
Definition: nusoap.php:4648
Backward compatibility.
Definition: nusoap.php:4613
setDebugLevel($level)
sets the debug level for this instance
Definition: nusoap.php:279
send($data, $timeout=0, $response_timeout=30, $cookies=null)
sends the SOAP request and gets the SOAP response via HTTP[S]
Definition: nusoap.php:2599
$res
Definition: ltiservices.php:69
setHeader($name, $value)
sets an HTTP header
Definition: nusoap.php:2266
setCredentials($username, $password, $authtype='basic', $digestRequest=array(), $certRequest=array())
if authenticating, set user credentials here
Definition: nusoap.php:2655
setDefaultRpcParams($rpcParams)
sets the default RPC parameter setting.
Definition: nusoap.php:7902
& getDebugAsXMLComment()
gets the current debug data for this instance as an XML comment this may change the contents of the d...
Definition: nusoap.php:344
getmicrotime()
returns the time in ODBC canonical form with microseconds
Definition: nusoap.php:887
setError($str)
sets error string
Definition: nusoap.php:393
parseString($xml, $type)
parse an XML string
Definition: nusoap.php:1224
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:5313
$wsdl
Definition: nusoap.php:4636
decodeChunked($buffer, $lb)
decode a string that is encoded w/ "chunked&#39; transfer encoding as defined in RFC2068 19...
Definition: nusoap.php:2825
Contains information for a SOAP fault.
Definition: nusoap.php:1033
decodeSimple($value, $type, $typens)
decodes simple types into PHP variables
Definition: nusoap.php:7042
end_element($parser, $name)
end-element handler
Definition: nusoap.php:6863
getHTTPBody($soapmsg)
gets the HTTP body for the current response.
Definition: nusoap.php:4375
$scope
Definition: ltiregstart.php:51
transport class for sending/receiving data via HTTP and HTTPS NOTE: PHP must be compiled with the CUR...
Definition: nusoap.php:2183
& getDebug()
gets the current debug data for this instance
Definition: nusoap.php:330
__construct($schema='', $xml='', $namespaces=array())
constructor
Definition: nusoap.php:1164
decodeUTF8($bool)
Definition: nusoap.php:8074
if(empty($path)) $serviceName
Definition: ltiservices.php:37
start_element($parser, $name, $attrs)
start-element handler
Definition: nusoap.php:6707
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:6397
getDebugLevel()
gets the debug level for this instance
Definition: nusoap.php:268
addSimpleType($name, $restrictionBase='', $typeClass='simpleType', $phpType='scalar', $enumeration=array())
adds a simple type to the schema
Definition: nusoap.php:2021
isArraySimpleOrStruct($val)
detect if array is a simple array or a struct (associative array)
Definition: nusoap.php:405
iso8601_to_timestamp($datestr)
convert ISO 8601 compliant date string to unix timestamp
Definition: nusoap.php:969
getProxyClassCode()
dynamically creates proxy class code
Definition: nusoap.php:8023
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 a WSDL file, allows access to it&#39;s data, other utility methods.
Definition: nusoap.php:4630
get_soapbody()
get the parsed SOAP Body (NULL if there was none)
Definition: nusoap.php:7006
if($clientAssertionType !='urn:ietf:params:oauth:client-assertion-type:jwt-bearer'|| $grantType !='client_credentials') $parts
Definition: ltitoken.php:61
character_data($parser, $data)
element content handler
Definition: nusoap.php:5166
setProxy($proxyhost, $proxyport, $proxyusername='', $proxypassword='', $proxyauthtype='basic')
set proxy info here
Definition: nusoap.php:2766
setEncoding($enc='gzip, deflate')
use http encoding
Definition: nusoap.php:2741
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:1919
$location
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
Definition: buildRTE.php:22
parseFile($xml, $type)
parse an XML file
Definition: nusoap.php:1197
getCookies()
gets all Cookies
Definition: nusoap.php:8103
addComplexType($name, $typeClass='complexType', $phpType='array', $compositor='', $restrictionBase='', $elements=array(), $attrs=array(), $arrayType='')
adds a complex type to the schema
Definition: nusoap.php:1992
parseWSDL($wsdl='')
parses the wsdl document
Definition: nusoap.php:4817
if(! $DIC->user() ->getId()||!ilLTIConsumerAccess::hasCustomProviderCreationAccess()) $params
Definition: ltiregstart.php:31
buildVal($pos)
builds response structures for compound values (arrays/structs) and scalars
Definition: nusoap.php:7087
getOperationDataForSoapAction($soapAction, $bindingType='soap')
returns an associative array of data necessary for calling an operation
Definition: nusoap.php:5274
if(count($parts) !=3) $payload
Definition: ltitoken.php:67
setCookie($name, $value)
adds a new Cookie into $this->cookies array
Definition: nusoap.php:8088
getGlobalDebugLevel()
gets the global debug level, which applies to future instances
Definition: nusoap.php:246
useHTTPPersistentConnection()
use HTTP persistent connections if possible
Definition: nusoap.php:7869
parseResponse($headers, $data)
processes SOAP message returned from server
Definition: nusoap.php:7697
$currentSchema
Definition: nusoap.php:4639
send_response()
sends an HTTP response
Definition: nusoap.php:4223
checkWSDL()
check WSDL passed as an instance or pulled from an endpoint
Definition: nusoap.php:7546
$currentPortType
Definition: nusoap.php:4646
$XMLSchemaVersion
Definition: nusoap.php:153
Backward compatibility.
Definition: nusoap.php:1108
usleepWindows($usec)
sleeps some number of microseconds
Definition: nusoap.php:1010
nusoap_server allows the user to create a SOAP server that is capable of receiving messages and retur...
Definition: nusoap.php:3520
$response
Definition: xapitoken.php:90
send($msg, $soapaction='', $timeout=0, $response_timeout=30)
send the SOAP message
Definition: nusoap.php:7617
$parser
Definition: nusoap.php:4658
parse_request($data='')
parses a request
Definition: nusoap.php:3936
getDefaultRpcParams()
gets the default RPC parameter setting.
Definition: nusoap.php:7886
buildPayload($data, $cookie_str='')
Writes the payload, including HTTP headers, to $this->outgoing_payload.
Definition: nusoap.php:2883
serializeComplexTypeElements($typeDef, $value, $ns, $uqType, $use='encoded', $encodingStyle=false)
serializes the elements for a complexType
Definition: nusoap.php:6294
$url
Definition: shib_logout.php:63
getLocalPart($str)
returns the local part of a prefixed string returns the original string, if not prefixed ...
Definition: nusoap.php:819
fault($faultcode, $faultstring, $faultactor='', $faultdetail='')
Specify a fault to be returned to the client.
Definition: nusoap.php:4505
get_response()
get the parsed message (SOAP Body)
Definition: nusoap.php:6995
$responseData
getTypeDef($type)
returns an associative array of information about a given type returns false if no type exists by the...
Definition: nusoap.php:1805
$http
Definition: deliver.php:14
setContentType($type, $charset=false)
sets the content-type for the SOAP message to be sent
Definition: nusoap.php:3366
serialize_return()
serializes the return value from a PHP function into a full SOAP Envelope
Definition: nusoap.php:4130
serialize($debug=0)
serialize the parsed wsdl
Definition: nusoap.php:5512
__construct($wsdl=false)
constructor the optional parameter is a path to a WSDL file that you&#39;d like to bind the server instan...
Definition: nusoap.php:3680
$c
Definition: deliver.php:9
setURL($url)
sets the URL to which to connect
Definition: nusoap.php:2292
schemaStartElement($parser, $name, $attrs)
start-element handler
Definition: nusoap.php:1289
__construct()
constructor
Definition: nusoap.php:235
decode()
decodes a soapval object into a PHP native type
Definition: nusoap.php:2162
end_element($parser, $name)
end-element handler
Definition: nusoap.php:5135
Backward compatibility.
Definition: nusoap.php:2058
getHTTPContentTypeCharset()
gets the HTTP content type charset for the current request.
Definition: nusoap.php:8063
xdebug($string)
adds debug data to the clas level debug string
Definition: nusoap.php:1754
$path
Definition: ltiservices.php:30
For creating serializable abstractions of native PHP types.
Definition: nusoap.php:2077
addElement($attrs)
adds an element to the WSDL types
Definition: nusoap.php:6460
__construct($endpoint, $wsdl=false, $proxyhost=false, $proxyport=false, $proxyusername=false, $proxypassword=false, $timeout=0, $response_timeout=30)
constructor
Definition: nusoap.php:7303
catch(\Exception $e) $req
Definition: xapiproxy.php:78
getError()
returns error string if present
Definition: nusoap.php:379
debug($string)
adds debug data to the instance debug string with formatting
Definition: nusoap.php:290
$element_ns
Definition: nusoap.php:2106
setHeaders($headers)
set the SOAP headers
Definition: nusoap.php:7775
setCurlOption($option, $value)
sets a cURL option
Definition: nusoap.php:2252
addElement($attrs)
adds an element to the schema
Definition: nusoap.php:2042
__construct($xml, $encoding='UTF-8', $method='', $decode_utf8=true)
constructor that actually does the parsing
Definition: nusoap.php:6612
$currentPort
Definition: nusoap.php:4650
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:1771
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
$serviceName
Definition: nusoap.php:4633
Backward compatibility.
Definition: nusoap.php:7199
setEndpoint($endpoint)
sets the SOAP endpoint, which can override WSDL
Definition: nusoap.php:7763
invoke_method()
invokes a PHP function for the requested SOAP method
Definition: nusoap.php:3984
serializeParameters($operation, $direction, $parameters)
serialize a PHP value according to a WSDL message definition
Definition: nusoap.php:5849
checkCookies()
checks all Cookies and delete those which are expired
Definition: nusoap.php:8114
setHTTPProxy($proxyhost, $proxyport, $proxyusername='', $proxypassword='')
set proxy info here
Definition: nusoap.php:7813
__toString()
represents the object as a string
Definition: nusoap.php:922
serializeRPCParameters($operation, $direction, $parameters, $bindingType='soap')
serialize PHP values according to a WSDL message definition contrary to the method name...
Definition: nusoap.php:5754
$GLOBALS["DIC"]
Definition: wac.php:30
getPrefixFromNamespace($ns)
returns the prefix for a given namespace (or prefix) or false if no prefixes registered for the given...
Definition: nusoap.php:870
getHTTPContentType()
gets the HTTP content type for the current response.
Definition: nusoap.php:4388
getHTTPContentType()
gets the HTTP content type for the current request.
Definition: nusoap.php:8049
setGlobalDebugLevel($level)
sets the global debug level, which applies to future instances
Definition: nusoap.php:257
__construct($url, $curl_options=null, $use_curl=false)
constructor
Definition: nusoap.php:2230
expandQname($qname)
expands (changes prefix to namespace) a qualified name
Definition: nusoap.php:793
parses an XML Schema, allows access to it&#39;s data, other utility methods.
Definition: nusoap.php:1125
setCredentials($username, $password, $authtype='basic', $certRequest=array())
if authenticating, set user credentials here
Definition: nusoap.php:5186
setSOAPAction($soapaction)
set the soapaction value
Definition: nusoap.php:2730
verify_method($operation, $request)
takes the value that was created by parsing the request and compares to the method&#39;s signature...
Definition: nusoap.php:4303
nusoap_base
Definition: nusoap.php:94
_getProxyClassCode($r)
dynamically creates proxy class code
Definition: nusoap.php:7963
getHeaders()
get the SOAP response headers (namespace resolution incomplete)
Definition: nusoap.php:7788
$_SERVER['HTTP_HOST']
Definition: raiseError.php:10
webDescription()
prints html description of services
Definition: nusoap.php:5370
parseRequest($headers, $data)
processes SOAP message received from client
Definition: nusoap.php:4323
$currentPortOperation
Definition: nusoap.php:4635
$param
Definition: xapitoken.php:44
isSkippableCurlHeader(&$data)
Test if the given string starts with a header that is to be skipped.
Definition: nusoap.php:2795
$out
Definition: buildRTE.php:24
getCookiesForRequest($cookies, $secure=false)
sort out cookies for the current request
Definition: nusoap.php:3465
[nu]soapclient higher level class for easy usage.
Definition: nusoap.php:7227
__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:4691
__construct($faultcode, $faultactor='', $faultstring='', $faultdetail='')
constructor
Definition: nusoap.php:1068
serializeEnvelope($body, $headers=false, $namespaces=array(), $style='rpc', $use='encoded', $encodingStyle='http://schemas.xmlsoap.org/soap/encoding/')
serializes a message
Definition: nusoap.php:698
serializeType($name, $type, $value, $use='encoded', $encodingStyle=false, $unqualified=false)
serializes a PHP value according a given type definition
Definition: nusoap.php:5927
getHeader()
get the SOAP response Header (parsed)
Definition: nusoap.php:7799
getOperationData($operation)
get available data pertaining to an operation
Definition: nusoap.php:7589
getHTTPBody($soapmsg)
gets the HTTP body for the current request.
Definition: nusoap.php:8036
setHTTPEncoding($enc='gzip, deflate')
use HTTP encoding
Definition: nusoap.php:7846
sendRequest($data, $cookies=null)
sends the SOAP request via HTTP[S]
Definition: nusoap.php:2931
start_element($parser, $name, $attrs)
start-element handler
Definition: nusoap.php:4922
$_GET['cmd']
Definition: lti.php:26
varDump($data)
Returns a string with the output of var_dump.
Definition: nusoap.php:907
getResponse()
gets the SOAP response via HTTP[S]
Definition: nusoap.php:2989
getHeaders()
get the unparsed SOAP Header
Definition: nusoap.php:7028
getPrefix($str)
returns the prefix part of a prefixed string returns false, if not prefixed
Definition: nusoap.php:837
parse_http_headers()
parses HTTP request headers.
Definition: nusoap.php:3807
getOperations($bindingType='soap')
returns an assoc array of operation names => operation data
Definition: nusoap.php:5210
contractQname($qname)
contracts (changes namespace to prefix) a qualified name
Definition: nusoap.php:767
schemaCharacterData($parser, $data)
element content handler
Definition: nusoap.php:1625
setUseCURL($use)
Set whether to try to use cURL connections if possible.
Definition: nusoap.php:7858
foreach($mandatory_scripts as $file) $timestamp
Definition: buildRTE.php:70
character_data($parser, $data)
element content handler
Definition: nusoap.php:6968
formatDump($str)
formats a string to be inserted into an HTML stream
Definition: nusoap.php:754
$attributes
Definition: nusoap.php:2120
serialize()
serialize a fault
Definition: nusoap.php:1083
addInternalPort(string $serviceName, string $url)
Definition: nusoap.php:4596
unsetHeader($name)
unsets an HTTP header
Definition: nusoap.php:2278
$opStatus
Definition: nusoap.php:4634
$soap_defencoding
Definition: nusoap.php:162
CreateTypeName($ename)
gets a type name for an unnamed type
Definition: nusoap.php:1272
usePersistentConnection()
specifies that an HTTP persistent connection should be used
Definition: nusoap.php:3377
$id
plugin.php for ilComponentBuildPluginInfoObjectiveTest::testAddPlugins
Definition: plugin.php:24
__construct(Container $dic, ilPlugin $plugin)
expandEntities($val)
expands entities, e.g.
Definition: nusoap.php:361
parseCookie($cookie_str)
parse an incoming Cookie into it&#39;s parts
Definition: nusoap.php:3398
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:2640
schemaEndElement($parser, $name)
end-element handler
Definition: nusoap.php:1587
serializeComplexTypeAttributes($typeDef, $value, $ns, $uqType)
serializes the attributes for a complexType
Definition: nusoap.php:6231
$a
thx to https://mlocati.github.io/php-cs-fixer-configurator for the examples
__construct($name='soapval', $type=false, $value=-1, $element_ns=false, $type_ns=false, $attributes=false)
constructor
Definition: nusoap.php:2133
getNamespaceFromPrefix($prefix)
pass it a prefix, it returns a namespace
Definition: nusoap.php:853
nusoap_parser class parses SOAP XML messages into native PHP values
Definition: nusoap.php:6565
setCredentials($username, $password, $authtype='basic', $certRequest=array())
if authenticating, set user credentials here
Definition: nusoap.php:7830
serializeSchema()
serialize the schema
Definition: nusoap.php:1636
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:6480
getOperationData($operation, $bindingType='soap')
returns an associative array of data necessary for calling an operation
Definition: nusoap.php:5242
serializeTypeDef($type)
returns a sample serialization of a given type, or false if no type by the given name ...
Definition: nusoap.php:1882
get_soapheader()
get the parsed SOAP Header (NULL if there was none)
Definition: nusoap.php:7017
io_method()
gets the I/O method to use
Definition: nusoap.php:2337
loadWSDL()
instantiate wsdl object and parse wsdl file
Definition: nusoap.php:7573
getProxy()
dynamically creates an instance of a proxy class, allowing user to directly call methods from wsdl ...
Definition: nusoap.php:7914
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:7362
$currentOperation
Definition: nusoap.php:4644
getHTTPContentTypeCharset()
gets the HTTP content type charset for the current response.
Definition: nusoap.php:4402
clearDebug()
clears the current debug data for this instance
Definition: nusoap.php:317
UpdateCookies($cookies)
updates the current cookies with a new set
Definition: nusoap.php:8148
getBindingData($binding)
Definition: nusoap.php:5196
header()
expected output: > ILIAS shows the rendered Component.
Definition: header.php:13
setCurlOption($option, $value)
sets user-specified cURL options
Definition: nusoap.php:7750
fetchWSDL($wsdl)
fetches the WSDL document and parses it
Definition: nusoap.php:4713
parametersMatchWrapped($type, &$parameters)
determine whether a set of parameters are unwrapped when they are expect to be wrapped, Microsoft-style.
Definition: nusoap.php:5660
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:431
timestamp_to_iso8601($timestamp, $utc=true)
convert unix timestamp to ISO 8601 compliant date string
Definition: nusoap.php:939
catch(ilCmiXapiException $e) send($response)
Definition: xapitoken.php:97
$currentMessage
Definition: nusoap.php:4643
$r
service($data)
processes request and returns response
Definition: nusoap.php:3744