PageRenderTime 54ms CodeModel.GetById 13ms RepoModel.GetById 0ms app.codeStats 1ms

/plugins/registrar/_directi/nusoap.php

https://github.com/oilcf/agilebill
PHP | 4583 lines | 3068 code | 253 blank | 1262 comment | 836 complexity | 4121174b7e8aae42385323bb87539fe9 MD5 | raw file
Possible License(s): MPL-2.0-no-copyleft-exception, Apache-2.0, LGPL-2.0

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

  1. <?php
  2. /*
  3. $Id: nusoap.php,v 1.1 2004/09/30 09:25:23 Tony 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.soapclient.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.soap_server.php');*/
  37. /**
  38. *
  39. * nusoap_base
  40. *
  41. * @author Dietrich Ayala <dietrich@ganx4.com>
  42. * @version $Id: nusoap.php,v 1.1 2004/09/30 09:25:23 Tony Exp $
  43. * @access public
  44. */
  45. class nusoap_base {
  46. var $title = 'NuSOAP';
  47. var $version = '0.6.6';
  48. var $error_str = false;
  49. var $debug_str = '';
  50. // toggles automatic encoding of special characters as entities
  51. // (should always be true, I think)
  52. var $charencoding = true;
  53. /**
  54. * set schema version
  55. *
  56. * @var XMLSchemaVersion
  57. * @access public
  58. */
  59. var $XMLSchemaVersion = 'http://www.w3.org/2001/XMLSchema';
  60. /**
  61. * set charset encoding for outgoing messages
  62. *
  63. * @var soap_defencoding
  64. * @access public
  65. */
  66. var $soap_defencoding = 'UTF-8';
  67. //var $soap_defencoding = 'ISO-8859-1';
  68. /**
  69. * load namespace uris into an array of uri => prefix
  70. *
  71. * @var namespaces
  72. * @access public
  73. */
  74. var $namespaces = array(
  75. 'SOAP-ENV' => 'http://schemas.xmlsoap.org/soap/envelope/',
  76. 'xsd' => 'http://www.w3.org/2001/XMLSchema',
  77. 'xsi' => 'http://www.w3.org/2001/XMLSchema-instance',
  78. 'SOAP-ENC' => 'http://schemas.xmlsoap.org/soap/encoding/',
  79. 'si' => 'http://soapinterop.org/xsd');
  80. /**
  81. * load types into typemap array
  82. * is this legacy yet?
  83. * no, this is used by the xmlschema class to verify type => namespace mappings.
  84. * @var typemap
  85. * @access public
  86. */
  87. var $typemap = array(
  88. 'http://www.w3.org/2001/XMLSchema' => array(
  89. 'string'=>'string','boolean'=>'boolean','float'=>'double','double'=>'double','decimal'=>'double',
  90. 'duration'=>'','dateTime'=>'string','time'=>'string','date'=>'string','gYearMonth'=>'',
  91. 'gYear'=>'','gMonthDay'=>'','gDay'=>'','gMonth'=>'','hexBinary'=>'string','base64Binary'=>'string',
  92. // derived datatypes
  93. 'normalizedString'=>'string','token'=>'string','language'=>'','NMTOKEN'=>'','NMTOKENS'=>'','Name'=>'','NCName'=>'','ID'=>'',
  94. 'IDREF'=>'','IDREFS'=>'','ENTITY'=>'','ENTITIES'=>'','integer'=>'integer','nonPositiveInteger'=>'integer',
  95. 'negativeInteger'=>'integer','long'=>'integer','int'=>'integer','short'=>'integer','byte'=>'integer','nonNegativeInteger'=>'integer',
  96. 'unsignedLong'=>'','unsignedInt'=>'','unsignedShort'=>'','unsignedByte'=>'','positiveInteger'=>''),
  97. 'http://www.w3.org/1999/XMLSchema' => array(
  98. 'i4'=>'','int'=>'integer','boolean'=>'boolean','string'=>'string','double'=>'double',
  99. 'float'=>'double','dateTime'=>'string',
  100. 'timeInstant'=>'string','base64Binary'=>'string','base64'=>'string','ur-type'=>'array'),
  101. 'http://soapinterop.org/xsd' => array('SOAPStruct'=>'struct'),
  102. 'http://schemas.xmlsoap.org/soap/encoding/' => array('base64'=>'string','array'=>'array','Array'=>'array'),
  103. 'http://xml.apache.org/xml-soap' => array('Map')
  104. );
  105. /**
  106. * entities to convert
  107. *
  108. * @var xmlEntities
  109. * @access public
  110. */
  111. var $xmlEntities = array('quot' => '"','amp' => '&',
  112. 'lt' => '<','gt' => '>','apos' => "'");
  113. /**
  114. * adds debug data to the class level debug string
  115. *
  116. * @param string $string debug data
  117. * @access private
  118. */
  119. function debug($string){
  120. $this->debug_str .= get_class($this).": $string\n";
  121. }
  122. /**
  123. * returns error string if present
  124. *
  125. * @return boolean $string error string
  126. * @access public
  127. */
  128. function getError(){
  129. if($this->error_str != ''){
  130. return $this->error_str;
  131. }
  132. return false;
  133. }
  134. /**
  135. * sets error string
  136. *
  137. * @return boolean $string error string
  138. * @access private
  139. */
  140. function setError($str){
  141. $this->error_str = $str;
  142. }
  143. /**
  144. * serializes PHP values in accordance w/ section 5. Type information is
  145. * not serialized if $use == 'literal'.
  146. *
  147. * @return string
  148. * @access public
  149. */
  150. //$uqType This parameter is added By Manish.
  151. function serialize_val($val,$name=false,$type=false,$name_ns=false,$type_ns=false,$attributes=false,$use='encoded',$uqType=""){
  152. if(is_object($val) && get_class($val) == 'soapval'){
  153. return $val->serialize($use);
  154. }
  155. $this->debug( "in serialize_val: $val, $name, $type, $name_ns, $type_ns, $attributes, $use");
  156. // if no name, use item
  157. $name = (!$name|| is_numeric($name)) ? 'soapVal' : $name;
  158. // if name has ns, add ns prefix to name
  159. $xmlns = '';
  160. if($name_ns){
  161. $prefix = 'nu'.rand(1000,9999);
  162. $name = $prefix.':'.$name;
  163. $xmlns .= " xmlns:$prefix=\"$name_ns\"";
  164. }
  165. // if type is prefixed, create type prefix
  166. if($type_ns != '' && $type_ns == $this->namespaces['xsd']){
  167. // need to fix this. shouldn't default to xsd if no ns specified
  168. // w/o checking against typemap
  169. $type_prefix = 'xsd';
  170. } elseif($type_ns){
  171. $type_prefix = 'ns'.rand(1000,9999);
  172. $xmlns .= " xmlns:$type_prefix=\"$type_ns\"";
  173. }
  174. // serialize attributes if present
  175. $atts = '';
  176. if($attributes){
  177. foreach($attributes as $k => $v){
  178. $atts .= " $k=\"$v\"";
  179. }
  180. }
  181. // serialize if an xsd built-in primitive type
  182. if($type != '' && isset($this->typemap[$this->XMLSchemaVersion][$type])){
  183. if(is_bool($val) && !$val){
  184. $val = 0;
  185. } else if (is_string($val)) {
  186. if($this->charencoding){
  187. $val = str_replace('&', '&amp;', $val);
  188. $val = str_replace("'", '&apos;', $val);
  189. $val = str_replace('"', '&quot;', $val);
  190. $val = str_replace('<', '&lt;', $val);
  191. $val = str_replace('>', '&gt;', $val);
  192. }
  193. }
  194. if ($use == 'literal') {
  195. return "<$name$xmlns>$val</$name>";
  196. } else {
  197. return "<$name$xmlns xsi:type=\"xsd:$type\">$val</$name>";
  198. }
  199. }
  200. // detect type and serialize
  201. $xml = '';
  202. switch(true) {
  203. case ($type == '' && is_null($val)):
  204. if ($use == 'literal') {
  205. // TODO: depends on nillable
  206. $xml .= "<$name$xmlns/>";
  207. } else {
  208. $xml .= "<$name$xmlns xsi:nil=\"true\"/>";
  209. }
  210. break;
  211. case (is_bool($val) || $type == 'boolean'):
  212. if(!$val){
  213. $val = 'false'; // Change By Manish To handle boolean $val = 0;
  214. }
  215. if ($use == 'literal') {
  216. $xml .= "<$name$xmlns $atts>$val</$name>";
  217. } else {
  218. $xml .= "<$name$xmlns xsi:type=\"xsd:boolean\"$atts>$val</$name>";
  219. }
  220. break;
  221. case (is_int($val) || is_long($val) || $type == 'int'):
  222. if ($use == 'literal') {
  223. $xml .= "<$name$xmlns $atts>$val</$name>";
  224. } else {
  225. $xml .= "<$name$xmlns xsi:type=\"xsd:int\"$atts>$val</$name>";
  226. }
  227. break;
  228. case (is_float($val)|| is_double($val) || $type == 'float'):
  229. if ($use == 'literal') {
  230. $xml .= "<$name$xmlns $atts>$val</$name>";
  231. } else {
  232. $xml .= "<$name$xmlns xsi:type=\"xsd:float\"$atts>$val</$name>";
  233. }
  234. break;
  235. case (is_string($val) || $type == 'string'):
  236. if($this->charencoding){
  237. $val = str_replace('&', '&amp;', $val);
  238. $val = str_replace("'", '&apos;', $val);
  239. $val = str_replace('"', '&quot;', $val);
  240. $val = str_replace('<', '&lt;', $val);
  241. $val = str_replace('>', '&gt;', $val);
  242. }
  243. if ($use == 'literal') {
  244. $xml .= "<$name$xmlns $atts>$val</$name>";
  245. } else {
  246. $xml .= "<$name$xmlns xsi:type=\"xsd:string\"$atts>$val</$name>";
  247. }
  248. break;
  249. case is_object($val):
  250. $name = get_class($val);
  251. foreach(get_object_vars($val) as $k => $v){
  252. $pXml = isset($pXml) ? $pXml.$this->serialize_val($v,$k,false,false,false,false,$use) : $this->serialize_val($v,$k,false,false,false,false,$use);
  253. }
  254. $xml .= '<'.$name.'>'.$pXml.'</'.$name.'>';
  255. break;
  256. break;
  257. case (is_array($val) || $type):
  258. //Manish code starts here
  259. if($uqType == "Map" || $uqType == "Vector")
  260. {
  261. if($uqType == "Map")
  262. {
  263. $xml .= "<value$xmlns xsi:type=\"apachesoap:Map\"$atts>";
  264. }
  265. elseif($uqType == "Vector")
  266. {
  267. $xml .= "<item$xmlns xsi:type=\"apachesoap:Map\"$atts>";
  268. }
  269. foreach($val as $k => $v)
  270. {
  271. $xml .= '<item>';
  272. $xml .= $this->serialize_val($k,'key',false,false,false,false,$use);
  273. $xml .= $this->serialize_val($v,'value',false,false,false,false,$use,"Map");
  274. $xml .= '</item>';
  275. }
  276. if($uqType == "Map")
  277. {
  278. $xml .= "</value>";
  279. }
  280. elseif($uqType == "Vector")
  281. {
  282. $xml .= "</item>";
  283. }
  284. break;
  285. }
  286. //Manish code ends here.
  287. // detect if struct or array
  288. $keyList = array_keys($val);
  289. $valueType = 'arraySimple';
  290. foreach($keyList as $keyListValue){
  291. if(!is_int($keyListValue)){
  292. $valueType = 'arrayStruct';
  293. break;
  294. }
  295. }
  296. if($valueType=='arraySimple' || ereg('^ArrayOf',$type)){
  297. $i = 0;
  298. if(is_array($val) && count($val)> 0){
  299. foreach($val as $v){
  300. if(is_object($v) && get_class($v) == 'soapval'){
  301. $tt_ns = $v->type_ns;
  302. $tt = $v->type;
  303. } else {
  304. $tt = gettype($v);
  305. }
  306. $array_types[$tt] = 1;
  307. $xml .= $this->serialize_val($v,'item',false,false,false,false,$use);
  308. ++$i;
  309. }
  310. if(count($array_types) > 1){
  311. $array_typename = 'xsd:ur-type';
  312. } elseif(isset($tt) && isset($this->typemap[$this->XMLSchemaVersion][$tt])) {
  313. $array_typename = 'xsd:'.$tt;
  314. } elseif($tt == 'array' || $tt == 'Array'){
  315. $array_typename = 'SOAP-ENC:Array';
  316. } else {
  317. // if type is prefixed, create type prefix
  318. if ($tt_ns != '' && $tt_ns == $this->namespaces['xsd']){
  319. $array_typename = 'xsd:' . $tt;
  320. } elseif ($tt_ns) {
  321. $tt_prefix = 'ns' . rand(1000, 9999);
  322. $array_typename = "$tt_prefix:$tt";
  323. $xmlns .= " xmlns:$tt_prefix=\"$tt_ns\"";
  324. } else {
  325. $array_typename = $tt;
  326. }
  327. }
  328. $array_type = $i;
  329. if ($use == 'literal') {
  330. $type_str = '';
  331. } else if (isset($type) && isset($type_prefix)) {
  332. $type_str = " xsi:type=\"$type_prefix:$type\"";
  333. } else {
  334. $type_str = " xsi:type=\"SOAP-ENC:Array\" SOAP-ENC:arrayType=\"".$array_typename."[$array_type]\"";
  335. }
  336. // empty array
  337. } else {
  338. if ($use == 'literal') {
  339. $type_str = '';
  340. } else if (isset($type) && isset($type_prefix)) {
  341. $type_str = " xsi:type=\"$type_prefix:$type\"";
  342. } else {
  343. $type_str = " xsi:type=\"SOAP-ENC:Array\"";
  344. }
  345. }
  346. $xml = "<$name$xmlns$type_str$atts>".$xml."</$name>";
  347. } else {
  348. // got a struct
  349. if(isset($type) && isset($type_prefix)){
  350. $type_str = " xsi:type=\"$type_prefix:$type\"";
  351. } else {
  352. $type_str = '';
  353. }
  354. if ($use == 'literal') {
  355. $xml .= "<$name$xmlns $atts>";
  356. } else {
  357. $xml .= "<$name$xmlns$type_str$atts>";
  358. }
  359. foreach($val as $k => $v){
  360. // Apache Map
  361. if ($type == 'Map' && $type_ns == 'http://xml.apache.org/xml-soap') {
  362. $xml .= '<item>';
  363. $xml .= $this->serialize_val($k,'key',false,false,false,false,$use);
  364. $xml .= $this->serialize_val($v,'value',false,false,false,false,$use);
  365. $xml .= '</item>';
  366. } else {
  367. $xml .= $this->serialize_val($v,$k,false,false,false,false,$use);
  368. }
  369. }
  370. $xml .= "</$name>";
  371. }
  372. break;
  373. default:
  374. $xml .= 'not detected, got '.gettype($val).' for '.$val;
  375. break;
  376. }
  377. return $xml;
  378. }
  379. /**
  380. * serialize message
  381. *
  382. * @param string body
  383. * @param string headers
  384. * @param array namespaces
  385. * @param string style
  386. * @return string message
  387. * @access public
  388. */
  389. function serializeEnvelope($body,$headers=false,$namespaces=array(),$style='rpc'){
  390. // TODO: add an option to automatically run utf8_encode on $body and $headers
  391. // if $this->soap_defencoding is UTF-8. Not doing this automatically allows
  392. // one to send arbitrary UTF-8 characters, not just characters that map to ISO-8859-1
  393. // serialize namespaces
  394. $ns_string = '';
  395. foreach(array_merge($this->namespaces,$namespaces) as $k => $v){
  396. $ns_string .= " xmlns:$k=\"$v\"";
  397. }
  398. if($style == 'rpc') {
  399. $ns_string = ' SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"' . $ns_string;
  400. }
  401. // serialize headers
  402. if($headers){
  403. $headers = "<SOAP-ENV:Header>".$headers."</SOAP-ENV:Header>";
  404. }
  405. // serialize envelope
  406. return
  407. '<?xml version="1.0" encoding="'.$this->soap_defencoding .'"?'.">".
  408. '<SOAP-ENV:Envelope'.$ns_string.">".
  409. $headers.
  410. "<SOAP-ENV:Body>".
  411. $body.
  412. "</SOAP-ENV:Body>".
  413. "</SOAP-ENV:Envelope>";
  414. }
  415. function formatDump($str){
  416. $str = htmlspecialchars($str);
  417. return nl2br($str);
  418. }
  419. /**
  420. * returns the local part of a prefixed string
  421. * returns the original string, if not prefixed
  422. *
  423. * @param string
  424. * @return string
  425. * @access public
  426. */
  427. function getLocalPart($str){
  428. if($sstr = strrchr($str,':')){
  429. // get unqualified name
  430. return substr( $sstr, 1 );
  431. } else {
  432. return $str;
  433. }
  434. }
  435. /**
  436. * returns the prefix part of a prefixed string
  437. * returns false, if not prefixed
  438. *
  439. * @param string
  440. * @return mixed
  441. * @access public
  442. */
  443. function getPrefix($str){
  444. if($pos = strrpos($str,':')){
  445. // get prefix
  446. return substr($str,0,$pos);
  447. }
  448. return false;
  449. }
  450. function varDump($data) {
  451. ob_start();
  452. var_dump($data);
  453. $ret_val = ob_get_contents();
  454. ob_end_clean();
  455. return $ret_val;
  456. }
  457. }
  458. // XML Schema Datatype Helper Functions
  459. //xsd:dateTime helpers
  460. /**
  461. * convert unix timestamp to ISO 8601 compliant date string
  462. *
  463. * @param string $timestamp Unix time stamp
  464. * @access public
  465. */
  466. function timestamp_to_iso8601($timestamp,$utc=true){
  467. $datestr = date('Y-m-d\TH:i:sO',$timestamp);
  468. if($utc){
  469. $eregStr =
  470. '([0-9]{4})-'. // centuries & years CCYY-
  471. '([0-9]{2})-'. // months MM-
  472. '([0-9]{2})'. // days DD
  473. 'T'. // separator T
  474. '([0-9]{2}):'. // hours hh:
  475. '([0-9]{2}):'. // minutes mm:
  476. '([0-9]{2})(\.[0-9]*)?'. // seconds ss.ss...
  477. '(Z|[+\-][0-9]{2}:?[0-9]{2})?'; // Z to indicate UTC, -/+HH:MM:SS.SS... for local tz's
  478. if(ereg($eregStr,$datestr,$regs)){
  479. return sprintf('%04d-%02d-%02dT%02d:%02d:%02dZ',$regs[1],$regs[2],$regs[3],$regs[4],$regs[5],$regs[6]);
  480. }
  481. return false;
  482. } else {
  483. return $datestr;
  484. }
  485. }
  486. /**
  487. * convert ISO 8601 compliant date string to unix timestamp
  488. *
  489. * @param string $datestr ISO 8601 compliant date string
  490. * @access public
  491. */
  492. function iso8601_to_timestamp($datestr){
  493. $eregStr =
  494. '([0-9]{4})-'. // centuries & years CCYY-
  495. '([0-9]{2})-'. // months MM-
  496. '([0-9]{2})'. // days DD
  497. 'T'. // separator T
  498. '([0-9]{2}):'. // hours hh:
  499. '([0-9]{2}):'. // minutes mm:
  500. '([0-9]{2})(\.[0-9]+)?'. // seconds ss.ss...
  501. '(Z|[+\-][0-9]{2}:?[0-9]{2})?'; // Z to indicate UTC, -/+HH:MM:SS.SS... for local tz's
  502. if(ereg($eregStr,$datestr,$regs)){
  503. // not utc
  504. if($regs[8] != 'Z'){
  505. $op = substr($regs[8],0,1);
  506. $h = substr($regs[8],1,2);
  507. $m = substr($regs[8],strlen($regs[8])-2,2);
  508. if($op == '-'){
  509. $regs[4] = $regs[4] + $h;
  510. $regs[5] = $regs[5] + $m;
  511. } elseif($op == '+'){
  512. $regs[4] = $regs[4] - $h;
  513. $regs[5] = $regs[5] - $m;
  514. }
  515. }
  516. return strtotime("$regs[1]-$regs[2]-$regs[3] $regs[4]:$regs[5]:$regs[6]Z");
  517. } else {
  518. return false;
  519. }
  520. }
  521. function usleepWindows($usec)
  522. {
  523. $start = gettimeofday();
  524. do
  525. {
  526. $stop = gettimeofday();
  527. $timePassed = 1000000 * ($stop['sec'] - $start['sec'])
  528. + $stop['usec'] - $start['usec'];
  529. }
  530. while ($timePassed < $usec);
  531. }
  532. ?><?php
  533. /**
  534. * soap_fault class, allows for creation of faults
  535. * mainly used for returning faults from deployed functions
  536. * in a server instance.
  537. * @author Dietrich Ayala <dietrich@ganx4.com>
  538. * @version $Id: nusoap.php,v 1.1 2004/09/30 09:25:23 Tony Exp $
  539. * @access public
  540. */
  541. class soap_fault extends nusoap_base {
  542. var $faultcode;
  543. var $faultactor;
  544. var $faultstring;
  545. var $faultdetail;
  546. /**
  547. * constructor
  548. *
  549. * @param string $faultcode (client | server)
  550. * @param string $faultactor only used when msg routed between multiple actors
  551. * @param string $faultstring human readable error message
  552. * @param string $faultdetail
  553. */
  554. function soap_fault($faultcode,$faultactor='',$faultstring='',$faultdetail=''){
  555. $this->faultcode = $faultcode;
  556. $this->faultactor = $faultactor;
  557. $this->faultstring = $faultstring;
  558. $this->faultdetail = $faultdetail;
  559. }
  560. /**
  561. * serialize a fault
  562. *
  563. * @access public
  564. */
  565. function serialize(){
  566. $ns_string = '';
  567. foreach($this->namespaces as $k => $v){
  568. $ns_string .= "\n xmlns:$k=\"$v\"";
  569. }
  570. $return_msg =
  571. '<?xml version="1.0" encoding="'.$this->soap_defencoding.'"?>'.
  572. '<SOAP-ENV:Envelope SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"'.$ns_string.">\n".
  573. '<SOAP-ENV:Body>'.
  574. '<SOAP-ENV:Fault>'.
  575. '<faultcode>'.$this->faultcode.'</faultcode>'.
  576. '<faultactor>'.$this->faultactor.'</faultactor>'.
  577. '<faultstring>'.$this->faultstring.'</faultstring>'.
  578. '<detail>'.$this->serialize_val($this->faultdetail).'</detail>'.
  579. '</SOAP-ENV:Fault>'.
  580. '</SOAP-ENV:Body>'.
  581. '</SOAP-ENV:Envelope>';
  582. return $return_msg;
  583. }
  584. }
  585. ?><?php
  586. /**
  587. * parses an XML Schema, allows access to it's data, other utility methods
  588. * no validation... yet.
  589. * very experimental and limited. As is discussed on XML-DEV, I'm one of the people
  590. * that just doesn't have time to read the spec(s) thoroughly, and just have a couple of trusty
  591. * tutorials I refer to :)
  592. *
  593. * @author Dietrich Ayala <dietrich@ganx4.com>
  594. * @version $Id: nusoap.php,v 1.1 2004/09/30 09:25:23 Tony Exp $
  595. * @access public
  596. */
  597. class XMLSchema extends nusoap_base {
  598. // files
  599. var $schema = '';
  600. var $xml = '';
  601. // define internal arrays of bindings, ports, operations, messages, etc.
  602. var $complexTypes = array();
  603. // target namespace
  604. var $schemaTargetNamespace = '';
  605. // parser vars
  606. var $parser;
  607. var $position;
  608. var $depth = 0;
  609. var $depth_array = array();
  610. /**
  611. * constructor
  612. *
  613. * @param string $schema schema document URI
  614. * @param string $xml xml document URI
  615. * @access public
  616. */
  617. function XMLSchema($schema='',$xml=''){
  618. $this->debug('xmlschema class instantiated, inside constructor');
  619. // files
  620. $this->schema = $schema;
  621. $this->xml = $xml;
  622. // parse schema file
  623. if($schema != ''){
  624. $this->debug('initial schema file: '.$schema);
  625. $this->parseFile($schema);
  626. }
  627. // parse xml file
  628. if($xml != ''){
  629. $this->debug('initial xml file: '.$xml);
  630. $this->parseFile($xml);
  631. }
  632. }
  633. /**
  634. * parse an XML file
  635. *
  636. * @param string $xml, path/URL to XML file
  637. * @param string $type, (schema | xml)
  638. * @return boolean
  639. * @access public
  640. */
  641. function parseFile($xml,$type){
  642. // parse xml file
  643. if($xml != ""){
  644. $this->debug('parsing $xml');
  645. $xmlStr = @join("",@file($xml));
  646. if($xmlStr == ""){
  647. $this->setError('No file at the specified URL: '.$xml);
  648. return false;
  649. } else {
  650. $this->parseString($xmlStr,$type);
  651. return true;
  652. }
  653. }
  654. return false;
  655. }
  656. /**
  657. * parse an XML string
  658. *
  659. * @param string $xml path or URL
  660. * @param string $type, (schema|xml)
  661. * @access private
  662. */
  663. function parseString($xml,$type){
  664. // parse xml string
  665. if($xml != ""){
  666. // Create an XML parser.
  667. $this->parser = xml_parser_create();
  668. // Set the options for parsing the XML data.
  669. xml_parser_set_option($this->parser, XML_OPTION_CASE_FOLDING, 0);
  670. // Set the object for the parser.
  671. xml_set_object($this->parser, $this);
  672. // Set the element handlers for the parser.
  673. if($type == "schema"){
  674. xml_set_element_handler($this->parser, 'schemaStartElement','schemaEndElement');
  675. xml_set_character_data_handler($this->parser,'schemaCharacterData');
  676. } elseif($type == "xml"){
  677. xml_set_element_handler($this->parser, 'xmlStartElement','xmlEndElement');
  678. xml_set_character_data_handler($this->parser,'xmlCharacterData');
  679. }
  680. // Parse the XML file.
  681. if(!xml_parse($this->parser,$xml,true)){
  682. // Display an error message.
  683. $errstr = sprintf('XML error on line %d: %s',
  684. xml_get_current_line_number($this->parser),
  685. xml_error_string(xml_get_error_code($this->parser))
  686. );
  687. $this->debug('XML parse error: '.$errstr);
  688. $this->setError('Parser error: '.$errstr);
  689. }
  690. xml_parser_free($this->parser);
  691. } else{
  692. $this->debug('no xml passed to parseString()!!');
  693. $this->setError('no xml passed to parseString()!!');
  694. }
  695. }
  696. /**
  697. * start-element handler
  698. *
  699. * @param string $parser XML parser object
  700. * @param string $name element name
  701. * @param string $attrs associative array of attributes
  702. * @access private
  703. */
  704. function schemaStartElement($parser, $name, $attrs) {
  705. // position in the total number of elements, starting from 0
  706. $pos = $this->position++;
  707. $depth = $this->depth++;
  708. // set self as current value for this depth
  709. $this->depth_array[$depth] = $pos;
  710. // get element prefix
  711. if($prefix = $this->getPrefix($name)){
  712. // get unqualified name
  713. $name = $this->getLocalPart($name);
  714. } else {
  715. $prefix = '';
  716. }
  717. // loop thru attributes, expanding, and registering namespace declarations
  718. if(count($attrs) > 0){
  719. foreach($attrs as $k => $v){
  720. // if ns declarations, add to class level array of valid namespaces
  721. if(ereg("^xmlns",$k)){
  722. //$this->xdebug("$k: $v");
  723. //$this->xdebug('ns_prefix: '.$this->getPrefix($k));
  724. if($ns_prefix = substr(strrchr($k,':'),1)){
  725. $this->namespaces[$ns_prefix] = $v;
  726. } else {
  727. $this->namespaces['ns'.(count($this->namespaces)+1)] = $v;
  728. }
  729. if($v == 'http://www.w3.org/2001/XMLSchema' || $v == 'http://www.w3.org/1999/XMLSchema'){
  730. $this->XMLSchemaVersion = $v;
  731. $this->namespaces['xsi'] = $v.'-instance';
  732. }
  733. }
  734. }
  735. foreach($attrs as $k => $v){
  736. // expand each attribute
  737. $k = strpos($k,':') ? $this->expandQname($k) : $k;
  738. $v = strpos($v,':') ? $this->expandQname($v) : $v;
  739. $eAttrs[$k] = $v;
  740. }
  741. $attrs = $eAttrs;
  742. } else {
  743. $attrs = array();
  744. }
  745. // find status, register data
  746. switch($name){
  747. case ('all'|'choice'|'sequence'):
  748. //$this->complexTypes[$this->currentComplexType]['compositor'] = 'all';
  749. $this->complexTypes[$this->currentComplexType]['compositor'] = $name;
  750. if($name == 'all'){
  751. $this->complexTypes[$this->currentComplexType]['phpType'] = 'struct';
  752. }
  753. break;
  754. case 'attribute':
  755. //$this->xdebug("parsing attribute $attrs[name] $attrs[ref] of value: ".$attrs['http://schemas.xmlsoap.org/wsdl/:arrayType']);
  756. if(isset($attrs['name'])){
  757. $this->attributes[$attrs['name']] = $attrs;
  758. $aname = $attrs['name'];
  759. } elseif(isset($attrs['ref']) && $attrs['ref'] == 'http://schemas.xmlsoap.org/soap/encoding/:arrayType'){
  760. $aname = $attrs['http://schemas.xmlsoap.org/wsdl/:arrayType'];
  761. } elseif(isset($attrs['ref'])){
  762. $aname = $attrs['ref'];
  763. $this->attributes[$attrs['ref']] = $attrs;
  764. }
  765. if(isset($this->currentComplexType)){
  766. $this->complexTypes[$this->currentComplexType]['attrs'][$aname] = $attrs;
  767. } elseif(isset($this->currentElement)){
  768. $this->elements[$this->currentElement]['attrs'][$aname] = $attrs;
  769. }
  770. // arrayType attribute
  771. if(isset($attrs['http://schemas.xmlsoap.org/wsdl/:arrayType']) || $this->getLocalPart($aname) == 'arrayType'){
  772. $this->complexTypes[$this->currentComplexType]['phpType'] = 'array';
  773. $prefix = $this->getPrefix($aname);
  774. if(isset($attrs['http://schemas.xmlsoap.org/wsdl/:arrayType'])){
  775. $v = $attrs['http://schemas.xmlsoap.org/wsdl/:arrayType'];
  776. } else {
  777. $v = '';
  778. }
  779. if(strpos($v,'[,]')){
  780. $this->complexTypes[$this->currentComplexType]['multidimensional'] = true;
  781. }
  782. $v = substr($v,0,strpos($v,'[')); // clip the []
  783. if(!strpos($v,':') && isset($this->typemap[$this->XMLSchemaVersion][$v])){
  784. $v = $this->XMLSchemaVersion.':'.$v;
  785. }
  786. $this->complexTypes[$this->currentComplexType]['arrayType'] = $v;
  787. }
  788. break;
  789. case 'complexType':
  790. if(isset($attrs['name'])){
  791. $this->currentElement = false;
  792. $this->currentComplexType = $attrs['name'];
  793. $this->complexTypes[$this->currentComplexType] = $attrs;
  794. $this->complexTypes[$this->currentComplexType]['typeClass'] = 'complexType';
  795. if(isset($attrs['base']) && ereg(':Array$',$attrs['base'])){
  796. $this->complexTypes[$this->currentComplexType]['phpType'] = 'array';
  797. } else {
  798. $this->complexTypes[$this->currentComplexType]['phpType'] = 'struct';
  799. }
  800. $this->xdebug('processing complexType '.$attrs['name']);
  801. }
  802. break;
  803. case 'element':
  804. if(isset($attrs['type'])){
  805. $this->xdebug("processing element ".$attrs['name']);
  806. $this->currentElement = $attrs['name'];
  807. $this->elements[ $attrs['name'] ] = $attrs;
  808. $this->elements[ $attrs['name'] ]['typeClass'] = 'element';
  809. $ename = $attrs['name'];
  810. } elseif(isset($attrs['ref'])){
  811. $ename = $attrs['ref'];
  812. } else {
  813. $this->xdebug('adding complexType '.$attrs['name']);
  814. $this->currentComplexType = $attrs['name'];
  815. $this->complexTypes[ $attrs['name'] ] = $attrs;
  816. $this->complexTypes[ $attrs['name'] ]['element'] = 1;
  817. $this->complexTypes[$this->currentComplexType]['phpType'] = 'struct';
  818. }
  819. if(isset($ename) && $this->currentComplexType){
  820. $this->complexTypes[$this->currentComplexType]['elements'][$ename] = $attrs;
  821. }
  822. break;
  823. case 'restriction':
  824. $this->xdebug("in restriction for ct: $this->currentComplexType and ce: $this->currentElement");
  825. if($this->currentElement){
  826. $this->elements[$this->currentElement]['type'] = $attrs['base'];
  827. } elseif($this->currentComplexType){
  828. $this->complexTypes[$this->currentComplexType]['restrictionBase'] = $attrs['base'];
  829. if(strstr($attrs['base'],':') == ':Array'){
  830. $this->complexTypes[$this->currentComplexType]['phpType'] = 'array';
  831. }
  832. }
  833. break;
  834. case 'schema':
  835. $this->schema = $attrs;
  836. $this->schema['schemaVersion'] = $this->getNamespaceFromPrefix($prefix);
  837. break;
  838. case 'simpleType':
  839. if(isset($attrs['name'])){
  840. $this->currentElement = $attrs['name'];
  841. $this->elements[ $attrs['name'] ] = $attrs;
  842. $this->elements[ $attrs['name'] ]['typeClass'] = 'element';
  843. } else {
  844. //echo 'not parsing: '.$name;
  845. //var_dump($attrs);
  846. }
  847. break;
  848. }
  849. }
  850. /**
  851. * end-element handler
  852. *
  853. * @param string $parser XML parser object
  854. * @param string $name element name
  855. * @access private
  856. */
  857. function schemaEndElement($parser, $name) {
  858. // position of current element is equal to the last value left in depth_array for my depth
  859. if(isset($this->depth_array[$this->depth])){
  860. $pos = $this->depth_array[$this->depth];
  861. }
  862. // bring depth down a notch
  863. $this->depth--;
  864. // move on...
  865. if($name == 'complexType'){
  866. $this->currentComplexType = false;
  867. $this->currentElement = false;
  868. }
  869. if($name == 'element'){
  870. $this->currentElement = false;
  871. }
  872. }
  873. /**
  874. * element content handler
  875. *
  876. * @param string $parser XML parser object
  877. * @param string $data element content
  878. * @access private
  879. */
  880. function schemaCharacterData($parser, $data){
  881. $pos = $this->depth_array[$this->depth];
  882. $this->message[$pos]['cdata'] .= $data;
  883. }
  884. /**
  885. * serialize the schema
  886. *
  887. * @access public
  888. */
  889. function serializeSchema(){
  890. $schemaPrefix = $this->getPrefixFromNamespace($this->XMLSchemaVersion);
  891. $xml = '';
  892. // complex types
  893. foreach($this->complexTypes as $typeName => $attrs){
  894. $contentStr = '';
  895. // serialize child elements
  896. if(count($attrs['elements']) > 0){
  897. foreach($attrs['elements'] as $element => $eParts){
  898. if(isset($eParts['ref'])){
  899. $contentStr .= "<$schemaPrefix:element ref=\"$element\"/>";
  900. } else {
  901. $contentStr .= "<$schemaPrefix:element name=\"$element\" type=\"$eParts[type]\"/>";
  902. }
  903. }
  904. }
  905. // attributes
  906. if(count($attrs['attrs']) >= 1){
  907. foreach($attrs['attrs'] as $attr => $aParts){
  908. $contentStr .= "<$schemaPrefix:attribute ref=\"".$aParts['ref'].'"';
  909. if(isset($aParts['wsdl:arrayType'])){
  910. $contentStr .= ' wsdl:arrayType="'.$aParts['wsdl:arrayType'].'"';
  911. }
  912. $contentStr .= '/>';
  913. }
  914. }
  915. // if restriction
  916. if( isset($attrs['restrictionBase']) && $attrs['restrictionBase'] != ''){
  917. $contentStr = "<$schemaPrefix:restriction base=\"".$attrs['restrictionBase']."\">".$contentStr."</$schemaPrefix:restriction>";
  918. }
  919. // "all" compositor obviates complex/simple content
  920. if(isset($attrs['compositor']) && $attrs['compositor'] == 'all'){
  921. $contentStr = "<$schemaPrefix:$attrs[compositor]>".$contentStr."</$schemaPrefix:$attrs[compositor]>";
  922. }
  923. // complex or simple content
  924. elseif( count($attrs['elements']) > 0 || count($attrs['attrs']) > 0){
  925. $contentStr = "<$schemaPrefix:complexContent>".$contentStr."</$schemaPrefix:complexContent>";
  926. }
  927. // compositors
  928. if(isset($attrs['compositor']) && $attrs['compositor'] != '' && $attrs['compositor'] != 'all'){
  929. $contentStr = "<$schemaPrefix:$attrs[compositor]>".$contentStr."</$schemaPrefix:$attrs[compositor]>";
  930. }
  931. // finalize complex type
  932. if($contentStr != ''){
  933. $contentStr = "<$schemaPrefix:complexType name=\"$typeName\">".$contentStr."</$schemaPrefix:complexType>";
  934. } else {
  935. $contentStr = "<$schemaPrefix:complexType name=\"$typeName\"/>";
  936. }
  937. $xml .= $contentStr;
  938. }
  939. // elements
  940. if(isset($this->elements) && count($this->elements) > 0){
  941. foreach($this->elements as $element => $eParts){
  942. $xml .= "<$schemaPrefix:element name=\"$element\" type=\"".$eParts['type']."\"/>";
  943. }
  944. }
  945. // attributes
  946. if(isset($this->attributes) && count($this->attributes) > 0){
  947. foreach($this->attributes as $attr => $aParts){
  948. $xml .= "<$schemaPrefix:attribute name=\"$attr\" type=\"".$aParts['type']."\"/>";
  949. }
  950. }
  951. // finish 'er up
  952. $xml = "<$schemaPrefix:schema targetNamespace=\"$this->schemaTargetNamespace\"><$schemaPrefix:import namespace=\"http://schemas.xmlsoap.org/soap/encoding/\" /><$schemaPrefix:import namespace=\"http://schemas.xmlsoap.org/wsdl/\" />".$xml."</$schemaPrefix:schema>";
  953. return $xml;
  954. }
  955. /**
  956. * expands a qualified name
  957. *
  958. * @param string $string qname
  959. * @return string expanded qname
  960. * @access private
  961. */
  962. function expandQname($qname){
  963. // get element prefix
  964. if(strpos($qname,':') && !ereg('^http://',$qname)){
  965. // get unqualified name
  966. $name = substr(strstr($qname,':'),1);
  967. // get ns prefix
  968. $prefix = substr($qname,0,strpos($qname,':'));
  969. if(isset($this->namespaces[$prefix])){
  970. return $this->namespaces[$prefix].':'.$name;
  971. } else {
  972. return $qname;
  973. }
  974. } else {
  975. return $qname;
  976. }
  977. }
  978. /**
  979. * adds debug data to the clas level debug string
  980. *
  981. * @param string $string debug data
  982. * @access private
  983. */
  984. function xdebug($string){
  985. $this->debug(' xmlschema: '.$string);
  986. }
  987. /**
  988. * get the PHP type of a user defined type in the schema
  989. * PHP type is kind of a misnomer since it actually returns 'struct' for assoc. arrays
  990. * returns false if no type exists, or not w/ the given namespace
  991. * else returns a string that is either a native php type, or 'struct'
  992. *
  993. * @param string $type, name of defined type
  994. * @param string $ns, namespace of type
  995. * @return mixed
  996. * @access public
  997. */
  998. function getPHPType($type,$ns){
  999. if(isset($this->typemap[$ns][$type])){
  1000. //print "found type '$type' and ns $ns in typemap<br>";
  1001. return $this->typemap[$ns][$type];
  1002. } elseif(isset($this->complexTypes[$type])){
  1003. //print "getting type '$type' and ns $ns from complexTypes array<br>";
  1004. return $this->complexTypes[$type]['phpType'];
  1005. }
  1006. return false;
  1007. }
  1008. /**
  1009. * returns the local part of a prefixed string
  1010. * returns the original string, if not prefixed
  1011. *
  1012. * @param string
  1013. * @return string
  1014. * @access public
  1015. */
  1016. function getLocalPart($str){
  1017. if($sstr = strrchr($str,':')){
  1018. // get unqualified name
  1019. return substr( $sstr, 1 );
  1020. } else {
  1021. return $str;
  1022. }
  1023. }
  1024. /**
  1025. * returns the prefix part of a prefixed string
  1026. * returns false, if not prefixed
  1027. *
  1028. * @param string
  1029. * @return mixed
  1030. * @access public
  1031. */
  1032. function getPrefix($str){
  1033. if($pos = strrpos($str,':')){
  1034. // get prefix
  1035. return substr($str,0,$pos);
  1036. }
  1037. return false;
  1038. }
  1039. /**
  1040. * pass it a prefix, it returns a namespace
  1041. * returns false if no namespace registered with the given prefix
  1042. *
  1043. * @param string
  1044. * @return mixed
  1045. * @access public
  1046. */
  1047. function getNamespaceFromPrefix($prefix){
  1048. if(isset($this->namespaces[$prefix])){
  1049. return $this->namespaces[$prefix];
  1050. }
  1051. //$this->setError("No namespace registered for prefix '$prefix'");
  1052. return false;
  1053. }
  1054. /**
  1055. * returns the prefix for a given namespace (or prefix)
  1056. * or false if no prefixes registered for the given namespace
  1057. *
  1058. * @param string
  1059. * @return mixed
  1060. * @access public
  1061. */
  1062. function getPrefixFromNamespace($ns){
  1063. foreach($this->namespaces as $p => $n){
  1064. if($ns == $n || $ns == $p){
  1065. $this->usedNamespaces[$p] = $n;
  1066. return $p;
  1067. }
  1068. }
  1069. return false;
  1070. }
  1071. /**
  1072. * returns an array of information about a given type
  1073. * returns false if no type exists by the given name
  1074. *
  1075. * typeDef = array(
  1076. * 'elements' => array(), // refs to elements array
  1077. * 'restrictionBase' => '',
  1078. * 'phpType' => '',
  1079. * 'order' => '(sequence|all)',
  1080. * 'attrs' => array() // refs to attributes array
  1081. * )
  1082. *
  1083. * @param string
  1084. * @return mixed
  1085. * @access public
  1086. */
  1087. function getTypeDef($type){
  1088. if(isset($this->complexTypes[$type])){
  1089. return $this->complexTypes[$type];
  1090. } elseif(isset($this->elements[$type])){
  1091. return $this->elements[$type];
  1092. } elseif(isset($this->attributes[$type])){
  1093. return $this->attributes[$type];
  1094. }
  1095. return false;
  1096. }
  1097. /**
  1098. * returns a sample serialization of a given type, or false if no type by the given name
  1099. *
  1100. * @param string $type, name of type
  1101. * @return mixed
  1102. * @access public
  1103. */
  1104. function serializeTypeDef($type){
  1105. //print "in sTD() for type $type<br>";
  1106. if($typeDef = $this->getTypeDef($type)){
  1107. $str .= '<'.$type;
  1108. if(is_array($typeDef['attrs'])){
  1109. foreach($attrs as $attName => $data){
  1110. $str .= " $attName=\"{type = ".$data['type']."}\"";
  1111. }
  1112. }
  1113. $str .= " xmlns=\"".$this->schema['targetNamespace']."\"";
  1114. if(count($typeDef['elements']) > 0){
  1115. $str .= ">";
  1116. foreach($typeDef['elements'] as $element => $eData){
  1117. $str .= $this->serializeTypeDef($element);
  1118. }
  1119. $str .= "</$type>";
  1120. } elseif($typeDef['typeClass'] == 'element') {
  1121. $str .= "></$type>";
  1122. } else {
  1123. $str .= "/>";
  1124. }
  1125. return $str;
  1126. }
  1127. return false;
  1128. }
  1129. /**
  1130. * returns HTML form elements that allow a user
  1131. * to enter values for creating an instance of the given type.
  1132. *
  1133. * @param string $name, name for type instance
  1134. * @param string $type, name of type
  1135. * @return string
  1136. * @access public
  1137. */
  1138. function typeToForm($name,$type){
  1139. // get typedef
  1140. if($typeDef = $this->getTypeDef($type)){
  1141. // if struct
  1142. if($typeDef['phpType'] == 'struct'){
  1143. $buffer .= '<table>';
  1144. foreach($typeDef['elements'] as $child => $childDef){
  1145. $buffer .= "
  1146. <tr><td align='right'>$childDef[name] (type: ".$this->getLocalPart($childDef['type'])."):</td>
  1147. <td><input type='text' name='parameters[".$name."][$childDef[name]]'></td></tr>";
  1148. }
  1149. $buffer .= '</table>';
  1150. // if array
  1151. } elseif($typeDef['phpType'] == 'array'){
  1152. $buffer .= '<table>';
  1153. for($i=0;$i < 3; $i++){
  1154. $buffer .= "
  1155. <tr><td align='right'>array item (type: $typeDef[arrayType]):</td>
  1156. <td><input type='text' name='parameters[".$name."][]'></td></tr>";
  1157. }
  1158. $buffer .= '</table>';
  1159. // if scalar
  1160. } else {
  1161. $buffer .= "<input type='text' name='parameters[$name]'>";
  1162. }
  1163. } else {
  1164. $buffer .= "<input type='text' name='parameters[$name]'>";
  1165. }
  1166. return $buffer;
  1167. }
  1168. /**
  1169. * adds an XML Schema complex type to the WSDL types
  1170. *
  1171. * example: array
  1172. *
  1173. * addType(
  1174. * 'ArrayOfstring',
  1175. * 'complexType',
  1176. * 'array',
  1177. * '',
  1178. * 'SOAP-ENC:Array',
  1179. * array('ref'=>'SOAP-ENC:arrayType','wsdl:arrayType'=>'string[]'),
  1180. * 'xsd:string'
  1181. * );
  1182. *
  1183. * example: PHP associative array ( SOAP Struct )
  1184. *
  1185. * addType(
  1186. * 'SOAPStruct',
  1187. * 'complexType',
  1188. * 'struct',
  1189. * 'all',
  1190. * array('myVar'=> array('name'=>'myVar','type'=>'string')
  1191. * );
  1192. *
  1193. * @param name
  1194. * @param typeClass (complexType|simpleType|attribute)
  1195. * @param phpType: currently supported are array and struct (php assoc array)
  1196. * @param compositor (all|sequence|choice)
  1197. * @param restrictionBase namespace:name (http://schemas.xmlsoap.org/soap/encoding/:Array)
  1198. * @param elements = array ( name = array(name=>'',type=>'') )
  1199. * @param attrs = array(
  1200. * array(
  1201. * 'ref' => "http://schemas.xmlsoap.org/soap/encoding/:arrayType",
  1202. * "http://schemas.xmlsoap.org/wsdl/:arrayType" => "string[]"
  1203. * )
  1204. * )
  1205. * @param arrayType: namespace:name (http://www.w3.org/2001/XMLSchema:string)
  1206. *
  1207. */
  1208. function addComplexType($name,$typeClass='complexType',$phpType='array',$compositor='',$restrictionBase='',$elements=array(),$attrs=array(),$arrayType=''){
  1209. $this->complexTypes[$name] = array(
  1210. 'name' => $name,
  1211. 'typeClass' => $typeClass,
  1212. 'phpType' => $phpType,
  1213. 'compositor'=> $compositor,
  1214. 'restrictionBase' => $restrictionBase,
  1215. 'elements' => $elements,
  1216. 'attrs' => $attrs,
  1217. 'arrayType' => $arrayType
  1218. );
  1219. }
  1220. }
  1221. ?><?php
  1222. /**
  1223. * for creating serializable abstractions of native PHP types
  1224. * NOTE: this is only really used when WSDL is not available.
  1225. *
  1226. * @author Dietrich Ayala <dietrich@ganx4.com>
  1227. * @version $Id: nusoap.php,v 1.1 2004/09/30 09:25:23 Tony Exp $
  1228. * @access public
  1229. */
  1230. class soapval extends nusoap_base {
  1231. /**
  1232. * constructor
  1233. *
  1234. * @param string $name optional name
  1235. * @param string $type optional type name
  1236. * @param mixed $value optional value
  1237. * @param string $namespace optional namespace of value
  1238. * @param string $type_namespace optional namespace of type
  1239. * @param array $attributes associative array of attributes to add to element serialization
  1240. * @access public
  1241. */
  1242. function soapval($name='soapval',$type=false,$value=-1,$element_ns=false,$type_ns=false,$attributes=false) {
  1243. $this->name = $name;
  1244. $this->value = $value;
  1245. $this->type = $type;
  1246. $this->element_ns = $element_ns;
  1247. $this->type_ns = $type_ns;
  1248. $this->attributes = $attributes;
  1249. }
  1250. /**
  1251. * return serialized value
  1252. *
  1253. * @return string XML data
  1254. * @access private
  1255. */
  1256. function serialize($use='encoded') {
  1257. return $this->serialize_val($this->value,$this->name,$this->type,$this->element_ns,$this->type_ns,$this->attributes,$use);
  1258. }
  1259. /**
  1260. * decodes a soapval object into a PHP native type
  1261. *
  1262. * @param object $soapval optional SOAPx4 soapval object, else uses self
  1263. * @return mixed
  1264. * @access public
  1265. */
  1266. function decode(){
  1267. return $this->value;
  1268. }
  1269. }
  1270. ?><?php
  1271. /**
  1272. * transport class for sending/receiving data via HTTP and HTTPS
  1273. * NOTE: PHP must be compiled with the CURL extension for HTTPS support
  1274. *
  1275. * @author Dietrich Ayala <dietrich@ganx4.com>
  1276. * @version $Id: nusoap.php,v 1.1 2004/09/30 09:25:23 Tony Exp $
  1277. * @access public
  1278. */
  1279. class soap_transport_http extends nusoap_base {
  1280. var $url = '';
  1281. var $uri = '';
  1282. var $scheme = '';
  1283. var $host = '';
  1284. var $port = '';
  1285. var $path = '';
  1286. var $request_method = 'POST';
  1287. var $protocol_version = '1.0';
  1288. var $encoding = '';
  1289. var $outgoing_headers = array();
  1290. var $incoming_headers = array();
  1291. var $outgoing_payload = '';
  1292. var $incoming_payload = '';
  1293. var $useSOAPAction = true;
  1294. var $persistentConnection = false;
  1295. var $ch = false; // cURL handle
  1296. /**
  1297. * constructor
  1298. */
  1299. function soap_transport_http($url){
  1300. $this->url = $url;
  1301. $u = parse_url($url);
  1302. foreach($u as $k => $v){
  1303. $this->debug("$k = $v");
  1304. $this->$k = $v;
  1305. }
  1306. // add any GET params to path
  1307. if(isset($u['query']) && $u['query'] != ''){
  1308. $this->path .= '?' . $u['query'];
  1309. }
  1310. // set default port
  1311. if(!isset($u['port'])){
  1312. if($u['scheme'] == 'https'){
  1313. $this->port = 443;
  1314. } else {
  1315. $this->port = 80;
  1316. }
  1317. }
  1318. $this->uri = $this->path;
  1319. // build headers
  1320. $this->outgoing_headers['User-Agent'] = $this->title.'/'.$this->version;
  1321. $this->outgoing_headers['Host'] = $this->host.':'.$this->port;
  1322. $this->outgoing_headers['Content-Type'] = 'text/xml; charset='.$this->soap_defencoding;
  1323. }
  1324. function connect($connection_timeout=0,$response_timeout=30){
  1325. if ($this->scheme == 'http') {
  1326. // use persistent connection
  1327. if($this->persistentConnection && is_resource($this->fp)){
  1328. if (!feof($this->fp)) {
  1329. $this->debug('Re-use persistent connection');
  1330. return true;
  1331. }
  1332. fclose($this->fp);
  1333. $this->debug('Closed persistent connection at EOF');
  1334. }
  1335. // set timeout
  1336. if($connection_timeout > 0){
  1337. $this->fp = fsockopen( $this->host, $this->port, $this->errno, $this->error_str, $connection_timeout);
  1338. } else {
  1339. $this->fp = fsockopen( $this->host, $this->port, $this->errno, $this->error_str);
  1340. }
  1341. // test pointer
  1342. if(!$this->fp) {
  1343. $this->debug('Couldn\'t open socket connection to server '.$this->url.', Error: '.$this->error_str);
  1344. $this->setError('Couldn\'t open socket connection to server: '.$this->url.', Error: '.$this->error_str);
  1345. return false;
  1346. }
  1347. // set response timeout
  1348. socket_set_timeout( $this->fp, $response_timeout);
  1349. $this->debug('socket connected');
  1350. return true;
  1351. } else if ($this->scheme == 'https') {
  1352. if (!extension_loaded('curl')) {
  1353. $this->setError('CURL Extension, or OpenSSL extension w/ PHP version >= 4.3 is required for HTTPS');
  1354. return false;
  1355. }
  1356. $this->debug('connect using http');
  1357. // init CURL
  1358. $this->ch = curl_init();
  1359. // set url
  1360. $hostURL = ($this->port != '') ? "https://$this->host:$this->port" : "https://$this->host";
  1361. // add path
  1362. $hostURL .= $this->path;
  1363. curl_setopt($this->ch, CURLOPT_URL, $hostURL);
  1364. // set other options
  1365. curl_setopt($this->ch, CURLOPT_HEADER, 1);
  1366. curl_setopt($this->ch, CURLOPT_RETURNTRANSFER, 1);
  1367. // encode
  1368. // We manage this ourselves through headers and encoding
  1369. // if(function_exists('gzuncompress')){
  1370. // curl_setopt($this->ch, CURLOPT_ENCODING, 'deflate');
  1371. // }
  1372. // persistent connection
  1373. if ($this->persistentConnection) {
  1374. // The way we send data, we cannot use persistent connections, since
  1375. // there will be some "junk" at the end of our request.
  1376. //curl_setopt($this->ch, CURL_HTTP_VERSION_1_1, true);
  1377. $this->persistentConnection = false;
  1378. $this->outgoing_headers['Connection'] = 'close';
  1379. }
  1380. // set timeout
  1381. if ($connection_timeout != 0) {
  1382. curl_setopt($this->ch, CURLOPT_TIMEOUT, $connection_timeout);
  1383. }
  1384. // recent versions of cURL turn on peer/host checking by default,
  1385. // while PHP binaries are not compiled with a default location for the
  1386. // CA cert bundle, so disable peer/host checking.
  1387. //curl_setopt($this->ch, CURLOPT_CAINFO, 'f:\php-4.3.2-win32\extensions\curl-ca-bundle.crt');
  1388. curl_setopt($this->ch, CURLOPT_SSL_VERIFYPEER, 0);
  1389. curl_setopt($this->ch, CURLOPT_SSL_VERIFYHOST, 0);
  1390. $this->debug('cURL connection set up');
  1391. return true;
  1392. } else {
  1393. $this->setError('Unknown scheme ' . $this->scheme);
  1394. $this->debug('Unknown scheme ' . $this->scheme);
  1395. return false;
  1396. }
  1397. }
  1398. /**
  1399. * send the SOAP message via HTTP
  1400. *
  1401. * @param string $data message data
  1402. * @param integer $timeout set timeout in seconds
  1403. * @return string data
  1404. * @access public
  1405. */
  1406. function send($data, $timeout=0) {
  1407. $this->debug('entered send() with data of length: '.strlen($data));
  1408. // make connnection
  1409. if(!$this->connect($timeout)){
  1410. return false;
  1411. }
  1412. // send request
  1413. if(!$this->sendRequest($data)){
  1414. return false;
  1415. }
  1416. // get response
  1417. if(!$data = $this->getResponse()){
  1418. return false;
  1419. }
  1420. $this->debug('end of send()');
  1421. return $data;
  1422. }
  1423. /**
  1424. * send the SOAP message via HTTPS 1.0 using CURL
  1425. *
  1426. * @param string $msg message data
  1427. * @param integer $timeout set timeout in seconds
  1428. * @return string data
  1429. * @access public
  1430. */
  1431. function sendHTTPS($data, $timeout=0) {
  1432. return $this->send($data, $timeout);
  1433. }
  1434. /**
  1435. * if authenticating, set user credentials here
  1436. *
  1437. * @param string $user
  1438. * @param string $pass
  1439. * @access public
  1440. */
  1441. function setCredentials($username, $password) {
  1442. $this->outgoing_headers['Authorization'] = ' Basic '.base64_encode($username.':'.$password);
  1443. }
  1444. /**
  1445. * set the soapaction value
  1446. *
  1447. * @param string $soapaction
  1448. * @access public
  1449. */
  1450. function setSOAPAction($soapaction) {
  1451. $this->outgoing_headers['SOAPAction'] = $soapaction;
  1452. }
  1453. /**
  1454. * use http encoding
  1455. *
  1456. * @param string $enc encoding style. supported values: gzip, deflate, or both
  1457. * @access public
  1458. */
  1459. function setEncoding($enc='gzip, deflate'){
  1460. $this->protocol_version = '1.1';
  1461. $this->outgoing_headers['Accept-Encoding'] = $enc;
  1462. $this->outgoing_headers['Connection'] = 'close';
  1463. $this->persistentConnection = false;
  1464. set_magic_quotes_runtime(0);
  1465. // deprecated
  1466. $this->encoding = $enc;
  1467. }
  1468. /**
  1469. * set proxy info here
  1470. *
  1471. * @param string $proxyhost
  1472. * @param string $proxyport
  1473. * @param string $proxyusername
  1474. * @param string $proxypassword
  1475. * @access public
  1476. */
  1477. function setProxy($proxyhost, $proxyport, $proxyusername = '', $proxypassword = '') {
  1478. $this->uri = $this->url;
  1479. $this->host = $proxyhost;
  1480. $this->port = $proxyport;
  1481. if ($proxyusername != '' && $proxypassword != '') {
  1482. $this->outgoing_headers['Proxy-Authorization'] = ' Basic '.base64_encode($proxyusername.':'.$proxypassword);
  1483. }
  1484. }
  1485. /**
  1486. * decode a string that is encoded w/ "chunked' transfer encoding
  1487. * as defined in RFC2068 19.4.6
  1488. *
  1489. * @param string $buffer
  1490. * @returns string
  1491. * @access public
  1492. */
  1493. function decodeChunked($buffer){
  1494. // length := 0
  1495. $length = 0;
  1496. $new = '';
  1497. // read chunk-size, chunk-extension (if any) and CRLF
  1498. // get the position of the linebreak
  1499. $chunkend = strpos($buffer,"\r\n") + 2;
  1500. $temp = substr($buffer,0,$chunkend);
  1501. $chunk_size = hexdec( trim($temp) );
  1502. $chunkstart = $chunkend;
  1503. // while (chunk-size > 0) {
  1504. while ($chunk_size > 0) {
  1505. $this->debug("chunkstart: $chunkstart chunk_size: $chunk_size");
  1506. $chunkend = strpos( $buffer, "\r\n", $chunkstart + $chunk_size);
  1507. // Just in case we got a broken connection
  1508. if ($chunkend == FALSE) {
  1509. $chunk = substr($buffer,$chunkstart);
  1510. // append chunk-data to entity-body
  1511. $new .= $chunk;
  1512. $length += strlen($chunk);
  1513. break;
  1514. }
  1515. // read chunk-data and CRLF
  1516. $chunk = substr($buffer,$chunkstart,$chunkend-$chunkstart);
  1517. // append chunk-data to entity-body
  1518. $new .= $chunk;
  1519. // length := length + chunk-size
  1520. $length += strlen($chunk);
  1521. // read chunk-size and CRLF
  1522. $chunkstart = $chunkend + 2;
  1523. $chunkend = strpos($buffer,"\r\n",$chunkstart)+2;
  1524. if ($chunkend == FALSE) {
  1525. break; //Just in case we got a broken connection
  1526. }
  1527. $temp = substr($buffer,$chunkstart,$chunkend-$chunkstart);
  1528. $chunk_size = hexdec( trim($temp) );
  1529. $chunkstart = $chunkend;
  1530. }
  1531. return $new;
  1532. }
  1533. /*
  1534. * Writes payload, including HTTP headers, to $this->outgoing_payload.
  1535. */
  1536. function buildPayload($data) {
  1537. // update content-type header since we may have changed soap_defencoding
  1538. $this->outgoing_headers['Content-Type'] = 'text/xml; charset='.$this->soap_defencoding;
  1539. // add content-length header
  1540. $this->outgoing_headers['Content-Length'] = strlen($data);
  1541. // start building outgoing payload:
  1542. $this->outgoing_payload = "$this->request_method $this->uri HTTP/$this->protocol_version\r\n";
  1543. // loop thru headers, serializing
  1544. foreach($this->outgoing_headers as $k => $v){
  1545. if($k == 'SOAPAction'){
  1546. $v = '"'.$v.'"';
  1547. }
  1548. $this->outgoing_payload .= $k.': '.$v."\r\n";
  1549. }
  1550. // header/body separator
  1551. $this->outgoing_payload .= "\r\n";
  1552. // add data
  1553. $this->outgoing_payload .= $data;
  1554. }
  1555. function sendRequest($data){
  1556. // build payload
  1557. $this->buildPayload($data);
  1558. if ($this->scheme == 'http') {
  1559. // send payload
  1560. if(!fputs($this->fp, $this->outgoing_payload, strlen($this->outgoing_payload))) {
  1561. $this->setError('couldn\'t write message data to socket');
  1562. $this->debug('couldn\'t write message data to socket');
  1563. return false;
  1564. }
  1565. $this->debug('wrote data to socket');
  1566. return true;
  1567. } else if ($this->scheme == 'https') {
  1568. // set payload
  1569. curl_setopt($this->ch, CURLOPT_CUSTOMREQUEST, $this->outgoing

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