nusoap_base

Nusoap_base.

Defined (2)

The class is defined in the following location(s).

/lib/class.nusoap_base.php  
  1. class nusoap_base { 
  2. /** 
  3. * Identification for HTTP headers. 
  4. * @var string 
  5. * @access private 
  6. */ 
  7. var $title = 'NuSOAP'; 
  8. /** 
  9. * Version for HTTP headers. 
  10. * @var string 
  11. * @access private 
  12. */ 
  13. var $version = '0.9.5'; 
  14. /** 
  15. * CVS revision for HTTP headers. 
  16. * @var string 
  17. * @access private 
  18. */ 
  19. var $revision = '$Revision: 1.56 $'; 
  20. /** 
  21. * Current error string (manipulated by getError/setError) 
  22. * @var string 
  23. * @access private 
  24. */ 
  25. var $error_str = ''; 
  26. /** 
  27. * Current debug string (manipulated by debug/appendDebug/clearDebug/getDebug/getDebugAsXMLComment) 
  28. * @var string 
  29. * @access private 
  30. */ 
  31. var $debug_str = ''; 
  32. /** 
  33. * toggles automatic encoding of special characters as entities 
  34. * (should always be true, I think) 
  35. * @var boolean 
  36. * @access private 
  37. */ 
  38. var $charencoding = true; 
  39. /** 
  40. * the debug level for this instance 
  41. * @var integer 
  42. * @access private 
  43. */ 
  44. var $debugLevel; 
  45.  
  46. /** 
  47. * set schema version 
  48. * @var string 
  49. * @access public 
  50. */ 
  51. var $XMLSchemaVersion = 'http://www.w3.org/2001/XMLSchema'; 
  52.  
  53. /** 
  54. * charset encoding for outgoing messages 
  55. * @var string 
  56. * @access public 
  57. */ 
  58. var $soap_defencoding = 'ISO-8859-1'; 
  59. //var $soap_defencoding = 'UTF-8'; 
  60.  
  61. /** 
  62. * namespaces in an array of prefix => uri 
  63. * this is "seeded" by a set of constants, but it may be altered by code 
  64. * @var array 
  65. * @access public 
  66. */ 
  67. var $namespaces = array( 
  68. 'SOAP-ENV' => 'http://schemas.xmlsoap.org/soap/envelope/',  
  69. 'xsd' => 'http://www.w3.org/2001/XMLSchema',  
  70. 'xsi' => 'http://www.w3.org/2001/XMLSchema-instance',  
  71. 'SOAP-ENC' => 'http://schemas.xmlsoap.org/soap/encoding/' 
  72. ); 
  73.  
  74. /** 
  75. * namespaces used in the current context, e.g. during serialization 
  76. * @var array 
  77. * @access private 
  78. */ 
  79. var $usedNamespaces = array(); 
  80.  
  81. /** 
  82. * XML Schema types in an array of uri => (array of xml type => php type) 
  83. * is this legacy yet? 
  84. * no, this is used by the nusoap_xmlschema class to verify type => namespace mappings. 
  85. * @var array 
  86. * @access public 
  87. */ 
  88. var $typemap = array( 
  89. 'http://www.w3.org/2001/XMLSchema' => array( 
  90. 'string'=>'string', 'boolean'=>'boolean', 'float'=>'double', 'double'=>'double', 'decimal'=>'double',  
  91. 'duration'=>'', 'dateTime'=>'string', 'time'=>'string', 'date'=>'string', 'gYearMonth'=>'',  
  92. 'gYear'=>'', 'gMonthDay'=>'', 'gDay'=>'', 'gMonth'=>'', 'hexBinary'=>'string', 'base64Binary'=>'string',  
  93. // abstract "any" types 
  94. 'anyType'=>'string', 'anySimpleType'=>'string',  
  95. // derived datatypes 
  96. 'normalizedString'=>'string', 'token'=>'string', 'language'=>'', 'NMTOKEN'=>'', 'NMTOKENS'=>'', 'Name'=>'', 'NCName'=>'', 'ID'=>'',  
  97. 'IDREF'=>'', 'IDREFS'=>'', 'ENTITY'=>'', 'ENTITIES'=>'', 'integer'=>'integer', 'nonPositiveInteger'=>'integer',  
  98. 'negativeInteger'=>'integer', 'long'=>'integer', 'int'=>'integer', 'short'=>'integer', 'byte'=>'integer', 'nonNegativeInteger'=>'integer',  
  99. 'unsignedLong'=>'', 'unsignedInt'=>'', 'unsignedShort'=>'', 'unsignedByte'=>'', 'positiveInteger'=>''),  
  100. 'http://www.w3.org/2000/10/XMLSchema' => array( 
  101. 'i4'=>'', 'int'=>'integer', 'boolean'=>'boolean', 'string'=>'string', 'double'=>'double',  
  102. 'float'=>'double', 'dateTime'=>'string',  
  103. 'timeInstant'=>'string', 'base64Binary'=>'string', 'base64'=>'string', 'ur-type'=>'array'),  
  104. 'http://www.w3.org/1999/XMLSchema' => array( 
  105. 'i4'=>'', 'int'=>'integer', 'boolean'=>'boolean', 'string'=>'string', 'double'=>'double',  
  106. 'float'=>'double', 'dateTime'=>'string',  
  107. 'timeInstant'=>'string', 'base64Binary'=>'string', 'base64'=>'string', 'ur-type'=>'array'),  
  108. 'http://soapinterop.org/xsd' => array('SOAPStruct'=>'struct'),  
  109. 'http://schemas.xmlsoap.org/soap/encoding/' => array('base64'=>'string', 'array'=>'array', 'Array'=>'array'),  
  110. 'http://xml.apache.org/xml-soap' => array('Map') 
  111. ); 
  112.  
  113. /** 
  114. * XML entities to convert 
  115. * @var array 
  116. * @access public 
  117. * @deprecated 
  118. * @see expandEntities 
  119. */ 
  120. var $xmlEntities = array('quot' => '"', 'amp' => '&',  
  121. 'lt' => '<', 'gt' => '>', 'apos' => "'"); 
  122.  
  123. /** 
  124. * constructor 
  125. * @access public 
  126. */ 
  127. function nusoap_base() { 
  128. $this->debugLevel = $GLOBALS['_transient']['static']['nusoap_base']['globalDebugLevel']; 
  129.  
  130. /** 
  131. * gets the global debug level, which applies to future instances 
  132. * @return integer Debug level 0-9, where 0 turns off 
  133. * @access public 
  134. */ 
  135. function getGlobalDebugLevel() { 
  136. return $GLOBALS['_transient']['static']['nusoap_base']['globalDebugLevel']; 
  137.  
  138. /** 
  139. * sets the global debug level, which applies to future instances 
  140. * @param int $level Debug level 0-9, where 0 turns off 
  141. * @access public 
  142. */ 
  143. function setGlobalDebugLevel($level) { 
  144. $GLOBALS['_transient']['static']['nusoap_base']['globalDebugLevel'] = $level; 
  145.  
  146. /** 
  147. * gets the debug level for this instance 
  148. * @return int Debug level 0-9, where 0 turns off 
  149. * @access public 
  150. */ 
  151. function getDebugLevel() { 
  152. return $this->debugLevel; 
  153.  
  154. /** 
  155. * sets the debug level for this instance 
  156. * @param int $level Debug level 0-9, where 0 turns off 
  157. * @access public 
  158. */ 
  159. function setDebugLevel($level) { 
  160. $this->debugLevel = $level; 
  161.  
  162. /** 
  163. * adds debug data to the instance debug string with formatting 
  164. * @param string $string debug data 
  165. * @access private 
  166. */ 
  167. function debug($string) { 
  168. if ($this->debugLevel > 0) { 
  169. $this->appendDebug($this->getmicrotime().' '.get_class($this).": $string\n"); 
  170.  
  171. /** 
  172. * adds debug data to the instance debug string without formatting 
  173. * @param string $string debug data 
  174. * @access public 
  175. */ 
  176. function appendDebug($string) { 
  177. if ($this->debugLevel > 0) { 
  178. // it would be nice to use a memory stream here to use 
  179. // memory more efficiently 
  180. $this->debug_str .= $string; 
  181.  
  182. /** 
  183. * clears the current debug data for this instance 
  184. * @access public 
  185. */ 
  186. function clearDebug() { 
  187. // it would be nice to use a memory stream here to use 
  188. // memory more efficiently 
  189. $this->debug_str = ''; 
  190.  
  191. /** 
  192. * gets the current debug data for this instance 
  193. * @return debug data 
  194. * @access public 
  195. */ 
  196. function &getDebug() { 
  197. // it would be nice to use a memory stream here to use 
  198. // memory more efficiently 
  199. return $this->debug_str; 
  200.  
  201. /** 
  202. * gets the current debug data for this instance as an XML comment 
  203. * this may change the contents of the debug data 
  204. * @return debug data as an XML comment 
  205. * @access public 
  206. */ 
  207. function &getDebugAsXMLComment() { 
  208. // it would be nice to use a memory stream here to use 
  209. // memory more efficiently 
  210. while (strpos($this->debug_str, '--')) { 
  211. $this->debug_str = str_replace('--', '- -', $this->debug_str); 
  212. $ret = "<!--\n" . $this->debug_str . "\n-->"; 
  213. return $ret; 
  214.  
  215. /** 
  216. * expands entities, e.g. changes '<' to '<'. 
  217. * @param string $val The string in which to expand entities. 
  218. * @access private 
  219. */ 
  220. function expandEntities($val) { 
  221. if ($this->charencoding) { 
  222. $val = str_replace('&', '&', $val); 
  223. $val = str_replace("'", ''', $val); 
  224. $val = str_replace('"', '"', $val); 
  225. $val = str_replace('<', '<', $val); 
  226. $val = str_replace('>', '>', $val); 
  227. return $val; 
  228.  
  229. /** 
  230. * returns error string if present 
  231. * @return mixed error string or false 
  232. * @access public 
  233. */ 
  234. function getError() { 
  235. if($this->error_str != '') { 
  236. return $this->error_str; 
  237. return false; 
  238.  
  239. /** 
  240. * sets error string 
  241. * @return boolean $string error string 
  242. * @access private 
  243. */ 
  244. function setError($str) { 
  245. $this->error_str = $str; 
  246.  
  247. /** 
  248. * detect if array is a simple array or a struct (associative array) 
  249. * @param mixed $val The PHP array 
  250. * @return string (arraySimple|arrayStruct) 
  251. * @access private 
  252. */ 
  253. function isArraySimpleOrStruct($val) { 
  254. $keyList = array_keys($val); 
  255. foreach ($keyList as $keyListValue) { 
  256. if (!is_int($keyListValue)) { 
  257. return 'arrayStruct'; 
  258. return 'arraySimple'; 
  259.  
  260. /** 
  261. * serializes PHP values in accordance w/ section 5. Type information is 
  262. * not serialized if $use == 'literal'. 
  263. * @param mixed $val The value to serialize 
  264. * @param string $name The name (local part) of the XML element 
  265. * @param string $type The XML schema type (local part) for the element 
  266. * @param string $name_ns The namespace for the name of the XML element 
  267. * @param string $type_ns The namespace for the type of the element 
  268. * @param array $attributes The attributes to serialize as name=>value pairs 
  269. * @param string $use The WSDL "use" (encoded|literal) 
  270. * @param boolean $soapval Whether this is called from soapval. 
  271. * @return string The serialized element, possibly with child elements 
  272. * @access public 
  273. */ 
  274. function serialize_val($val, $name=false, $type=false, $name_ns=false, $type_ns=false, $attributes=false, $use='encoded', $soapval=false) { 
  275. $this->debug("in serialize_val: name=$name, type=$type, name_ns=$name_ns, type_ns=$type_ns, use=$use, soapval=$soapval"); 
  276. $this->appendDebug('value=' . $this->varDump($val)); 
  277. $this->appendDebug('attributes=' . $this->varDump($attributes)); 
  278.  
  279. if (is_object($val) && get_class($val) == 'soapval' && (! $soapval)) { 
  280. $this->debug("serialize_val: serialize soapval"); 
  281. $xml = $val->serialize($use); 
  282. $this->appendDebug($val->getDebug()); 
  283. $val->clearDebug(); 
  284. $this->debug("serialize_val of soapval returning $xml"); 
  285. return $xml; 
  286. // force valid name if necessary 
  287. if (is_numeric($name)) { 
  288. $name = '__numeric_' . $name; 
  289. } elseif (! $name) { 
  290. $name = 'noname'; 
  291. // if name has ns, add ns prefix to name 
  292. $xmlns = ''; 
  293. if($name_ns) { 
  294. $prefix = 'nu'.rand(1000, 9999); 
  295. $name = $prefix.':'.$name; 
  296. $xmlns .= " xmlns:$prefix=\"$name_ns\""; 
  297. // if type is prefixed, create type prefix 
  298. if($type_ns != '' && $type_ns == $this->namespaces['xsd']) { 
  299. // need to fix this. shouldn't default to xsd if no ns specified 
  300. // w/o checking against typemap 
  301. $type_prefix = 'xsd'; 
  302. } elseif($type_ns) { 
  303. $type_prefix = 'ns'.rand(1000, 9999); 
  304. $xmlns .= " xmlns:$type_prefix=\"$type_ns\""; 
  305. // serialize attributes if present 
  306. $atts = ''; 
  307. if($attributes) { 
  308. foreach($attributes as $k => $v) { 
  309. $atts .= " $k=\"".$this->expandEntities($v).'"'; 
  310. // serialize null value 
  311. if (is_null($val)) { 
  312. $this->debug("serialize_val: serialize null"); 
  313. if ($use == 'literal') { 
  314. // TODO: depends on minOccurs 
  315. $xml = "<$name$xmlns$atts/>"; 
  316. $this->debug("serialize_val returning $xml"); 
  317. return $xml; 
  318. } else { 
  319. if (isset($type) && isset($type_prefix)) { 
  320. $type_str = " xsi:type=\"$type_prefix:$type\""; 
  321. } else { 
  322. $type_str = ''; 
  323. $xml = "<$name$xmlns$type_str$atts xsi:nil=\"true\"/>"; 
  324. $this->debug("serialize_val returning $xml"); 
  325. return $xml; 
  326. // serialize if an xsd built-in primitive type 
  327. if($type != '' && isset($this->typemap[$this->XMLSchemaVersion][$type])) { 
  328. $this->debug("serialize_val: serialize xsd built-in primitive type"); 
  329. if (is_bool($val)) { 
  330. if ($type == 'boolean') { 
  331. $val = $val ? 'true' : 'false'; 
  332. } elseif (! $val) { 
  333. $val = 0; 
  334. } else if (is_string($val)) { 
  335. $val = $this->expandEntities($val); 
  336. if ($use == 'literal') { 
  337. $xml = "<$name$xmlns$atts>$val</$name>"; 
  338. $this->debug("serialize_val returning $xml"); 
  339. return $xml; 
  340. } else { 
  341. $xml = "<$name$xmlns xsi:type=\"xsd:$type\"$atts>$val</$name>"; 
  342. $this->debug("serialize_val returning $xml"); 
  343. return $xml; 
  344. // detect type and serialize 
  345. $xml = ''; 
  346. switch(true) { 
  347. case (is_bool($val) || $type == 'boolean'): 
  348. $this->debug("serialize_val: serialize boolean"); 
  349. if ($type == 'boolean') { 
  350. $val = $val ? 'true' : 'false'; 
  351. } elseif (! $val) { 
  352. $val = 0; 
  353. if ($use == 'literal') { 
  354. $xml .= "<$name$xmlns$atts>$val</$name>"; 
  355. } else { 
  356. $xml .= "<$name$xmlns xsi:type=\"xsd:boolean\"$atts>$val</$name>"; 
  357. break; 
  358. case (is_int($val) || is_long($val) || $type == 'int'): 
  359. $this->debug("serialize_val: serialize int"); 
  360. if ($use == 'literal') { 
  361. $xml .= "<$name$xmlns$atts>$val</$name>"; 
  362. } else { 
  363. $xml .= "<$name$xmlns xsi:type=\"xsd:int\"$atts>$val</$name>"; 
  364. break; 
  365. case (is_float($val)|| is_double($val) || $type == 'float'): 
  366. $this->debug("serialize_val: serialize float"); 
  367. if ($use == 'literal') { 
  368. $xml .= "<$name$xmlns$atts>$val</$name>"; 
  369. } else { 
  370. $xml .= "<$name$xmlns xsi:type=\"xsd:float\"$atts>$val</$name>"; 
  371. break; 
  372. case (is_string($val) || $type == 'string'): 
  373. $this->debug("serialize_val: serialize string"); 
  374. $val = $this->expandEntities($val); 
  375. if ($use == 'literal') { 
  376. $xml .= "<$name$xmlns$atts>$val</$name>"; 
  377. } else { 
  378. $xml .= "<$name$xmlns xsi:type=\"xsd:string\"$atts>$val</$name>"; 
  379. break; 
  380. case is_object($val): 
  381. $this->debug("serialize_val: serialize object"); 
  382. if (get_class($val) == 'soapval') { 
  383. $this->debug("serialize_val: serialize soapval object"); 
  384. $pXml = $val->serialize($use); 
  385. $this->appendDebug($val->getDebug()); 
  386. $val->clearDebug(); 
  387. } else { 
  388. if (! $name) { 
  389. $name = get_class($val); 
  390. $this->debug("In serialize_val, used class name $name as element name"); 
  391. } else { 
  392. $this->debug("In serialize_val, do not override name $name for element name for class " . get_class($val)); 
  393. foreach(get_object_vars($val) as $k => $v) { 
  394. $pXml = isset($pXml) ? $pXml.$this->serialize_val($v, $k, false, false, false, false, $use) : $this->serialize_val($v, $k, false, false, false, false, $use); 
  395. if(isset($type) && isset($type_prefix)) { 
  396. $type_str = " xsi:type=\"$type_prefix:$type\""; 
  397. } else { 
  398. $type_str = ''; 
  399. if ($use == 'literal') { 
  400. $xml .= "<$name$xmlns$atts>$pXml</$name>"; 
  401. } else { 
  402. $xml .= "<$name$xmlns$type_str$atts>$pXml</$name>"; 
  403. break; 
  404. break; 
  405. case (is_array($val) || $type): 
  406. // detect if struct or array 
  407. $valueType = $this->isArraySimpleOrStruct($val); 
  408. if($valueType=='arraySimple' || preg_match('/^ArrayOf/', $type)) { 
  409. $this->debug("serialize_val: serialize array"); 
  410. $i = 0; 
  411. if(is_array($val) && count($val)> 0) { 
  412. foreach($val as $v) { 
  413. if(is_object($v) && get_class($v) == 'soapval') { 
  414. $tt_ns = $v->type_ns; 
  415. $tt = $v->type; 
  416. } elseif (is_array($v)) { 
  417. $tt = $this->isArraySimpleOrStruct($v); 
  418. } else { 
  419. $tt = gettype($v); 
  420. $array_types[$tt] = 1; 
  421. // TODO: for literal, the name should be $name 
  422. $xml .= $this->serialize_val($v, 'item', false, false, false, false, $use); 
  423. ++$i; 
  424. if(count($array_types) > 1) { 
  425. $array_typename = 'xsd:anyType'; 
  426. } elseif(isset($tt) && isset($this->typemap[$this->XMLSchemaVersion][$tt])) { 
  427. if ($tt == 'integer') { 
  428. $tt = 'int'; 
  429. $array_typename = 'xsd:'.$tt; 
  430. } elseif(isset($tt) && $tt == 'arraySimple') { 
  431. $array_typename = 'SOAP-ENC:Array'; 
  432. } elseif(isset($tt) && $tt == 'arrayStruct') { 
  433. $array_typename = 'unnamed_struct_use_soapval'; 
  434. } else { 
  435. // if type is prefixed, create type prefix 
  436. if ($tt_ns != '' && $tt_ns == $this->namespaces['xsd']) { 
  437. $array_typename = 'xsd:' . $tt; 
  438. } elseif ($tt_ns) { 
  439. $tt_prefix = 'ns' . rand(1000, 9999); 
  440. $array_typename = "$tt_prefix:$tt"; 
  441. $xmlns .= " xmlns:$tt_prefix=\"$tt_ns\""; 
  442. } else { 
  443. $array_typename = $tt; 
  444. $array_type = $i; 
  445. if ($use == 'literal') { 
  446. $type_str = ''; 
  447. } else if (isset($type) && isset($type_prefix)) { 
  448. $type_str = " xsi:type=\"$type_prefix:$type\""; 
  449. } else { 
  450. $type_str = " xsi:type=\"SOAP-ENC:Array\" SOAP-ENC:arrayType=\"".$array_typename."[$array_type]\""; 
  451. // empty array 
  452. } else { 
  453. if ($use == 'literal') { 
  454. $type_str = ''; 
  455. } else if (isset($type) && isset($type_prefix)) { 
  456. $type_str = " xsi:type=\"$type_prefix:$type\""; 
  457. } else { 
  458. $type_str = " xsi:type=\"SOAP-ENC:Array\" SOAP-ENC:arrayType=\"xsd:anyType[0]\""; 
  459. // TODO: for array in literal, there is no wrapper here 
  460. $xml = "<$name$xmlns$type_str$atts>".$xml."</$name>"; 
  461. } else { 
  462. // got a struct 
  463. $this->debug("serialize_val: serialize struct"); 
  464. if(isset($type) && isset($type_prefix)) { 
  465. $type_str = " xsi:type=\"$type_prefix:$type\""; 
  466. } else { 
  467. $type_str = ''; 
  468. if ($use == 'literal') { 
  469. $xml .= "<$name$xmlns$atts>"; 
  470. } else { 
  471. $xml .= "<$name$xmlns$type_str$atts>"; 
  472. foreach($val as $k => $v) { 
  473. // Apache Map 
  474. if ($type == 'Map' && $type_ns == 'http://xml.apache.org/xml-soap') { 
  475. $xml .= '<item>'; 
  476. $xml .= $this->serialize_val($k, 'key', false, false, false, false, $use); 
  477. $xml .= $this->serialize_val($v, 'value', false, false, false, false, $use); 
  478. $xml .= '</item>'; 
  479. } else { 
  480. $xml .= $this->serialize_val($v, $k, false, false, false, false, $use); 
  481. $xml .= "</$name>"; 
  482. break; 
  483. default: 
  484. $this->debug("serialize_val: serialize unknown"); 
  485. $xml .= 'not detected, got '.gettype($val).' for '.$val; 
  486. break; 
  487. $this->debug("serialize_val returning $xml"); 
  488. return $xml; 
  489.  
  490. /** 
  491. * serializes a message 
  492. * @param string $body the XML of the SOAP body 
  493. * @param mixed $headers optional string of XML with SOAP header content, or array of soapval objects for SOAP headers, or associative array 
  494. * @param array $namespaces optional the namespaces used in generating the body and headers 
  495. * @param string $style optional (rpc|document) 
  496. * @param string $use optional (encoded|literal) 
  497. * @param string $encodingStyle optional (usually 'http://schemas.xmlsoap.org/soap/encoding/' for encoded) 
  498. * @return string the message 
  499. * @access public 
  500. */ 
  501. function serializeEnvelope($body, $headers=false, $namespaces=array(), $style='rpc', $use='encoded', $encodingStyle='http://schemas.xmlsoap.org/soap/encoding/') { 
  502. // TODO: add an option to automatically run utf8_encode on $body and $headers 
  503. // if $this->soap_defencoding is UTF-8. Not doing this automatically allows 
  504. // one to send arbitrary UTF-8 characters, not just characters that map to ISO-8859-1 
  505.  
  506. $this->debug("In serializeEnvelope length=" . strlen($body) . " body (max 1000 characters)=" . substr($body, 0, 1000) . " style=$style use=$use encodingStyle=$encodingStyle"); 
  507. $this->debug("headers:"); 
  508. $this->appendDebug($this->varDump($headers)); 
  509. $this->debug("namespaces:"); 
  510. $this->appendDebug($this->varDump($namespaces)); 
  511.  
  512. // serialize namespaces 
  513. $ns_string = ''; 
  514. foreach(array_merge($this->namespaces, $namespaces) as $k => $v) { 
  515. $ns_string .= " xmlns:$k=\"$v\""; 
  516. if($encodingStyle) { 
  517. $ns_string = " SOAP-ENV:encodingStyle=\"$encodingStyle\"$ns_string"; 
  518.  
  519. // serialize headers 
  520. if($headers) { 
  521. if (is_array($headers)) { 
  522. $xml = ''; 
  523. foreach ($headers as $k => $v) { 
  524. if (is_object($v) && get_class($v) == 'soapval') { 
  525. $xml .= $this->serialize_val($v, false, false, false, false, false, $use); 
  526. } else { 
  527. $xml .= $this->serialize_val($v, $k, false, false, false, false, $use); 
  528. $headers = $xml; 
  529. $this->debug("In serializeEnvelope, serialized array of headers to $headers"); 
  530. $headers = "<SOAP-ENV:Header>".$headers."</SOAP-ENV:Header>"; 
  531. // serialize envelope 
  532. return 
  533. '<?xml version="1.0" encoding="'.$this->soap_defencoding .'"?'.">". 
  534. '<SOAP-ENV:Envelope'.$ns_string.">". 
  535. $headers. 
  536. "<SOAP-ENV:Body>". 
  537. $body. 
  538. "</SOAP-ENV:Body>". 
  539. "</SOAP-ENV:Envelope>"; 
  540.  
  541. /** 
  542. * formats a string to be inserted into an HTML stream 
  543. * @param string $str The string to format 
  544. * @return string The formatted string 
  545. * @access public 
  546. * @deprecated 
  547. */ 
  548. function formatDump($str) { 
  549. $str = htmlspecialchars($str); 
  550. return nl2br($str); 
  551.  
  552. /** 
  553. * contracts (changes namespace to prefix) a qualified name 
  554. * @param string $qname qname 
  555. * @return string contracted qname 
  556. * @access private 
  557. */ 
  558. function contractQname($qname) { 
  559. // get element namespace 
  560. //$this->xdebug("Contract $qname"); 
  561. if (strrpos($qname, ':')) { 
  562. // get unqualified name 
  563. $name = substr($qname, strrpos($qname, ':') + 1); 
  564. // get ns 
  565. $ns = substr($qname, 0, strrpos($qname, ':')); 
  566. $p = $this->getPrefixFromNamespace($ns); 
  567. if ($p) { 
  568. return $p . ':' . $name; 
  569. return $qname; 
  570. } else { 
  571. return $qname; 
  572.  
  573. /** 
  574. * expands (changes prefix to namespace) a qualified name 
  575. * @param string $qname qname 
  576. * @return string expanded qname 
  577. * @access private 
  578. */ 
  579. function expandQname($qname) { 
  580. // get element prefix 
  581. if(strpos($qname, ':') && !preg_match('/^http:\/\//', $qname)) { 
  582. // get unqualified name 
  583. $name = substr(strstr($qname, ':'), 1); 
  584. // get ns prefix 
  585. $prefix = substr($qname, 0, strpos($qname, ':')); 
  586. if(isset($this->namespaces[$prefix])) { 
  587. return $this->namespaces[$prefix].':'.$name; 
  588. } else { 
  589. return $qname; 
  590. } else { 
  591. return $qname; 
  592.  
  593. /** 
  594. * returns the local part of a prefixed string 
  595. * returns the original string, if not prefixed 
  596. * @param string $str The prefixed string 
  597. * @return string The local part 
  598. * @access public 
  599. */ 
  600. function getLocalPart($str) { 
  601. if($sstr = strrchr($str, ':')) { 
  602. // get unqualified name 
  603. return substr( $sstr, 1 ); 
  604. } else { 
  605. return $str; 
  606.  
  607. /** 
  608. * returns the prefix part of a prefixed string 
  609. * returns false, if not prefixed 
  610. * @param string $str The prefixed string 
  611. * @return mixed The prefix or false if there is no prefix 
  612. * @access public 
  613. */ 
  614. function getPrefix($str) { 
  615. if($pos = strrpos($str, ':')) { 
  616. // get prefix 
  617. return substr($str, 0, $pos); 
  618. return false; 
  619.  
  620. /** 
  621. * pass it a prefix, it returns a namespace 
  622. * @param string $prefix The prefix 
  623. * @return mixed The namespace, false if no namespace has the specified prefix 
  624. * @access public 
  625. */ 
  626. function getNamespaceFromPrefix($prefix) { 
  627. if (isset($this->namespaces[$prefix])) { 
  628. return $this->namespaces[$prefix]; 
  629. //$this->setError("No namespace registered for prefix '$prefix'"); 
  630. return false; 
  631.  
  632. /** 
  633. * returns the prefix for a given namespace (or prefix) 
  634. * or false if no prefixes registered for the given namespace 
  635. * @param string $ns The namespace 
  636. * @return mixed The prefix, false if the namespace has no prefixes 
  637. * @access public 
  638. */ 
  639. function getPrefixFromNamespace($ns) { 
  640. foreach ($this->namespaces as $p => $n) { 
  641. if ($ns == $n || $ns == $p) { 
  642. $this->usedNamespaces[$p] = $n; 
  643. return $p; 
  644. return false; 
  645.  
  646. /** 
  647. * returns the time in ODBC canonical form with microseconds 
  648. * @return string The time in ODBC canonical form with microseconds 
  649. * @access public 
  650. */ 
  651. function getmicrotime() { 
  652. if (function_exists('gettimeofday')) { 
  653. $tod = gettimeofday(); 
  654. $sec = $tod['sec']; 
  655. $usec = $tod['usec']; 
  656. } else { 
  657. $sec = time(); 
  658. $usec = 0; 
  659. return strftime('%Y-%m-%d %H:%M:%S', $sec) . '.' . sprintf('%06d', $usec); 
  660.  
  661. /** 
  662. * Returns a string with the output of var_dump 
  663. * @param mixed $data The variable to var_dump 
  664. * @return string The output of var_dump 
  665. * @access public 
  666. */ 
  667. function varDump($data) { 
  668. ob_start(); 
  669. var_dump($data); 
  670. $ret_val = ob_get_contents(); 
  671. ob_end_clean(); 
  672. return $ret_val; 
  673.  
  674. /** 
  675. * represents the object as a string 
  676. * @return string 
  677. * @access public 
  678. */ 
  679. function __toString() { 
  680. return $this->varDump($this); 
/lib/nusoap.php  
  1. class nusoap_base { 
  2. /** 
  3. * Identification for HTTP headers. 
  4. * @var string 
  5. * @access private 
  6. */ 
  7. var $title = 'NuSOAP'; 
  8. /** 
  9. * Version for HTTP headers. 
  10. * @var string 
  11. * @access private 
  12. */ 
  13. var $version = '0.9.5'; 
  14. /** 
  15. * CVS revision for HTTP headers. 
  16. * @var string 
  17. * @access private 
  18. */ 
  19. var $revision = '$Revision: 1.123 $'; 
  20. /** 
  21. * Current error string (manipulated by getError/setError) 
  22. * @var string 
  23. * @access private 
  24. */ 
  25. var $error_str = ''; 
  26. /** 
  27. * Current debug string (manipulated by debug/appendDebug/clearDebug/getDebug/getDebugAsXMLComment) 
  28. * @var string 
  29. * @access private 
  30. */ 
  31. var $debug_str = ''; 
  32. /** 
  33. * toggles automatic encoding of special characters as entities 
  34. * (should always be true, I think) 
  35. * @var boolean 
  36. * @access private 
  37. */ 
  38. var $charencoding = true; 
  39. /** 
  40. * the debug level for this instance 
  41. * @var integer 
  42. * @access private 
  43. */ 
  44. var $debugLevel; 
  45.  
  46. /** 
  47. * set schema version 
  48. * @var string 
  49. * @access public 
  50. */ 
  51. var $XMLSchemaVersion = 'http://www.w3.org/2001/XMLSchema'; 
  52.  
  53. /** 
  54. * charset encoding for outgoing messages 
  55. * @var string 
  56. * @access public 
  57. */ 
  58. var $soap_defencoding = 'ISO-8859-1'; 
  59. //var $soap_defencoding = 'UTF-8'; 
  60.  
  61. /** 
  62. * namespaces in an array of prefix => uri 
  63. * this is "seeded" by a set of constants, but it may be altered by code 
  64. * @var array 
  65. * @access public 
  66. */ 
  67. var $namespaces = array( 
  68. 'SOAP-ENV' => 'http://schemas.xmlsoap.org/soap/envelope/',  
  69. 'xsd' => 'http://www.w3.org/2001/XMLSchema',  
  70. 'xsi' => 'http://www.w3.org/2001/XMLSchema-instance',  
  71. 'SOAP-ENC' => 'http://schemas.xmlsoap.org/soap/encoding/' 
  72. ); 
  73.  
  74. /** 
  75. * namespaces used in the current context, e.g. during serialization 
  76. * @var array 
  77. * @access private 
  78. */ 
  79. var $usedNamespaces = array(); 
  80.  
  81. /** 
  82. * XML Schema types in an array of uri => (array of xml type => php type) 
  83. * is this legacy yet? 
  84. * no, this is used by the nusoap_xmlschema class to verify type => namespace mappings. 
  85. * @var array 
  86. * @access public 
  87. */ 
  88. var $typemap = array( 
  89. 'http://www.w3.org/2001/XMLSchema' => array( 
  90. 'string'=>'string', 'boolean'=>'boolean', 'float'=>'double', 'double'=>'double', 'decimal'=>'double',  
  91. 'duration'=>'', 'dateTime'=>'string', 'time'=>'string', 'date'=>'string', 'gYearMonth'=>'',  
  92. 'gYear'=>'', 'gMonthDay'=>'', 'gDay'=>'', 'gMonth'=>'', 'hexBinary'=>'string', 'base64Binary'=>'string',  
  93. // abstract "any" types 
  94. 'anyType'=>'string', 'anySimpleType'=>'string',  
  95. // derived datatypes 
  96. 'normalizedString'=>'string', 'token'=>'string', 'language'=>'', 'NMTOKEN'=>'', 'NMTOKENS'=>'', 'Name'=>'', 'NCName'=>'', 'ID'=>'',  
  97. 'IDREF'=>'', 'IDREFS'=>'', 'ENTITY'=>'', 'ENTITIES'=>'', 'integer'=>'integer', 'nonPositiveInteger'=>'integer',  
  98. 'negativeInteger'=>'integer', 'long'=>'integer', 'int'=>'integer', 'short'=>'integer', 'byte'=>'integer', 'nonNegativeInteger'=>'integer',  
  99. 'unsignedLong'=>'', 'unsignedInt'=>'', 'unsignedShort'=>'', 'unsignedByte'=>'', 'positiveInteger'=>''),  
  100. 'http://www.w3.org/2000/10/XMLSchema' => array( 
  101. 'i4'=>'', 'int'=>'integer', 'boolean'=>'boolean', 'string'=>'string', 'double'=>'double',  
  102. 'float'=>'double', 'dateTime'=>'string',  
  103. 'timeInstant'=>'string', 'base64Binary'=>'string', 'base64'=>'string', 'ur-type'=>'array'),  
  104. 'http://www.w3.org/1999/XMLSchema' => array( 
  105. 'i4'=>'', 'int'=>'integer', 'boolean'=>'boolean', 'string'=>'string', 'double'=>'double',  
  106. 'float'=>'double', 'dateTime'=>'string',  
  107. 'timeInstant'=>'string', 'base64Binary'=>'string', 'base64'=>'string', 'ur-type'=>'array'),  
  108. 'http://soapinterop.org/xsd' => array('SOAPStruct'=>'struct'),  
  109. 'http://schemas.xmlsoap.org/soap/encoding/' => array('base64'=>'string', 'array'=>'array', 'Array'=>'array'),  
  110. 'http://xml.apache.org/xml-soap' => array('Map') 
  111. ); 
  112.  
  113. /** 
  114. * XML entities to convert 
  115. * @var array 
  116. * @access public 
  117. * @deprecated 
  118. * @see expandEntities 
  119. */ 
  120. var $xmlEntities = array('quot' => '"', 'amp' => '&',  
  121. 'lt' => '<', 'gt' => '>', 'apos' => "'"); 
  122.  
  123. /** 
  124. * constructor 
  125. * @access public 
  126. */ 
  127. function nusoap_base() { 
  128. $this->debugLevel = $GLOBALS['_transient']['static']['nusoap_base']['globalDebugLevel']; 
  129.  
  130. /** 
  131. * gets the global debug level, which applies to future instances 
  132. * @return integer Debug level 0-9, where 0 turns off 
  133. * @access public 
  134. */ 
  135. function getGlobalDebugLevel() { 
  136. return $GLOBALS['_transient']['static']['nusoap_base']['globalDebugLevel']; 
  137.  
  138. /** 
  139. * sets the global debug level, which applies to future instances 
  140. * @param int $level Debug level 0-9, where 0 turns off 
  141. * @access public 
  142. */ 
  143. function setGlobalDebugLevel($level) { 
  144. $GLOBALS['_transient']['static']['nusoap_base']['globalDebugLevel'] = $level; 
  145.  
  146. /** 
  147. * gets the debug level for this instance 
  148. * @return int Debug level 0-9, where 0 turns off 
  149. * @access public 
  150. */ 
  151. function getDebugLevel() { 
  152. return $this->debugLevel; 
  153.  
  154. /** 
  155. * sets the debug level for this instance 
  156. * @param int $level Debug level 0-9, where 0 turns off 
  157. * @access public 
  158. */ 
  159. function setDebugLevel($level) { 
  160. $this->debugLevel = $level; 
  161.  
  162. /** 
  163. * adds debug data to the instance debug string with formatting 
  164. * @param string $string debug data 
  165. * @access private 
  166. */ 
  167. function debug($string) { 
  168. if ($this->debugLevel > 0) { 
  169. $this->appendDebug($this->getmicrotime().' '.get_class($this).": $string\n"); 
  170.  
  171. /** 
  172. * adds debug data to the instance debug string without formatting 
  173. * @param string $string debug data 
  174. * @access public 
  175. */ 
  176. function appendDebug($string) { 
  177. if ($this->debugLevel > 0) { 
  178. // it would be nice to use a memory stream here to use 
  179. // memory more efficiently 
  180. $this->debug_str .= $string; 
  181.  
  182. /** 
  183. * clears the current debug data for this instance 
  184. * @access public 
  185. */ 
  186. function clearDebug() { 
  187. // it would be nice to use a memory stream here to use 
  188. // memory more efficiently 
  189. $this->debug_str = ''; 
  190.  
  191. /** 
  192. * gets the current debug data for this instance 
  193. * @return debug data 
  194. * @access public 
  195. */ 
  196. function &getDebug() { 
  197. // it would be nice to use a memory stream here to use 
  198. // memory more efficiently 
  199. return $this->debug_str; 
  200.  
  201. /** 
  202. * gets the current debug data for this instance as an XML comment 
  203. * this may change the contents of the debug data 
  204. * @return debug data as an XML comment 
  205. * @access public 
  206. */ 
  207. function &getDebugAsXMLComment() { 
  208. // it would be nice to use a memory stream here to use 
  209. // memory more efficiently 
  210. while (strpos($this->debug_str, '--')) { 
  211. $this->debug_str = str_replace('--', '- -', $this->debug_str); 
  212. $ret = "<!--\n" . $this->debug_str . "\n-->"; 
  213. return $ret; 
  214.  
  215. /** 
  216. * expands entities, e.g. changes '<' to '<'. 
  217. * @param string $val The string in which to expand entities. 
  218. * @access private 
  219. */ 
  220. function expandEntities($val) { 
  221. if ($this->charencoding) { 
  222. $val = str_replace('&', '&', $val); 
  223. $val = str_replace("'", ''', $val); 
  224. $val = str_replace('"', '"', $val); 
  225. $val = str_replace('<', '<', $val); 
  226. $val = str_replace('>', '>', $val); 
  227. return $val; 
  228.  
  229. /** 
  230. * returns error string if present 
  231. * @return mixed error string or false 
  232. * @access public 
  233. */ 
  234. function getError() { 
  235. if($this->error_str != '') { 
  236. return $this->error_str; 
  237. return false; 
  238.  
  239. /** 
  240. * sets error string 
  241. * @return boolean $string error string 
  242. * @access private 
  243. */ 
  244. function setError($str) { 
  245. $this->error_str = $str; 
  246.  
  247. /** 
  248. * detect if array is a simple array or a struct (associative array) 
  249. * @param mixed $val The PHP array 
  250. * @return string (arraySimple|arrayStruct) 
  251. * @access private 
  252. */ 
  253. function isArraySimpleOrStruct($val) { 
  254. $keyList = array_keys($val); 
  255. foreach ($keyList as $keyListValue) { 
  256. if (!is_int($keyListValue)) { 
  257. return 'arrayStruct'; 
  258. return 'arraySimple'; 
  259.  
  260. /** 
  261. * serializes PHP values in accordance w/ section 5. Type information is 
  262. * not serialized if $use == 'literal'. 
  263. * @param mixed $val The value to serialize 
  264. * @param string $name The name (local part) of the XML element 
  265. * @param string $type The XML schema type (local part) for the element 
  266. * @param string $name_ns The namespace for the name of the XML element 
  267. * @param string $type_ns The namespace for the type of the element 
  268. * @param array $attributes The attributes to serialize as name=>value pairs 
  269. * @param string $use The WSDL "use" (encoded|literal) 
  270. * @param boolean $soapval Whether this is called from soapval. 
  271. * @return string The serialized element, possibly with child elements 
  272. * @access public 
  273. */ 
  274. function serialize_val($val, $name=false, $type=false, $name_ns=false, $type_ns=false, $attributes=false, $use='encoded', $soapval=false) { 
  275. $this->debug("in serialize_val: name=$name, type=$type, name_ns=$name_ns, type_ns=$type_ns, use=$use, soapval=$soapval"); 
  276. $this->appendDebug('value=' . $this->varDump($val)); 
  277. $this->appendDebug('attributes=' . $this->varDump($attributes)); 
  278.  
  279. if (is_object($val) && get_class($val) == 'soapval' && (! $soapval)) { 
  280. $this->debug("serialize_val: serialize soapval"); 
  281. $xml = $val->serialize($use); 
  282. $this->appendDebug($val->getDebug()); 
  283. $val->clearDebug(); 
  284. $this->debug("serialize_val of soapval returning $xml"); 
  285. return $xml; 
  286. // force valid name if necessary 
  287. if (is_numeric($name)) { 
  288. $name = '__numeric_' . $name; 
  289. } elseif (! $name) { 
  290. $name = 'noname'; 
  291. // if name has ns, add ns prefix to name 
  292. $xmlns = ''; 
  293. if($name_ns) { 
  294. $prefix = 'nu'.rand(1000, 9999); 
  295. $name = $prefix.':'.$name; 
  296. $xmlns .= " xmlns:$prefix=\"$name_ns\""; 
  297. // if type is prefixed, create type prefix 
  298. if($type_ns != '' && $type_ns == $this->namespaces['xsd']) { 
  299. // need to fix this. shouldn't default to xsd if no ns specified 
  300. // w/o checking against typemap 
  301. $type_prefix = 'xsd'; 
  302. } elseif($type_ns) { 
  303. $type_prefix = 'ns'.rand(1000, 9999); 
  304. $xmlns .= " xmlns:$type_prefix=\"$type_ns\""; 
  305. // serialize attributes if present 
  306. $atts = ''; 
  307. if($attributes) { 
  308. foreach($attributes as $k => $v) { 
  309. $atts .= " $k=\"".$this->expandEntities($v).'"'; 
  310. // serialize null value 
  311. if (is_null($val)) { 
  312. $this->debug("serialize_val: serialize null"); 
  313. if ($use == 'literal') { 
  314. // TODO: depends on minOccurs 
  315. $xml = "<$name$xmlns$atts/>"; 
  316. $this->debug("serialize_val returning $xml"); 
  317. return $xml; 
  318. } else { 
  319. if (isset($type) && isset($type_prefix)) { 
  320. $type_str = " xsi:type=\"$type_prefix:$type\""; 
  321. } else { 
  322. $type_str = ''; 
  323. $xml = "<$name$xmlns$type_str$atts xsi:nil=\"true\"/>"; 
  324. $this->debug("serialize_val returning $xml"); 
  325. return $xml; 
  326. // serialize if an xsd built-in primitive type 
  327. if($type != '' && isset($this->typemap[$this->XMLSchemaVersion][$type])) { 
  328. $this->debug("serialize_val: serialize xsd built-in primitive type"); 
  329. if (is_bool($val)) { 
  330. if ($type == 'boolean') { 
  331. $val = $val ? 'true' : 'false'; 
  332. } elseif (! $val) { 
  333. $val = 0; 
  334. } else if (is_string($val)) { 
  335. $val = $this->expandEntities($val); 
  336. if ($use == 'literal') { 
  337. $xml = "<$name$xmlns$atts>$val</$name>"; 
  338. $this->debug("serialize_val returning $xml"); 
  339. return $xml; 
  340. } else { 
  341. $xml = "<$name$xmlns xsi:type=\"xsd:$type\"$atts>$val</$name>"; 
  342. $this->debug("serialize_val returning $xml"); 
  343. return $xml; 
  344. // detect type and serialize 
  345. $xml = ''; 
  346. switch(true) { 
  347. case (is_bool($val) || $type == 'boolean'): 
  348. $this->debug("serialize_val: serialize boolean"); 
  349. if ($type == 'boolean') { 
  350. $val = $val ? 'true' : 'false'; 
  351. } elseif (! $val) { 
  352. $val = 0; 
  353. if ($use == 'literal') { 
  354. $xml .= "<$name$xmlns$atts>$val</$name>"; 
  355. } else { 
  356. $xml .= "<$name$xmlns xsi:type=\"xsd:boolean\"$atts>$val</$name>"; 
  357. break; 
  358. case (is_int($val) || is_long($val) || $type == 'int'): 
  359. $this->debug("serialize_val: serialize int"); 
  360. if ($use == 'literal') { 
  361. $xml .= "<$name$xmlns$atts>$val</$name>"; 
  362. } else { 
  363. $xml .= "<$name$xmlns xsi:type=\"xsd:int\"$atts>$val</$name>"; 
  364. break; 
  365. case (is_float($val)|| is_double($val) || $type == 'float'): 
  366. $this->debug("serialize_val: serialize float"); 
  367. if ($use == 'literal') { 
  368. $xml .= "<$name$xmlns$atts>$val</$name>"; 
  369. } else { 
  370. $xml .= "<$name$xmlns xsi:type=\"xsd:float\"$atts>$val</$name>"; 
  371. break; 
  372. case (is_string($val) || $type == 'string'): 
  373. $this->debug("serialize_val: serialize string"); 
  374. $val = $this->expandEntities($val); 
  375. if ($use == 'literal') { 
  376. $xml .= "<$name$xmlns$atts>$val</$name>"; 
  377. } else { 
  378. $xml .= "<$name$xmlns xsi:type=\"xsd:string\"$atts>$val</$name>"; 
  379. break; 
  380. case is_object($val): 
  381. $this->debug("serialize_val: serialize object"); 
  382. if (get_class($val) == 'soapval') { 
  383. $this->debug("serialize_val: serialize soapval object"); 
  384. $pXml = $val->serialize($use); 
  385. $this->appendDebug($val->getDebug()); 
  386. $val->clearDebug(); 
  387. } else { 
  388. if (! $name) { 
  389. $name = get_class($val); 
  390. $this->debug("In serialize_val, used class name $name as element name"); 
  391. } else { 
  392. $this->debug("In serialize_val, do not override name $name for element name for class " . get_class($val)); 
  393. foreach(get_object_vars($val) as $k => $v) { 
  394. $pXml = isset($pXml) ? $pXml.$this->serialize_val($v, $k, false, false, false, false, $use) : $this->serialize_val($v, $k, false, false, false, false, $use); 
  395. if(isset($type) && isset($type_prefix)) { 
  396. $type_str = " xsi:type=\"$type_prefix:$type\""; 
  397. } else { 
  398. $type_str = ''; 
  399. if ($use == 'literal') { 
  400. $xml .= "<$name$xmlns$atts>$pXml</$name>"; 
  401. } else { 
  402. $xml .= "<$name$xmlns$type_str$atts>$pXml</$name>"; 
  403. break; 
  404. break; 
  405. case (is_array($val) || $type): 
  406. // detect if struct or array 
  407. $valueType = $this->isArraySimpleOrStruct($val); 
  408. if($valueType=='arraySimple' || preg_match('/^ArrayOf/', $type)) { 
  409. $this->debug("serialize_val: serialize array"); 
  410. $i = 0; 
  411. if(is_array($val) && count($val)> 0) { 
  412. foreach($val as $v) { 
  413. if(is_object($v) && get_class($v) == 'soapval') { 
  414. $tt_ns = $v->type_ns; 
  415. $tt = $v->type; 
  416. } elseif (is_array($v)) { 
  417. $tt = $this->isArraySimpleOrStruct($v); 
  418. } else { 
  419. $tt = gettype($v); 
  420. $array_types[$tt] = 1; 
  421. // TODO: for literal, the name should be $name 
  422. $xml .= $this->serialize_val($v, 'item', false, false, false, false, $use); 
  423. ++$i; 
  424. if(count($array_types) > 1) { 
  425. $array_typename = 'xsd:anyType'; 
  426. } elseif(isset($tt) && isset($this->typemap[$this->XMLSchemaVersion][$tt])) { 
  427. if ($tt == 'integer') { 
  428. $tt = 'int'; 
  429. $array_typename = 'xsd:'.$tt; 
  430. } elseif(isset($tt) && $tt == 'arraySimple') { 
  431. $array_typename = 'SOAP-ENC:Array'; 
  432. } elseif(isset($tt) && $tt == 'arrayStruct') { 
  433. $array_typename = 'unnamed_struct_use_soapval'; 
  434. } else { 
  435. // if type is prefixed, create type prefix 
  436. if ($tt_ns != '' && $tt_ns == $this->namespaces['xsd']) { 
  437. $array_typename = 'xsd:' . $tt; 
  438. } elseif ($tt_ns) { 
  439. $tt_prefix = 'ns' . rand(1000, 9999); 
  440. $array_typename = "$tt_prefix:$tt"; 
  441. $xmlns .= " xmlns:$tt_prefix=\"$tt_ns\""; 
  442. } else { 
  443. $array_typename = $tt; 
  444. $array_type = $i; 
  445. if ($use == 'literal') { 
  446. $type_str = ''; 
  447. } else if (isset($type) && isset($type_prefix)) { 
  448. $type_str = " xsi:type=\"$type_prefix:$type\""; 
  449. } else { 
  450. $type_str = " xsi:type=\"SOAP-ENC:Array\" SOAP-ENC:arrayType=\"".$array_typename."[$array_type]\""; 
  451. // empty array 
  452. } else { 
  453. if ($use == 'literal') { 
  454. $type_str = ''; 
  455. } else if (isset($type) && isset($type_prefix)) { 
  456. $type_str = " xsi:type=\"$type_prefix:$type\""; 
  457. } else { 
  458. $type_str = " xsi:type=\"SOAP-ENC:Array\" SOAP-ENC:arrayType=\"xsd:anyType[0]\""; 
  459. // TODO: for array in literal, there is no wrapper here 
  460. $xml = "<$name$xmlns$type_str$atts>".$xml."</$name>"; 
  461. } else { 
  462. // got a struct 
  463. $this->debug("serialize_val: serialize struct"); 
  464. if(isset($type) && isset($type_prefix)) { 
  465. $type_str = " xsi:type=\"$type_prefix:$type\""; 
  466. } else { 
  467. $type_str = ''; 
  468. if ($use == 'literal') { 
  469. $xml .= "<$name$xmlns$atts>"; 
  470. } else { 
  471. $xml .= "<$name$xmlns$type_str$atts>"; 
  472. foreach($val as $k => $v) { 
  473. // Apache Map 
  474. if ($type == 'Map' && $type_ns == 'http://xml.apache.org/xml-soap') { 
  475. $xml .= '<item>'; 
  476. $xml .= $this->serialize_val($k, 'key', false, false, false, false, $use); 
  477. $xml .= $this->serialize_val($v, 'value', false, false, false, false, $use); 
  478. $xml .= '</item>'; 
  479. } else { 
  480. $xml .= $this->serialize_val($v, $k, false, false, false, false, $use); 
  481. $xml .= "</$name>"; 
  482. break; 
  483. default: 
  484. $this->debug("serialize_val: serialize unknown"); 
  485. $xml .= 'not detected, got '.gettype($val).' for '.$val; 
  486. break; 
  487. $this->debug("serialize_val returning $xml"); 
  488. return $xml; 
  489.  
  490. /** 
  491. * serializes a message 
  492. * @param string $body the XML of the SOAP body 
  493. * @param mixed $headers optional string of XML with SOAP header content, or array of soapval objects for SOAP headers, or associative array 
  494. * @param array $namespaces optional the namespaces used in generating the body and headers 
  495. * @param string $style optional (rpc|document) 
  496. * @param string $use optional (encoded|literal) 
  497. * @param string $encodingStyle optional (usually 'http://schemas.xmlsoap.org/soap/encoding/' for encoded) 
  498. * @return string the message 
  499. * @access public 
  500. */ 
  501. function serializeEnvelope($body, $headers=false, $namespaces=array(), $style='rpc', $use='encoded', $encodingStyle='http://schemas.xmlsoap.org/soap/encoding/') { 
  502. // TODO: add an option to automatically run utf8_encode on $body and $headers 
  503. // if $this->soap_defencoding is UTF-8. Not doing this automatically allows 
  504. // one to send arbitrary UTF-8 characters, not just characters that map to ISO-8859-1 
  505.  
  506. $this->debug("In serializeEnvelope length=" . strlen($body) . " body (max 1000 characters)=" . substr($body, 0, 1000) . " style=$style use=$use encodingStyle=$encodingStyle"); 
  507. $this->debug("headers:"); 
  508. $this->appendDebug($this->varDump($headers)); 
  509. $this->debug("namespaces:"); 
  510. $this->appendDebug($this->varDump($namespaces)); 
  511.  
  512. // serialize namespaces 
  513. $ns_string = ''; 
  514. foreach(array_merge($this->namespaces, $namespaces) as $k => $v) { 
  515. $ns_string .= " xmlns:$k=\"$v\""; 
  516. if($encodingStyle) { 
  517. $ns_string = " SOAP-ENV:encodingStyle=\"$encodingStyle\"$ns_string"; 
  518.  
  519. // serialize headers 
  520. if($headers) { 
  521. if (is_array($headers)) { 
  522. $xml = ''; 
  523. foreach ($headers as $k => $v) { 
  524. if (is_object($v) && get_class($v) == 'soapval') { 
  525. $xml .= $this->serialize_val($v, false, false, false, false, false, $use); 
  526. } else { 
  527. $xml .= $this->serialize_val($v, $k, false, false, false, false, $use); 
  528. $headers = $xml; 
  529. $this->debug("In serializeEnvelope, serialized array of headers to $headers"); 
  530. $headers = "<SOAP-ENV:Header>".$headers."</SOAP-ENV:Header>"; 
  531. // serialize envelope 
  532. return 
  533. '<?xml version="1.0" encoding="'.$this->soap_defencoding .'"?'.">". 
  534. '<SOAP-ENV:Envelope'.$ns_string.">". 
  535. $headers. 
  536. "<SOAP-ENV:Body>". 
  537. $body. 
  538. "</SOAP-ENV:Body>". 
  539. "</SOAP-ENV:Envelope>"; 
  540.  
  541. /** 
  542. * formats a string to be inserted into an HTML stream 
  543. * @param string $str The string to format 
  544. * @return string The formatted string 
  545. * @access public 
  546. * @deprecated 
  547. */ 
  548. function formatDump($str) { 
  549. $str = htmlspecialchars($str); 
  550. return nl2br($str); 
  551.  
  552. /** 
  553. * contracts (changes namespace to prefix) a qualified name 
  554. * @param string $qname qname 
  555. * @return string contracted qname 
  556. * @access private 
  557. */ 
  558. function contractQname($qname) { 
  559. // get element namespace 
  560. //$this->xdebug("Contract $qname"); 
  561. if (strrpos($qname, ':')) { 
  562. // get unqualified name 
  563. $name = substr($qname, strrpos($qname, ':') + 1); 
  564. // get ns 
  565. $ns = substr($qname, 0, strrpos($qname, ':')); 
  566. $p = $this->getPrefixFromNamespace($ns); 
  567. if ($p) { 
  568. return $p . ':' . $name; 
  569. return $qname; 
  570. } else { 
  571. return $qname; 
  572.  
  573. /** 
  574. * expands (changes prefix to namespace) a qualified name 
  575. * @param string $qname qname 
  576. * @return string expanded qname 
  577. * @access private 
  578. */ 
  579. function expandQname($qname) { 
  580. // get element prefix 
  581. if(strpos($qname, ':') && !preg_match('/^http:\/\//', $qname)) { 
  582. // get unqualified name 
  583. $name = substr(strstr($qname, ':'), 1); 
  584. // get ns prefix 
  585. $prefix = substr($qname, 0, strpos($qname, ':')); 
  586. if(isset($this->namespaces[$prefix])) { 
  587. return $this->namespaces[$prefix].':'.$name; 
  588. } else { 
  589. return $qname; 
  590. } else { 
  591. return $qname; 
  592.  
  593. /** 
  594. * returns the local part of a prefixed string 
  595. * returns the original string, if not prefixed 
  596. * @param string $str The prefixed string 
  597. * @return string The local part 
  598. * @access public 
  599. */ 
  600. function getLocalPart($str) { 
  601. if($sstr = strrchr($str, ':')) { 
  602. // get unqualified name 
  603. return substr( $sstr, 1 ); 
  604. } else { 
  605. return $str; 
  606.  
  607. /** 
  608. * returns the prefix part of a prefixed string 
  609. * returns false, if not prefixed 
  610. * @param string $str The prefixed string 
  611. * @return mixed The prefix or false if there is no prefix 
  612. * @access public 
  613. */ 
  614. function getPrefix($str) { 
  615. if($pos = strrpos($str, ':')) { 
  616. // get prefix 
  617. return substr($str, 0, $pos); 
  618. return false; 
  619.  
  620. /** 
  621. * pass it a prefix, it returns a namespace 
  622. * @param string $prefix The prefix 
  623. * @return mixed The namespace, false if no namespace has the specified prefix 
  624. * @access public 
  625. */ 
  626. function getNamespaceFromPrefix($prefix) { 
  627. if (isset($this->namespaces[$prefix])) { 
  628. return $this->namespaces[$prefix]; 
  629. //$this->setError("No namespace registered for prefix '$prefix'"); 
  630. return false; 
  631.  
  632. /** 
  633. * returns the prefix for a given namespace (or prefix) 
  634. * or false if no prefixes registered for the given namespace 
  635. * @param string $ns The namespace 
  636. * @return mixed The prefix, false if the namespace has no prefixes 
  637. * @access public 
  638. */ 
  639. function getPrefixFromNamespace($ns) { 
  640. foreach ($this->namespaces as $p => $n) { 
  641. if ($ns == $n || $ns == $p) { 
  642. $this->usedNamespaces[$p] = $n; 
  643. return $p; 
  644. return false; 
  645.  
  646. /** 
  647. * returns the time in ODBC canonical form with microseconds 
  648. * @return string The time in ODBC canonical form with microseconds 
  649. * @access public 
  650. */ 
  651. function getmicrotime() { 
  652. if (function_exists('gettimeofday')) { 
  653. $tod = gettimeofday(); 
  654. $sec = $tod['sec']; 
  655. $usec = $tod['usec']; 
  656. } else { 
  657. $sec = time(); 
  658. $usec = 0; 
  659. return strftime('%Y-%m-%d %H:%M:%S', $sec) . '.' . sprintf('%06d', $usec); 
  660.  
  661. /** 
  662. * Returns a string with the output of var_dump 
  663. * @param mixed $data The variable to var_dump 
  664. * @return string The output of var_dump 
  665. * @access public 
  666. */ 
  667. function varDump($data) { 
  668. ob_start(); 
  669. var_dump($data); 
  670. $ret_val = ob_get_contents(); 
  671. ob_end_clean(); 
  672. return $ret_val; 
  673.  
  674. /** 
  675. * represents the object as a string 
  676. * @return string 
  677. * @access public 
  678. */ 
  679. function __toString() { 
  680. return $this->varDump($this);