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