PageRenderTime 56ms CodeModel.GetById 17ms RepoModel.GetById 0ms app.codeStats 1ms

/classes/nusoap.php

https://github.com/ngocphong1991/buylink
PHP | 7288 lines | 5933 code | 190 blank | 1165 comment | 662 complexity | a5803ba316297787747372d2e6a03be0 MD5 | raw file
Possible License(s): LGPL-2.1, GPL-2.0, AGPL-1.0, MPL-2.0-no-copyleft-exception

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

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

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