PageRenderTime 73ms CodeModel.GetById 20ms RepoModel.GetById 0ms app.codeStats 2ms

/htdocs/includes/nusoap/lib/nusoap.php

https://bitbucket.org/speedealing/speedealing
PHP | 8143 lines | 6631 code | 205 blank | 1307 comment | 790 complexity | eeae0107c2945b49de51916cb87adf49 MD5 | raw file
Possible License(s): LGPL-3.0, LGPL-2.1, GPL-3.0, MIT

Large files files are truncated, but you can click here to view the full file

  1. <?php
  2. /*
  3. NuSOAP - Web Services Toolkit for PHP
  4. Copyright (c) 2002 NuSphere Corporation
  5. This library is free software; you can redistribute it and/or
  6. modify it under the terms of the GNU Lesser General Public
  7. License as published by the Free Software Foundation; either
  8. version 2.1 of the License, or (at your option) any later version.
  9. This library is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  12. Lesser General Public License for more details.
  13. You should have received a copy of the GNU Lesser General Public
  14. along with this program. If not, see <http://www.gnu.org/licenses/>.
  15. The NuSOAP project home is:
  16. http://sourceforge.net/projects/nusoap/
  17. The primary support for NuSOAP is the Help forum on the project home page.
  18. If you have any questions or comments, please email:
  19. Dietrich Ayala
  20. dietrich@ganx4.com
  21. http://dietrich.ganx4.com/nusoap
  22. NuSphere Corporation
  23. http://www.nusphere.com
  24. */
  25. /*
  26. * Some of the standards implmented in whole or part by NuSOAP:
  27. *
  28. * SOAP 1.1 (http://www.w3.org/TR/2000/NOTE-SOAP-20000508/)
  29. * WSDL 1.1 (http://www.w3.org/TR/2001/NOTE-wsdl-20010315)
  30. * SOAP Messages With Attachments (http://www.w3.org/TR/SOAP-attachments)
  31. * XML 1.0 (http://www.w3.org/TR/2006/REC-xml-20060816/)
  32. * Namespaces in XML 1.0 (http://www.w3.org/TR/2006/REC-xml-names-20060816/)
  33. * XML Schema 1.0 (http://www.w3.org/TR/xmlschema-0/)
  34. * RFC 2045 Multipurpose Internet Mail Extensions (MIME) Part One: Format of Internet Message Bodies
  35. * RFC 2068 Hypertext Transfer Protocol -- HTTP/1.1
  36. * RFC 2617 HTTP Authentication: Basic and Digest Access Authentication
  37. */
  38. /* load classes
  39. // necessary classes
  40. require_once('class.soapclient.php');
  41. require_once('class.soap_val.php');
  42. require_once('class.soap_parser.php');
  43. require_once('class.soap_fault.php');
  44. // transport classes
  45. require_once('class.soap_transport_http.php');
  46. // optional add-on classes
  47. require_once('class.xmlschema.php');
  48. require_once('class.wsdl.php');
  49. // server class
  50. require_once('class.soap_server.php');*/
  51. // class variable emulation
  52. // cf. http://www.webkreator.com/php/techniques/php-static-class-variables.html
  53. $GLOBALS['_transient']['static']['nusoap_base']['globalDebugLevel'] = 9;
  54. /**
  55. *
  56. * nusoap_base
  57. *
  58. * @author Dietrich Ayala <dietrich@ganx4.com>
  59. * @author Scott Nichol <snichol@users.sourceforge.net>
  60. * @access public
  61. */
  62. class nusoap_base {
  63. /**
  64. * Identification for HTTP headers.
  65. *
  66. * @var string
  67. * @access private
  68. */
  69. var $title = 'NuSOAP';
  70. /**
  71. * Version for HTTP headers.
  72. *
  73. * @var string
  74. * @access private
  75. */
  76. var $version = '0.9.5';
  77. /**
  78. * CVS revision for HTTP headers.
  79. *
  80. * @var string
  81. * @access private
  82. */
  83. var $revision = '1.15';
  84. /**
  85. * Current error string (manipulated by getError/setError)
  86. *
  87. * @var string
  88. * @access private
  89. */
  90. var $error_str = '';
  91. /**
  92. * Current debug string (manipulated by debug/appendDebug/clearDebug/getDebug/getDebugAsXMLComment)
  93. *
  94. * @var string
  95. * @access private
  96. */
  97. var $debug_str = '';
  98. /**
  99. * toggles automatic encoding of special characters as entities
  100. * (should always be true, I think)
  101. *
  102. * @var boolean
  103. * @access private
  104. */
  105. var $charencoding = true;
  106. /**
  107. * the debug level for this instance
  108. *
  109. * @var integer
  110. * @access private
  111. */
  112. var $debugLevel;
  113. /**
  114. * set schema version
  115. *
  116. * @var string
  117. * @access public
  118. */
  119. var $XMLSchemaVersion = 'http://www.w3.org/2001/XMLSchema';
  120. /**
  121. * charset encoding for outgoing messages
  122. *
  123. * @var string
  124. * @access public
  125. */
  126. var $soap_defencoding = 'ISO-8859-1';
  127. //var $soap_defencoding = 'UTF-8';
  128. /**
  129. * namespaces in an array of prefix => uri
  130. *
  131. * this is "seeded" by a set of constants, but it may be altered by code
  132. *
  133. * @var array
  134. * @access public
  135. */
  136. var $namespaces = array(
  137. 'SOAP-ENV' => 'http://schemas.xmlsoap.org/soap/envelope/',
  138. 'xsd' => 'http://www.w3.org/2001/XMLSchema',
  139. 'xsi' => 'http://www.w3.org/2001/XMLSchema-instance',
  140. 'SOAP-ENC' => 'http://schemas.xmlsoap.org/soap/encoding/'
  141. );
  142. /**
  143. * namespaces used in the current context, e.g. during serialization
  144. *
  145. * @var array
  146. * @access private
  147. */
  148. var $usedNamespaces = array();
  149. /**
  150. * XML Schema types in an array of uri => (array of xml type => php type)
  151. * is this legacy yet?
  152. * no, this is used by the nusoap_xmlschema class to verify type => namespace mappings.
  153. * @var array
  154. * @access public
  155. */
  156. var $typemap = array(
  157. 'http://www.w3.org/2001/XMLSchema' => array(
  158. 'string'=>'string','boolean'=>'boolean','float'=>'double','double'=>'double','decimal'=>'double',
  159. 'duration'=>'','dateTime'=>'string','time'=>'string','date'=>'string','gYearMonth'=>'',
  160. 'gYear'=>'','gMonthDay'=>'','gDay'=>'','gMonth'=>'','hexBinary'=>'string','base64Binary'=>'string',
  161. // abstract "any" types
  162. 'anyType'=>'string','anySimpleType'=>'string',
  163. // derived datatypes
  164. 'normalizedString'=>'string','token'=>'string','language'=>'','NMTOKEN'=>'','NMTOKENS'=>'','Name'=>'','NCName'=>'','ID'=>'',
  165. 'IDREF'=>'','IDREFS'=>'','ENTITY'=>'','ENTITIES'=>'','integer'=>'integer','nonPositiveInteger'=>'integer',
  166. 'negativeInteger'=>'integer','long'=>'integer','int'=>'integer','short'=>'integer','byte'=>'integer','nonNegativeInteger'=>'integer',
  167. 'unsignedLong'=>'','unsignedInt'=>'','unsignedShort'=>'','unsignedByte'=>'','positiveInteger'=>''),
  168. 'http://www.w3.org/2000/10/XMLSchema' => array(
  169. 'i4'=>'','int'=>'integer','boolean'=>'boolean','string'=>'string','double'=>'double',
  170. 'float'=>'double','dateTime'=>'string',
  171. 'timeInstant'=>'string','base64Binary'=>'string','base64'=>'string','ur-type'=>'array'),
  172. 'http://www.w3.org/1999/XMLSchema' => array(
  173. 'i4'=>'','int'=>'integer','boolean'=>'boolean','string'=>'string','double'=>'double',
  174. 'float'=>'double','dateTime'=>'string',
  175. 'timeInstant'=>'string','base64Binary'=>'string','base64'=>'string','ur-type'=>'array'),
  176. 'http://soapinterop.org/xsd' => array('SOAPStruct'=>'struct'),
  177. 'http://schemas.xmlsoap.org/soap/encoding/' => array('base64'=>'string','array'=>'array','Array'=>'array'),
  178. 'http://xml.apache.org/xml-soap' => array('Map')
  179. );
  180. /**
  181. * XML entities to convert
  182. *
  183. * @var array
  184. * @access public
  185. * @deprecated
  186. * @see expandEntities
  187. */
  188. var $xmlEntities = array('quot' => '"','amp' => '&',
  189. 'lt' => '<','gt' => '>','apos' => "'");
  190. /**
  191. * constructor
  192. *
  193. * @access public
  194. */
  195. function nusoap_base() {
  196. $this->debugLevel = $GLOBALS['_transient']['static']['nusoap_base']['globalDebugLevel'];
  197. }
  198. /**
  199. * gets the global debug level, which applies to future instances
  200. *
  201. * @return integer Debug level 0-9, where 0 turns off
  202. * @access public
  203. */
  204. function getGlobalDebugLevel() {
  205. return $GLOBALS['_transient']['static']['nusoap_base']['globalDebugLevel'];
  206. }
  207. /**
  208. * sets the global debug level, which applies to future instances
  209. *
  210. * @param int $level Debug level 0-9, where 0 turns off
  211. * @access public
  212. */
  213. function setGlobalDebugLevel($level) {
  214. $GLOBALS['_transient']['static']['nusoap_base']['globalDebugLevel'] = $level;
  215. }
  216. /**
  217. * gets the debug level for this instance
  218. *
  219. * @return int Debug level 0-9, where 0 turns off
  220. * @access public
  221. */
  222. function getDebugLevel() {
  223. return $this->debugLevel;
  224. }
  225. /**
  226. * sets the debug level for this instance
  227. *
  228. * @param int $level Debug level 0-9, where 0 turns off
  229. * @access public
  230. */
  231. function setDebugLevel($level) {
  232. $this->debugLevel = $level;
  233. }
  234. /**
  235. * adds debug data to the instance debug string with formatting
  236. *
  237. * @param string $string debug data
  238. * @access private
  239. */
  240. function debug($string){
  241. if ($this->debugLevel > 0) {
  242. $this->appendDebug($this->getmicrotime().' '.get_class($this).": $string\n");
  243. }
  244. }
  245. /**
  246. * adds debug data to the instance debug string without formatting
  247. *
  248. * @param string $string debug data
  249. * @access public
  250. */
  251. function appendDebug($string){
  252. if ($this->debugLevel > 0) {
  253. // it would be nice to use a memory stream here to use
  254. // memory more efficiently
  255. $this->debug_str .= $string;
  256. }
  257. }
  258. /**
  259. * clears the current debug data for this instance
  260. *
  261. * @access public
  262. */
  263. function clearDebug() {
  264. // it would be nice to use a memory stream here to use
  265. // memory more efficiently
  266. $this->debug_str = '';
  267. }
  268. /**
  269. * gets the current debug data for this instance
  270. *
  271. * @return debug data
  272. * @access public
  273. */
  274. function &getDebug() {
  275. // it would be nice to use a memory stream here to use
  276. // memory more efficiently
  277. return $this->debug_str;
  278. }
  279. /**
  280. * gets the current debug data for this instance as an XML comment
  281. * this may change the contents of the debug data
  282. *
  283. * @return debug data as an XML comment
  284. * @access public
  285. */
  286. function &getDebugAsXMLComment() {
  287. // it would be nice to use a memory stream here to use
  288. // memory more efficiently
  289. while (strpos($this->debug_str, '--')) {
  290. $this->debug_str = str_replace('--', '- -', $this->debug_str);
  291. }
  292. $ret = "<!--\n" . $this->debug_str . "\n-->";
  293. return $ret;
  294. }
  295. /**
  296. * expands entities, e.g. changes '<' to '&lt;'.
  297. *
  298. * @param string $val The string in which to expand entities.
  299. * @access private
  300. */
  301. function expandEntities($val) {
  302. if ($this->charencoding) {
  303. $val = str_replace('&', '&amp;', $val);
  304. $val = str_replace("'", '&apos;', $val);
  305. $val = str_replace('"', '&quot;', $val);
  306. $val = str_replace('<', '&lt;', $val);
  307. $val = str_replace('>', '&gt;', $val);
  308. }
  309. return $val;
  310. }
  311. /**
  312. * returns error string if present
  313. *
  314. * @return mixed error string or false
  315. * @access public
  316. */
  317. function getError(){
  318. if($this->error_str != ''){
  319. return $this->error_str;
  320. }
  321. return false;
  322. }
  323. /**
  324. * sets error string
  325. *
  326. * @return boolean $string error string
  327. * @access private
  328. */
  329. function setError($str){
  330. $this->error_str = $str;
  331. }
  332. /**
  333. * detect if array is a simple array or a struct (associative array)
  334. *
  335. * @param mixed $val The PHP array
  336. * @return string (arraySimple|arrayStruct)
  337. * @access private
  338. */
  339. function isArraySimpleOrStruct($val) {
  340. $keyList = array_keys($val);
  341. foreach ($keyList as $keyListValue) {
  342. if (!is_int($keyListValue)) {
  343. return 'arrayStruct';
  344. }
  345. }
  346. return 'arraySimple';
  347. }
  348. /**
  349. * serializes PHP values in accordance w/ section 5. Type information is
  350. * not serialized if $use == 'literal'.
  351. *
  352. * @param mixed $val The value to serialize
  353. * @param string $name The name (local part) of the XML element
  354. * @param string $type The XML schema type (local part) for the element
  355. * @param string $name_ns The namespace for the name of the XML element
  356. * @param string $type_ns The namespace for the type of the element
  357. * @param array $attributes The attributes to serialize as name=>value pairs
  358. * @param string $use The WSDL "use" (encoded|literal)
  359. * @param boolean $soapval Whether this is called from soapval.
  360. * @return string The serialized element, possibly with child elements
  361. * @access public
  362. */
  363. function serialize_val($val,$name=false,$type=false,$name_ns=false,$type_ns=false,$attributes=false,$use='encoded',$soapval=false) {
  364. $this->debug("in serialize_val: name=$name, type=$type, name_ns=$name_ns, type_ns=$type_ns, use=$use, soapval=$soapval");
  365. $this->appendDebug('value=' . $this->varDump($val));
  366. $this->appendDebug('attributes=' . $this->varDump($attributes));
  367. if (is_object($val) && get_class($val) == 'soapval' && (! $soapval)) {
  368. $this->debug("serialize_val: serialize soapval");
  369. $xml = $val->serialize($use);
  370. $this->appendDebug($val->getDebug());
  371. $val->clearDebug();
  372. $this->debug("serialize_val of soapval returning $xml");
  373. return $xml;
  374. }
  375. // force valid name if necessary
  376. if (is_numeric($name)) {
  377. $name = '__numeric_' . $name;
  378. } elseif (! $name) {
  379. $name = 'noname';
  380. }
  381. // if name has ns, add ns prefix to name
  382. $xmlns = '';
  383. if($name_ns){
  384. $prefix = 'nu'.rand(1000,9999);
  385. $name = $prefix.':'.$name;
  386. $xmlns .= " xmlns:$prefix=\"$name_ns\"";
  387. }
  388. // if type is prefixed, create type prefix
  389. if($type_ns != '' && $type_ns == $this->namespaces['xsd']){
  390. // need to fix this. shouldn't default to xsd if no ns specified
  391. // w/o checking against typemap
  392. $type_prefix = 'xsd';
  393. } elseif($type_ns){
  394. $type_prefix = 'ns'.rand(1000,9999);
  395. $xmlns .= " xmlns:$type_prefix=\"$type_ns\"";
  396. }
  397. // serialize attributes if present
  398. $atts = '';
  399. if($attributes){
  400. foreach($attributes as $k => $v){
  401. $atts .= " $k=\"".$this->expandEntities($v).'"';
  402. }
  403. }
  404. // serialize null value
  405. if (is_null($val)) {
  406. $this->debug("serialize_val: serialize null");
  407. if ($use == 'literal') {
  408. // TODO: depends on minOccurs
  409. $xml = "<$name$xmlns$atts/>";
  410. $this->debug("serialize_val returning $xml");
  411. return $xml;
  412. } else {
  413. if (isset($type) && isset($type_prefix)) {
  414. $type_str = " xsi:type=\"$type_prefix:$type\"";
  415. } else {
  416. $type_str = '';
  417. }
  418. $xml = "<$name$xmlns$type_str$atts xsi:nil=\"true\"/>";
  419. $this->debug("serialize_val returning $xml");
  420. return $xml;
  421. }
  422. }
  423. // serialize if an xsd built-in primitive type
  424. if($type != '' && isset($this->typemap[$this->XMLSchemaVersion][$type])){
  425. $this->debug("serialize_val: serialize xsd built-in primitive type");
  426. if (is_bool($val)) {
  427. if ($type == 'boolean') {
  428. $val = $val ? 'true' : 'false';
  429. } elseif (! $val) {
  430. $val = 0;
  431. }
  432. } else if (is_string($val)) {
  433. $val = $this->expandEntities($val);
  434. }
  435. if ($use == 'literal') {
  436. $xml = "<$name$xmlns$atts>$val</$name>";
  437. $this->debug("serialize_val returning $xml");
  438. return $xml;
  439. } else {
  440. $xml = "<$name$xmlns xsi:type=\"xsd:$type\"$atts>$val</$name>";
  441. $this->debug("serialize_val returning $xml");
  442. return $xml;
  443. }
  444. }
  445. // detect type and serialize
  446. $xml = '';
  447. switch(true) {
  448. case (is_bool($val) || $type == 'boolean'):
  449. $this->debug("serialize_val: serialize boolean");
  450. if ($type == 'boolean') {
  451. $val = $val ? 'true' : 'false';
  452. } elseif (! $val) {
  453. $val = 0;
  454. }
  455. if ($use == 'literal') {
  456. $xml .= "<$name$xmlns$atts>$val</$name>";
  457. } else {
  458. $xml .= "<$name$xmlns xsi:type=\"xsd:boolean\"$atts>$val</$name>";
  459. }
  460. break;
  461. case (is_int($val) || is_long($val) || $type == 'int'):
  462. $this->debug("serialize_val: serialize int");
  463. if ($use == 'literal') {
  464. $xml .= "<$name$xmlns$atts>$val</$name>";
  465. } else {
  466. $xml .= "<$name$xmlns xsi:type=\"xsd:int\"$atts>$val</$name>";
  467. }
  468. break;
  469. case (is_float($val)|| is_double($val) || $type == 'float'):
  470. $this->debug("serialize_val: serialize float");
  471. if ($use == 'literal') {
  472. $xml .= "<$name$xmlns$atts>$val</$name>";
  473. } else {
  474. $xml .= "<$name$xmlns xsi:type=\"xsd:float\"$atts>$val</$name>";
  475. }
  476. break;
  477. case (is_string($val) || $type == 'string'):
  478. $this->debug("serialize_val: serialize string");
  479. $val = $this->expandEntities($val);
  480. if ($use == 'literal') {
  481. $xml .= "<$name$xmlns$atts>$val</$name>";
  482. } else {
  483. $xml .= "<$name$xmlns xsi:type=\"xsd:string\"$atts>$val</$name>";
  484. }
  485. break;
  486. case is_object($val):
  487. $this->debug("serialize_val: serialize object");
  488. if (get_class($val) == 'soapval') {
  489. $this->debug("serialize_val: serialize soapval object");
  490. $pXml = $val->serialize($use);
  491. $this->appendDebug($val->getDebug());
  492. $val->clearDebug();
  493. } else {
  494. if (! $name) {
  495. $name = get_class($val);
  496. $this->debug("In serialize_val, used class name $name as element name");
  497. } else {
  498. $this->debug("In serialize_val, do not override name $name for element name for class " . get_class($val));
  499. }
  500. foreach(get_object_vars($val) as $k => $v){
  501. $pXml = isset($pXml) ? $pXml.$this->serialize_val($v,$k,false,false,false,false,$use) : $this->serialize_val($v,$k,false,false,false,false,$use);
  502. }
  503. }
  504. if(isset($type) && isset($type_prefix)){
  505. $type_str = " xsi:type=\"$type_prefix:$type\"";
  506. } else {
  507. $type_str = '';
  508. }
  509. if ($use == 'literal') {
  510. $xml .= "<$name$xmlns$atts>$pXml</$name>";
  511. } else {
  512. $xml .= "<$name$xmlns$type_str$atts>$pXml</$name>";
  513. }
  514. break;
  515. break;
  516. case (is_array($val) || $type):
  517. // detect if struct or array
  518. $valueType = $this->isArraySimpleOrStruct($val);
  519. if($valueType=='arraySimple' || preg_match('/^ArrayOf/',$type)){
  520. $this->debug("serialize_val: serialize array");
  521. $i = 0;
  522. if(is_array($val) && count($val)> 0){
  523. foreach($val as $v){
  524. if(is_object($v) && get_class($v) == 'soapval'){
  525. $tt_ns = $v->type_ns;
  526. $tt = $v->type;
  527. } elseif (is_array($v)) {
  528. $tt = $this->isArraySimpleOrStruct($v);
  529. } else {
  530. $tt = gettype($v);
  531. }
  532. $array_types[$tt] = 1;
  533. // TODO: for literal, the name should be $name
  534. //DOL_CHANGE This is to have tag name with name reported by wsdl and not "item"
  535. //$xml .= $this->serialize_val($v,'item',false,false,false,false,$use);
  536. $tmp=preg_replace('/s$/i','',$name);
  537. $xml .= $this->serialize_val($v,$tmp?$tmp:'item',false,false,false,false,$use);
  538. ++$i;
  539. }
  540. if(count($array_types) > 1){
  541. $array_typename = 'xsd:anyType';
  542. } elseif(isset($tt) && isset($this->typemap[$this->XMLSchemaVersion][$tt])) {
  543. if ($tt == 'integer') {
  544. $tt = 'int';
  545. }
  546. $array_typename = 'xsd:'.$tt;
  547. } elseif(isset($tt) && $tt == 'arraySimple'){
  548. $array_typename = 'SOAP-ENC:Array';
  549. } elseif(isset($tt) && $tt == 'arrayStruct'){
  550. $array_typename = 'unnamed_struct_use_soapval';
  551. } else {
  552. // if type is prefixed, create type prefix
  553. if ($tt_ns != '' && $tt_ns == $this->namespaces['xsd']){
  554. $array_typename = 'xsd:' . $tt;
  555. } elseif ($tt_ns) {
  556. $tt_prefix = 'ns' . rand(1000, 9999);
  557. $array_typename = "$tt_prefix:$tt";
  558. $xmlns .= " xmlns:$tt_prefix=\"$tt_ns\"";
  559. } else {
  560. $array_typename = $tt;
  561. }
  562. }
  563. $array_type = $i;
  564. if ($use == 'literal') {
  565. $type_str = '';
  566. } else if (isset($type) && isset($type_prefix)) {
  567. $type_str = " xsi:type=\"$type_prefix:$type\"";
  568. } else {
  569. $type_str = " xsi:type=\"SOAP-ENC:Array\" SOAP-ENC:arrayType=\"".$array_typename."[$array_type]\"";
  570. }
  571. // empty array
  572. } else {
  573. if ($use == 'literal') {
  574. $type_str = '';
  575. } else if (isset($type) && isset($type_prefix)) {
  576. $type_str = " xsi:type=\"$type_prefix:$type\"";
  577. } else {
  578. $type_str = " xsi:type=\"SOAP-ENC:Array\" SOAP-ENC:arrayType=\"xsd:anyType[0]\"";
  579. }
  580. }
  581. // TODO: for array in literal, there is no wrapper here
  582. $xml = "<$name$xmlns$type_str$atts>".$xml."</$name>";
  583. } else {
  584. // got a struct
  585. $this->debug("serialize_val: serialize struct");
  586. if(isset($type) && isset($type_prefix)){
  587. $type_str = " xsi:type=\"$type_prefix:$type\"";
  588. } else {
  589. $type_str = '';
  590. }
  591. if ($use == 'literal') {
  592. $xml .= "<$name$xmlns$atts>";
  593. } else {
  594. $xml .= "<$name$xmlns$type_str$atts>";
  595. }
  596. foreach($val as $k => $v){
  597. // Apache Map
  598. if ($type == 'Map' && $type_ns == 'http://xml.apache.org/xml-soap') {
  599. $xml .= '<item>';
  600. $xml .= $this->serialize_val($k,'key',false,false,false,false,$use);
  601. $xml .= $this->serialize_val($v,'value',false,false,false,false,$use);
  602. $xml .= '</item>';
  603. } else {
  604. $xml .= $this->serialize_val($v,$k,false,false,false,false,$use);
  605. }
  606. }
  607. $xml .= "</$name>";
  608. }
  609. break;
  610. default:
  611. $this->debug("serialize_val: serialize unknown");
  612. $xml .= 'not detected, got '.gettype($val).' for '.$val;
  613. break;
  614. }
  615. $this->debug("serialize_val returning $xml");
  616. return $xml;
  617. }
  618. /**
  619. * serializes a message
  620. *
  621. * @param string $body the XML of the SOAP body
  622. * @param mixed $headers optional string of XML with SOAP header content, or array of soapval objects for SOAP headers, or associative array
  623. * @param array $namespaces optional the namespaces used in generating the body and headers
  624. * @param string $style optional (rpc|document)
  625. * @param string $use optional (encoded|literal)
  626. * @param string $encodingStyle optional (usually 'http://schemas.xmlsoap.org/soap/encoding/' for encoded)
  627. * @return string the message
  628. * @access public
  629. */
  630. function serializeEnvelope($body,$headers=false,$namespaces=array(),$style='rpc',$use='encoded',$encodingStyle='http://schemas.xmlsoap.org/soap/encoding/'){
  631. // TODO: add an option to automatically run utf8_encode on $body and $headers
  632. // if $this->soap_defencoding is UTF-8. Not doing this automatically allows
  633. // one to send arbitrary UTF-8 characters, not just characters that map to ISO-8859-1
  634. $this->debug("In serializeEnvelope length=" . strlen($body) . " body (max 1000 characters)=" . substr($body, 0, 1000) . " style=$style use=$use encodingStyle=$encodingStyle");
  635. $this->debug("headers:");
  636. $this->appendDebug($this->varDump($headers));
  637. $this->debug("namespaces:");
  638. $this->appendDebug($this->varDump($namespaces));
  639. // serialize namespaces
  640. $ns_string = '';
  641. foreach(array_merge($this->namespaces,$namespaces) as $k => $v){
  642. $ns_string .= " xmlns:$k=\"$v\"";
  643. }
  644. if($encodingStyle) {
  645. $ns_string = " SOAP-ENV:encodingStyle=\"$encodingStyle\"$ns_string";
  646. }
  647. // serialize headers
  648. if($headers){
  649. if (is_array($headers)) {
  650. $xml = '';
  651. foreach ($headers as $k => $v) {
  652. if (is_object($v) && get_class($v) == 'soapval') {
  653. $xml .= $this->serialize_val($v, false, false, false, false, false, $use);
  654. } else {
  655. $xml .= $this->serialize_val($v, $k, false, false, false, false, $use);
  656. }
  657. }
  658. $headers = $xml;
  659. $this->debug("In serializeEnvelope, serialized array of headers to $headers");
  660. }
  661. $headers = "<SOAP-ENV:Header>".$headers."</SOAP-ENV:Header>";
  662. }
  663. // serialize envelope
  664. return
  665. '<?xml version="1.0" encoding="'.$this->soap_defencoding .'"?'.">".
  666. '<SOAP-ENV:Envelope'.$ns_string.">".
  667. $headers.
  668. "<SOAP-ENV:Body>".
  669. $body.
  670. "</SOAP-ENV:Body>".
  671. "</SOAP-ENV:Envelope>";
  672. }
  673. /**
  674. * formats a string to be inserted into an HTML stream
  675. *
  676. * @param string $str The string to format
  677. * @return string The formatted string
  678. * @access public
  679. * @deprecated
  680. */
  681. function formatDump($str){
  682. $str = htmlspecialchars($str);
  683. return nl2br($str);
  684. }
  685. /**
  686. * contracts (changes namespace to prefix) a qualified name
  687. *
  688. * @param string $qname qname
  689. * @return string contracted qname
  690. * @access private
  691. */
  692. function contractQname($qname){
  693. // get element namespace
  694. //$this->xdebug("Contract $qname");
  695. if (strrpos($qname, ':')) {
  696. // get unqualified name
  697. $name = substr($qname, strrpos($qname, ':') + 1);
  698. // get ns
  699. $ns = substr($qname, 0, strrpos($qname, ':'));
  700. $p = $this->getPrefixFromNamespace($ns);
  701. if ($p) {
  702. return $p . ':' . $name;
  703. }
  704. return $qname;
  705. } else {
  706. return $qname;
  707. }
  708. }
  709. /**
  710. * expands (changes prefix to namespace) a qualified name
  711. *
  712. * @param string $qname qname
  713. * @return string expanded qname
  714. * @access private
  715. */
  716. function expandQname($qname){
  717. // get element prefix
  718. if(strpos($qname,':') && !preg_match('/^http:\/\//',$qname)){
  719. // get unqualified name
  720. $name = substr(strstr($qname,':'),1);
  721. // get ns prefix
  722. $prefix = substr($qname,0,strpos($qname,':'));
  723. if(isset($this->namespaces[$prefix])){
  724. return $this->namespaces[$prefix].':'.$name;
  725. } else {
  726. return $qname;
  727. }
  728. } else {
  729. return $qname;
  730. }
  731. }
  732. /**
  733. * returns the local part of a prefixed string
  734. * returns the original string, if not prefixed
  735. *
  736. * @param string $str The prefixed string
  737. * @return string The local part
  738. * @access public
  739. */
  740. function getLocalPart($str){
  741. if($sstr = strrchr($str,':')){
  742. // get unqualified name
  743. return substr( $sstr, 1 );
  744. } else {
  745. return $str;
  746. }
  747. }
  748. /**
  749. * returns the prefix part of a prefixed string
  750. * returns false, if not prefixed
  751. *
  752. * @param string $str The prefixed string
  753. * @return mixed The prefix or false if there is no prefix
  754. * @access public
  755. */
  756. function getPrefix($str){
  757. if($pos = strrpos($str,':')){
  758. // get prefix
  759. return substr($str,0,$pos);
  760. }
  761. return false;
  762. }
  763. /**
  764. * pass it a prefix, it returns a namespace
  765. *
  766. * @param string $prefix The prefix
  767. * @return mixed The namespace, false if no namespace has the specified prefix
  768. * @access public
  769. */
  770. function getNamespaceFromPrefix($prefix){
  771. if (isset($this->namespaces[$prefix])) {
  772. return $this->namespaces[$prefix];
  773. }
  774. //$this->setError("No namespace registered for prefix '$prefix'");
  775. return false;
  776. }
  777. /**
  778. * returns the prefix for a given namespace (or prefix)
  779. * or false if no prefixes registered for the given namespace
  780. *
  781. * @param string $ns The namespace
  782. * @return mixed The prefix, false if the namespace has no prefixes
  783. * @access public
  784. */
  785. function getPrefixFromNamespace($ns) {
  786. foreach ($this->namespaces as $p => $n) {
  787. if ($ns == $n || $ns == $p) {
  788. $this->usedNamespaces[$p] = $n;
  789. return $p;
  790. }
  791. }
  792. return false;
  793. }
  794. /**
  795. * returns the time in ODBC canonical form with microseconds
  796. *
  797. * @return string The time in ODBC canonical form with microseconds
  798. * @access public
  799. */
  800. function getmicrotime() {
  801. if (function_exists('gettimeofday')) {
  802. $tod = gettimeofday();
  803. $sec = $tod['sec'];
  804. $usec = $tod['usec'];
  805. } else {
  806. $sec = time();
  807. $usec = 0;
  808. }
  809. return strftime('%Y-%m-%d %H:%M:%S', $sec) . '.' . sprintf('%06d', $usec);
  810. }
  811. /**
  812. * Returns a string with the output of var_dump
  813. *
  814. * @param mixed $data The variable to var_dump
  815. * @return string The output of var_dump
  816. * @access public
  817. */
  818. function varDump($data) {
  819. ob_start();
  820. var_dump($data);
  821. $ret_val = ob_get_contents();
  822. ob_end_clean();
  823. return $ret_val;
  824. }
  825. /**
  826. * represents the object as a string
  827. *
  828. * @return string
  829. * @access public
  830. */
  831. function __toString() {
  832. return $this->varDump($this);
  833. }
  834. }
  835. // XML Schema Datatype Helper Functions
  836. //xsd:dateTime helpers
  837. /**
  838. * convert unix timestamp to ISO 8601 compliant date string
  839. *
  840. * @param int $timestamp Unix time stamp
  841. * @param boolean $utc Whether the time stamp is UTC or local
  842. * @return mixed ISO 8601 date string or false
  843. * @access public
  844. */
  845. function timestamp_to_iso8601($timestamp,$utc=true){
  846. $datestr = date('Y-m-d\TH:i:sO',$timestamp);
  847. $pos = strrpos($datestr, "+");
  848. if ($pos === FALSE) {
  849. $pos = strrpos($datestr, "-");
  850. }
  851. if ($pos !== FALSE) {
  852. if (strlen($datestr) == $pos + 5) {
  853. $datestr = substr($datestr, 0, $pos + 3) . ':' . substr($datestr, -2);
  854. }
  855. }
  856. if($utc){
  857. $pattern = '/'.
  858. '([0-9]{4})-'. // centuries & years CCYY-
  859. '([0-9]{2})-'. // months MM-
  860. '([0-9]{2})'. // days DD
  861. 'T'. // separator T
  862. '([0-9]{2}):'. // hours hh:
  863. '([0-9]{2}):'. // minutes mm:
  864. '([0-9]{2})(\.[0-9]*)?'. // seconds ss.ss...
  865. '(Z|[+\-][0-9]{2}:?[0-9]{2})?'. // Z to indicate UTC, -/+HH:MM:SS.SS... for local tz's
  866. '/';
  867. if(preg_match($pattern,$datestr,$regs)){
  868. return sprintf('%04d-%02d-%02dT%02d:%02d:%02dZ',$regs[1],$regs[2],$regs[3],$regs[4],$regs[5],$regs[6]);
  869. }
  870. return false;
  871. } else {
  872. return $datestr;
  873. }
  874. }
  875. /**
  876. * convert ISO 8601 compliant date string to unix timestamp
  877. *
  878. * @param string $datestr ISO 8601 compliant date string
  879. * @return mixed Unix timestamp (int) or false
  880. * @access public
  881. */
  882. function iso8601_to_timestamp($datestr){
  883. $pattern = '/'.
  884. '([0-9]{4})-'. // centuries & years CCYY-
  885. '([0-9]{2})-'. // months MM-
  886. '([0-9]{2})'. // days DD
  887. 'T'. // separator T
  888. '([0-9]{2}):'. // hours hh:
  889. '([0-9]{2}):'. // minutes mm:
  890. '([0-9]{2})(\.[0-9]+)?'. // seconds ss.ss...
  891. '(Z|[+\-][0-9]{2}:?[0-9]{2})?'. // Z to indicate UTC, -/+HH:MM:SS.SS... for local tz's
  892. '/';
  893. if(preg_match($pattern,$datestr,$regs)){
  894. // not utc
  895. if($regs[8] != 'Z'){
  896. $op = substr($regs[8],0,1);
  897. $h = substr($regs[8],1,2);
  898. $m = substr($regs[8],strlen($regs[8])-2,2);
  899. if($op == '-'){
  900. $regs[4] = $regs[4] + $h;
  901. $regs[5] = $regs[5] + $m;
  902. } elseif($op == '+'){
  903. $regs[4] = $regs[4] - $h;
  904. $regs[5] = $regs[5] - $m;
  905. }
  906. }
  907. return gmmktime($regs[4], $regs[5], $regs[6], $regs[2], $regs[3], $regs[1]);
  908. // return strtotime("$regs[1]-$regs[2]-$regs[3] $regs[4]:$regs[5]:$regs[6]Z");
  909. } else {
  910. return false;
  911. }
  912. }
  913. /**
  914. * sleeps some number of microseconds
  915. *
  916. * @param string $usec the number of microseconds to sleep
  917. * @access public
  918. * @deprecated
  919. */
  920. function usleepWindows($usec)
  921. {
  922. $start = gettimeofday();
  923. do
  924. {
  925. $stop = gettimeofday();
  926. $timePassed = 1000000 * ($stop['sec'] - $start['sec'])
  927. + $stop['usec'] - $start['usec'];
  928. }
  929. while ($timePassed < $usec);
  930. }
  931. ?><?php
  932. /**
  933. * Contains information for a SOAP fault.
  934. * Mainly used for returning faults from deployed functions
  935. * in a server instance.
  936. * @author Dietrich Ayala <dietrich@ganx4.com>
  937. * @access public
  938. */
  939. class nusoap_fault extends nusoap_base {
  940. /**
  941. * The fault code (client|server)
  942. * @var string
  943. * @access private
  944. */
  945. var $faultcode;
  946. /**
  947. * The fault actor
  948. * @var string
  949. * @access private
  950. */
  951. var $faultactor;
  952. /**
  953. * The fault string, a description of the fault
  954. * @var string
  955. * @access private
  956. */
  957. var $faultstring;
  958. /**
  959. * The fault detail, typically a string or array of string
  960. * @var mixed
  961. * @access private
  962. */
  963. var $faultdetail;
  964. /**
  965. * constructor
  966. *
  967. * @param string $faultcode (SOAP-ENV:Client | SOAP-ENV:Server)
  968. * @param string $faultactor only used when msg routed between multiple actors
  969. * @param string $faultstring human readable error message
  970. * @param mixed $faultdetail detail, typically a string or array of string
  971. */
  972. function nusoap_fault($faultcode,$faultactor='',$faultstring='',$faultdetail=''){
  973. parent::nusoap_base();
  974. $this->faultcode = $faultcode;
  975. $this->faultactor = $faultactor;
  976. $this->faultstring = $faultstring;
  977. $this->faultdetail = $faultdetail;
  978. }
  979. /**
  980. * serialize a fault
  981. *
  982. * @return string The serialization of the fault instance.
  983. * @access public
  984. */
  985. function serialize(){
  986. $ns_string = '';
  987. foreach($this->namespaces as $k => $v){
  988. $ns_string .= "\n xmlns:$k=\"$v\"";
  989. }
  990. $return_msg =
  991. '<?xml version="1.0" encoding="'.$this->soap_defencoding.'"?>'.
  992. '<SOAP-ENV:Envelope SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"'.$ns_string.">\n".
  993. '<SOAP-ENV:Body>'.
  994. '<SOAP-ENV:Fault>'.
  995. $this->serialize_val($this->faultcode, 'faultcode').
  996. $this->serialize_val($this->faultactor, 'faultactor').
  997. $this->serialize_val($this->faultstring, 'faultstring').
  998. $this->serialize_val($this->faultdetail, 'detail').
  999. '</SOAP-ENV:Fault>'.
  1000. '</SOAP-ENV:Body>'.
  1001. '</SOAP-ENV:Envelope>';
  1002. return $return_msg;
  1003. }
  1004. }
  1005. /**
  1006. * Backward compatibility
  1007. */
  1008. class soap_fault extends nusoap_fault {
  1009. }
  1010. ?><?php
  1011. /**
  1012. * parses an XML Schema, allows access to it's data, other utility methods.
  1013. * imperfect, no validation... yet, but quite functional.
  1014. *
  1015. * @author Dietrich Ayala <dietrich@ganx4.com>
  1016. * @author Scott Nichol <snichol@users.sourceforge.net>
  1017. * @access public
  1018. */
  1019. class nusoap_xmlschema extends nusoap_base {
  1020. // files
  1021. var $schema = '';
  1022. var $xml = '';
  1023. // namespaces
  1024. var $enclosingNamespaces;
  1025. // schema info
  1026. var $schemaInfo = array();
  1027. var $schemaTargetNamespace = '';
  1028. // types, elements, attributes defined by the schema
  1029. var $attributes = array();
  1030. var $complexTypes = array();
  1031. var $complexTypeStack = array();
  1032. var $currentComplexType = null;
  1033. var $elements = array();
  1034. var $elementStack = array();
  1035. var $currentElement = null;
  1036. var $simpleTypes = array();
  1037. var $simpleTypeStack = array();
  1038. var $currentSimpleType = null;
  1039. // imports
  1040. var $imports = array();
  1041. // parser vars
  1042. var $parser;
  1043. var $position = 0;
  1044. var $depth = 0;
  1045. var $depth_array = array();
  1046. var $message = array();
  1047. var $defaultNamespace = array();
  1048. /**
  1049. * constructor
  1050. *
  1051. * @param string $schema schema document URI
  1052. * @param string $xml xml document URI
  1053. * @param string $namespaces namespaces defined in enclosing XML
  1054. * @access public
  1055. */
  1056. function nusoap_xmlschema($schema='',$xml='',$namespaces=array()){
  1057. parent::nusoap_base();
  1058. $this->debug('nusoap_xmlschema class instantiated, inside constructor');
  1059. // files
  1060. $this->schema = $schema;
  1061. $this->xml = $xml;
  1062. // namespaces
  1063. $this->enclosingNamespaces = $namespaces;
  1064. $this->namespaces = array_merge($this->namespaces, $namespaces);
  1065. // parse schema file
  1066. if($schema != ''){
  1067. $this->debug('initial schema file: '.$schema);
  1068. $this->parseFile($schema, 'schema');
  1069. }
  1070. // parse xml file
  1071. if($xml != ''){
  1072. $this->debug('initial xml file: '.$xml);
  1073. $this->parseFile($xml, 'xml');
  1074. }
  1075. }
  1076. /**
  1077. * parse an XML file
  1078. *
  1079. * @param string $xml path/URL to XML file
  1080. * @param string $type (schema | xml)
  1081. * @return boolean
  1082. * @access public
  1083. */
  1084. function parseFile($xml,$type){
  1085. // parse xml file
  1086. if($xml != ""){
  1087. $xmlStr = @join("",@file($xml));
  1088. if($xmlStr == ""){
  1089. $msg = 'Error reading XML from '.$xml;
  1090. $this->setError($msg);
  1091. $this->debug($msg);
  1092. return false;
  1093. } else {
  1094. $this->debug("parsing $xml");
  1095. $this->parseString($xmlStr,$type);
  1096. $this->debug("done parsing $xml");
  1097. return true;
  1098. }
  1099. }
  1100. return false;
  1101. }
  1102. /**
  1103. * parse an XML string
  1104. *
  1105. * @param string $xml path or URL
  1106. * @param string $type (schema|xml)
  1107. * @access private
  1108. */
  1109. function parseString($xml,$type){
  1110. // parse xml string
  1111. if($xml != ""){
  1112. // Create an XML parser.
  1113. $this->parser = xml_parser_create();
  1114. // Set the options for parsing the XML data.
  1115. xml_parser_set_option($this->parser, XML_OPTION_CASE_FOLDING, 0);
  1116. // Set the object for the parser.
  1117. xml_set_object($this->parser, $this);
  1118. // Set the element handlers for the parser.
  1119. if($type == "schema"){
  1120. xml_set_element_handler($this->parser, 'schemaStartElement','schemaEndElement');
  1121. xml_set_character_data_handler($this->parser,'schemaCharacterData');
  1122. } elseif($type == "xml"){
  1123. xml_set_element_handler($this->parser, 'xmlStartElement','xmlEndElement');
  1124. xml_set_character_data_handler($this->parser,'xmlCharacterData');
  1125. }
  1126. // Parse the XML file.
  1127. if(!xml_parse($this->parser,$xml,true)){
  1128. // Display an error message.
  1129. $errstr = sprintf('XML error parsing XML schema on line %d: %s',
  1130. xml_get_current_line_number($this->parser),
  1131. xml_error_string(xml_get_error_code($this->parser))
  1132. );
  1133. $this->debug($errstr);
  1134. $this->debug("XML payload:\n" . $xml);
  1135. $this->setError($errstr);
  1136. }
  1137. xml_parser_free($this->parser);
  1138. } else{
  1139. $this->debug('no xml passed to parseString()!!');
  1140. $this->setError('no xml passed to parseString()!!');
  1141. }
  1142. }
  1143. /**
  1144. * gets a type name for an unnamed type
  1145. *
  1146. * @param string Element name
  1147. * @return string A type name for an unnamed type
  1148. * @access private
  1149. */
  1150. function CreateTypeName($ename) {
  1151. $scope = '';
  1152. for ($i = 0; $i < count($this->complexTypeStack); $i++) {
  1153. $scope .= $this->complexTypeStack[$i] . '_';
  1154. }
  1155. return $scope . $ename . '_ContainedType';
  1156. }
  1157. /**
  1158. * start-element handler
  1159. *
  1160. * @param string $parser XML parser object
  1161. * @param string $name element name
  1162. * @param string $attrs associative array of attributes
  1163. * @access private
  1164. */
  1165. function schemaStartElement($parser, $name, $attrs) {
  1166. // position in the total number of elements, starting from 0
  1167. $pos = $this->position++;
  1168. $depth = $this->depth++;
  1169. // set self as current value for this depth
  1170. $this->depth_array[$depth] = $pos;
  1171. $this->message[$pos] = array('cdata' => '');
  1172. if ($depth > 0) {
  1173. $this->defaultNamespace[$pos] = $this->defaultNamespace[$this->depth_array[$depth - 1]];
  1174. } else {
  1175. $this->defaultNamespace[$pos] = false;
  1176. }
  1177. // get element prefix
  1178. if($prefix = $this->getPrefix($name)){
  1179. // get unqualified name
  1180. $name = $this->getLocalPart($name);
  1181. } else {
  1182. $prefix = '';
  1183. }
  1184. // loop thru attributes, expanding, and registering namespace declarations
  1185. if(count($attrs) > 0){
  1186. foreach($attrs as $k => $v){
  1187. // if ns declarations, add to class level array of valid namespaces
  1188. if(preg_match('/^xmlns/',$k)){
  1189. //$this->xdebug("$k: $v");
  1190. //$this->xdebug('ns_prefix: '.$this->getPrefix($k));
  1191. if($ns_prefix = substr(strrchr($k,':'),1)){
  1192. //$this->xdebug("Add namespace[$ns_prefix] = $v");
  1193. $this->namespaces[$ns_prefix] = $v;
  1194. } else {
  1195. $this->defaultNamespace[$pos] = $v;
  1196. if (! $this->getPrefixFromNamespace($v)) {
  1197. $this->namespaces['ns'.(count($this->namespaces)+1)] = $v;
  1198. }
  1199. }
  1200. if($v == 'http://www.w3.org/2001/XMLSchema' || $v == 'http://www.w3.org/1999/XMLSchema' || $v == 'http://www.w3.org/2000/10/XMLSchema'){
  1201. $this->XMLSchemaVersion = $v;
  1202. $this->namespaces['xsi'] = $v.'-instance';
  1203. }
  1204. }
  1205. }
  1206. foreach($attrs as $k => $v){
  1207. // expand each attribute
  1208. $k = strpos($k,':') ? $this->expandQname($k) : $k;
  1209. $v = strpos($v,':') ? $this->expandQname($v) : $v;
  1210. $eAttrs[$k] = $v;
  1211. }
  1212. $attrs = $eAttrs;
  1213. } else {
  1214. $attrs = array();
  1215. }
  1216. // find status, register data
  1217. switch($name){
  1218. case 'all': // (optional) compositor content for a complexType
  1219. case 'choice':
  1220. case 'group':
  1221. case 'sequence':
  1222. //$this->xdebug("compositor $name for currentComplexType: $this->currentComplexType and currentElement: $this->currentElement");
  1223. $this->complexTypes[$this->currentComplexType]['compositor'] = $name;
  1224. //if($name == 'all' || $name == 'sequence'){
  1225. // $this->complexTypes[$this->currentComplexType]['phpType'] = 'struct';
  1226. //}
  1227. break;
  1228. case 'attribute': // complexType attribute
  1229. //$this->xdebug("parsing attribute $attrs[name] $attrs[ref] of value: ".$attrs['http://schemas.xmlsoap.org/wsdl/:arrayType']);
  1230. $this->xdebug("parsing attribute:");
  1231. $this->appendDebug($this->varDump($attrs));
  1232. if (!isset($attrs['form'])) {
  1233. // TODO: handle globals
  1234. $attrs['form'] = $this->schemaInfo['attributeFormDefault'];
  1235. }
  1236. if (isset($attrs['http://schemas.xmlsoap.org/wsdl/:arrayType'])) {
  1237. $v = $attrs['http://schemas.xmlsoap.org/wsdl/:arrayType'];
  1238. if (!strpos($v, ':')) {
  1239. // no namespace in arrayType attribute value...
  1240. if ($this->defaultNamespace[$pos]) {
  1241. // ...so use the default
  1242. $attrs['http://schemas.xmlsoap.org/wsdl/:arrayType'] = $this->defaultNamespace[$pos] . ':' . $attrs['http://schemas.xmlsoap.org/wsdl/:arrayType'];
  1243. }
  1244. }
  1245. }
  1246. if(isset($attrs['name'])){
  1247. $this->attributes[$attrs['name']] = $attrs;
  1248. $aname = $attrs['name'];
  1249. } elseif(isset($attrs['ref']) && $attrs['ref'] == 'http://schemas.xmlsoap.org/soap/encoding/:arrayType'){
  1250. if (isset($attrs['http://schemas.xmlsoap.org/wsdl/:arrayType'])) {
  1251. $aname = $attrs['http://schemas.xmlsoap.org/wsdl/:arrayType'];
  1252. } else {
  1253. $aname = '';
  1254. }
  1255. } elseif(isset($attrs['ref'])){
  1256. $aname = $attrs['ref'];
  1257. $this->attributes[$attrs['ref']] = $attrs;
  1258. }
  1259. if($this->currentComplexType){ // This should *always* be
  1260. $this->complexTypes[$this->currentComplexType]['attrs'][$aname] = $attrs;
  1261. }
  1262. // arrayType attribute
  1263. if(isset($attrs['http://schemas.xmlsoap.org/wsdl/:arrayType']) || $this->getLocalPart($aname) == 'arrayType'){
  1264. $this->complexTypes[$this->currentComplexType]['phpType'] = 'array';
  1265. $prefix = $this->getPrefix($aname);
  1266. if(isset($attrs['http://schemas.xmlsoap.org/wsdl/:arrayType'])){
  1267. $v = $attrs['http://schemas.xmlsoap.org/wsdl/:arrayType'];
  1268. } else {
  1269. $v = '';
  1270. }
  1271. if(strpos($v,'[,]')){
  1272. $this->complexTypes[$this->currentComplexType]['multidimensional'] = true;
  1273. }
  1274. $v = substr($v,0,strpos($v,'[')); // clip the []
  1275. if(!strpos($v,':') && isset($this->typemap[$this->XMLSchemaVersion][$v])){
  1276. $v = $this->XMLSchemaVersion.':'.$v;
  1277. }
  1278. $this->complexTypes[$this->currentComplexType]['arrayType'] = $v;
  1279. }
  1280. break;
  1281. case 'complexContent': // (optional) content for a complexType
  1282. $this->xdebug("do nothing for element $name");
  1283. break;
  1284. case 'complexType':
  1285. array_push($this->complexTypeStack, $this->currentComplexType);
  1286. if(isset($attrs['name'])){
  1287. // TODO: what is the scope of named complexTypes that appear
  1288. // nested within other c complexTypes?
  1289. $this->xdebug('processing named complexType '.$attrs['name']);
  1290. //$this->currentElement = false;
  1291. $this->currentComplexType = $attrs['name'];
  1292. $this->complexTypes[$this->currentComplexType] = $attrs;
  1293. $this->complexTypes[$this->currentComplexType]['typeClass'] = 'complexType';
  1294. // This is for constructs like
  1295. // <complexType name="ListOfString" base="soap:Array">
  1296. // <sequence>
  1297. // <element name="string" type="xsd:string"
  1298. // minOccurs="0" maxOccurs="unbounded" />
  1299. // </sequence>
  1300. // </complexType>
  1301. if(isset($attrs['base']) && preg_match('/:Array$/',$attrs['base'])){
  1302. $this->xdebug('complexType is unusual array');
  1303. $this->complexTypes[$this->currentComplexType]['phpType'] = 'array';
  1304. } else {
  1305. $this->complexTypes[$this->currentComplexType]['phpType'] = 'struct';
  1306. }
  1307. } else {
  1308. $name = $this->CreateTypeName($this->currentElement);
  1309. $this->xdebug('processing unnamed complexType for element ' . $this->currentElement . ' named ' . $name);
  1310. $this->currentComplexType = $name;
  1311. //$this->currentElement = false;
  1312. $this->complexTypes[$this->currentComplexType] = $attrs;
  1313. $this->complexTypes[$this->currentComplexType]['typeClass'] = 'complexType';
  1314. // This is for constructs like
  1315. // <complexType name="ListOfString" base="soap:Array">
  1316. // <sequence>
  1317. // <element name="string" type="xsd:string"
  1318. // minOccurs="0" maxOccurs="unbounded" />
  1319. // </sequence>
  1320. // </complexType>
  1321. if(isset($attrs['base']) && preg_match('/:Array$/',$attrs['base'])){
  1322. $this->xdebug('complexType is unusual array');
  1323. $this->complexTypes[$this->currentComplexType]['phpType'] = 'array';
  1324. } else {
  1325. $this->complexTypes[$this->currentComplexType]['phpType'] = 'struct';
  1326. }
  1327. }
  1328. $this->complexTypes[$this->currentComplexType]['simpleContent'] = 'false';
  1329. break;
  1330. case 'element':
  1331. array_push($this->elementStack, $this->currentElement);
  1332. if (!isset($attrs['form'])) {
  1333. if ($this->currentComplexType) {
  1334. $attrs['form'] = $this->schemaInfo['elementFormDefault'];
  1335. } else {
  1336. // global
  1337. $attrs['form'] = 'qualified';
  1338. }
  1339. }
  1340. if(isset($attrs['type'])){
  1341. $this->xdebug("processing typed element ".$attrs['name']." of type ".$attrs['type']);
  1342. if (! $this->getPrefix($attrs['type'])) {
  1343. if ($this->defaultNamespace[$pos]) {
  1344. $attrs['type'] = $this->defaultNamespace[$pos] . ':' . $attrs['type'];
  1345. $this->xdebug('used default namespace to make type ' . $attrs['type']);
  1346. }
  1347. }
  1348. // This is for constructs like
  1349. // <complexType name="ListOfString" base="soap:Array">
  1350. // <sequence>
  1351. // <element name="string" type="xsd:string"
  1352. // minOccurs="0" maxOccurs="unbounded" />
  1353. // </sequence>
  1354. // </complexType>
  1355. if ($this->currentComplexType && $this->complexTypes[$this->currentComplexType]['phpType'] == 'array') {
  1356. $this->xdebug('arrayType for unusual array is ' . $attrs['type']);
  1357. $this->complexTypes[$this->currentComplexType]['arrayType'] = $attrs['type'];
  1358. }
  1359. $this->currentElement = $attrs['name'];
  1360. $ename = $attrs['name'];
  1361. } elseif(isset($attrs['ref'])){
  1362. $this->xdebug("processing element as ref to ".$attrs['ref']);
  1363. $this->currentElement = "ref to ".$attrs['ref'];
  1364. $ename = $this->getLocalPart($attrs['ref']);
  1365. } else {
  1366. $type = $this->CreateTypeName($this->currentComplexType . '_' . $attrs['name']);
  1367. $this->xdebug("processing untyped element " . $attrs['name'] . ' type ' . $type);
  1368. $this->currentElement = $attrs['name'];
  1369. $attrs['type'] = $this->schemaTargetNamespace . ':' . $type;
  1370. $ename = $attrs['name'];
  1371. }
  1372. if (isset($ename) && $this->currentComplexType) {
  1373. $this->xdebug("add element $ename to complexType $this->currentComplexType");
  1374. $this->complexTypes[$this->currentComplexType]['elements'][$ename] = $attrs;
  1375. } elseif (!isset($attrs['ref'])) {
  1376. $this->xdebug("add element $ename to elements array");
  1377. $this->elements[ $attrs['name'] ] = $attrs;
  1378. $this->elements[ $attrs['name'] ]['typeClass'] = 'element';
  1379. }
  1380. break;
  1381. case 'enumeration': // restriction value list member
  1382. $this->xdebug('enumeration ' . $attrs['value']);
  1383. if ($this->currentSimpleType) {
  1384. $this->simpleTypes[$this->currentSimpleType]['enumeration'][] = $attrs['value'];
  1385. } elseif ($this->currentComplexType) {
  1386. $this->complexTypes[$this->currentComplexType]['enumeration'][] = $attrs['value'];
  1387. }
  1388. break;
  1389. case 'extension': // simpleContent or complexContent type extension
  1390. $this->xdebug('extension ' . $attrs['base']);
  1391. if ($this->currentComplexType) {
  1392. $ns = $this->getPrefix($attrs['base']);
  1393. if ($ns == '') {
  1394. $this->complexTypes[$this->currentComplexType]['extensionBase'] = $this->schemaTargetNamespace . ':' . $attrs['base'];
  1395. } else {
  1396. $this->complexTypes[$this->currentComplexType]['extensionBase'] = $attrs['base'];
  1397. }
  1398. } else {
  1399. $this->xdebug('no current complexType to set extensionBase');
  1400. }
  1401. break;
  1402. case 'import':
  1403. if (isset($attrs['schemaLocation'])) {
  1404. $this->xdebug('import namespace ' . $attrs['namespace'] . ' from ' . $attrs['schemaLocation']);
  1405. $this->imports[$attrs['namespace']][] = array('location' => $attrs['schemaLocation'], 'loaded' => false);
  1406. } else {
  1407. $this->xdebug('import namespace ' . $attrs['namespace']);
  1408. $this->imports[$attrs['namespace']][] = array('location' => '', 'loaded' => true);
  1409. if (! $this->getPrefixFromNamespace($attrs['namespace'])) {
  1410. $this->namespaces['ns'.(count($this->namespaces)+1)] = $attrs['namespace'];
  1411. }
  1412. }
  1413. break;
  1414. case 'include':
  1415. if (isset($attrs['schemaLocation'])) {
  1416. $this->xdebug('include into namespace ' . $this->schemaTargetNamespace . ' from ' . $attrs['schemaLocation']);
  1417. $this->imports[$this->schemaTargetNamespace][] = array('location' => $attrs['schemaLocation'], 'loaded' => false);
  1418. } else {
  1419. $this->xdebug('ignoring invalid XML Schema construct: include without schemaLocation attribute');
  1420. }
  1421. break;
  1422. case 'list': // simpleType value list
  1423. $this->xdebug("do nothing for element $name");
  1424. break;
  1425. case 'restriction': // simpleType, simpleContent or complexContent value restriction
  1426. $this->xdebug('restriction ' . $attrs['base']);
  1427. if($this->currentSimpleType){
  1428. $this->simpleTypes[$this->currentSimpleType]['type'] = $attrs['base'];
  1429. } elseif($this->currentComplexType){
  1430. $this->complexTypes[$this->currentComplexType]['restrictionBase'] = $attrs['base'];
  1431. if(strstr($attrs['base'],':') == ':Array'){
  1432. $this->complexTypes[$this->currentComplexType]['phpType'] = 'array';
  1433. }
  1434. }
  1435. break;
  1436. case 'schema':
  1437. $this->schemaInfo = $attrs;
  1438. $this->schemaInfo['schemaVersion'] = $this->getNamespaceFromPrefix($prefix);
  1439. if (isset($attrs['targetNamespace'])) {
  1440. $this->schemaTargetNamespace = $attrs['targetNamespace'];
  1441. }
  1442. if (!isset($attrs['elementFormDefault'])) {
  1443. $this->schemaInfo['elementFormDefault'] = 'unqualified';
  1444. }
  1445. if (!isset($attrs['attributeFormDefault'])) {
  1446. $this->schemaInfo['attributeFormDefault'] = 'unqualified';
  1447. }
  1448. break;
  1449. case 'simpleContent': // (optional) content for a complexType
  1450. if ($this->currentComplexType) { // This should *always* be
  1451. $this->complexTypes[$this->currentComplexType]['simpleContent'] = 'true';
  1452. } else {
  1453. $this->xdebug("do nothing for element $name because there is no current complexType");
  1454. }
  1455. break;
  1456. case 'simpleType':
  1457. array_push($this->simpleTypeStack, $this->currentSimpleType);
  1458. if(isset($attrs['name'])){
  1459. $this->xdebug("processing simpleType for name " . $attrs['name']);
  1460. $this->currentSimpleType = $attrs['name'];
  1461. $this->simpleTypes[ $attrs['name'] ] = $attrs;
  1462. $this->simpleTypes[ $attrs['name'] ]['typeClass'] = 'simpleType';
  1463. $this->simpleTypes[ $attrs['name'] ]['phpType'] = 'scalar';
  1464. } else {
  1465. $name = $this->CreateTypeName($this->currentComplexType . '_' . $this->currentElement);
  1466. $this->xdebug('processing unnamed simpleType for element ' . $this->currentElement . ' named ' . $name);
  1467. $this->currentSimpleType = $name;
  1468. //$this->current…

Large files files are truncated, but you can click here to view the full file