PageRenderTime 120ms CodeModel.GetById 29ms RepoModel.GetById 0ms app.codeStats 1ms

/include/nusoap/nusoap.php

https://bitbucket.org/cviolette/sugarcrm
PHP | 10058 lines | 7499 code | 227 blank | 2332 comment | 804 complexity | 08f16a90957ec98acd49a1a5a43458dc MD5 | raw file
Possible License(s): LGPL-2.1, MPL-2.0-no-copyleft-exception, BSD-3-Clause
  1. <?php
  2. /*
  3. Modification information for LGPL compliance
  4. commit af784931b8ab2263776badac5ac3fc4776c9cd61
  5. Author: Stanislav Malyshev <smalyshev@gmail.com>
  6. Date: Thu Feb 17 18:09:12 2011 -0800
  7. bug 34897 - remove characters that aren't valid in XML
  8. commit 1767411d701b8216cc5e043888fd1337e2eca315
  9. Author: Stanislav Malyshev <smalyshev@gmail.com>
  10. Date: Fri Jan 7 12:19:10 2011 -0800
  11. conserve memory when no debug is enabled
  12. commit 843510ebf455368865302a05b9d5041815a32c23
  13. Author: John Mertic <jmertic@sugarcrm.com>
  14. Date: Wed Nov 17 13:18:09 2010 -0500
  15. Bug 40716 - Fix WSDL validation problem by removing hardcoded schemaLocation attribute for the <xsd:import> tag.
  16. commit 2bd12c02078f3e291bd9c1e76179a144c788ce97
  17. Author: Collin Lee <clee@Collin-Lee-MacBook-Pro.local>
  18. Date: Fri Oct 22 16:37:42 2010 -0400
  19. Bug: 39937
  20. We traced the error to a combination of the new Hoovers' WSDL + the nusoapclient code that winds up improperly encoding the parameter elem
  21. ents (this is because the namespace specified for the soap call did not match that declared in the WSDL). Made changes to nusoap.php so that w
  22. e may manually set a payload XML portion that will not apply the namespace encoding to the parameters. Fixed unit tests to reflect the changes
  23. and also re-enabled those for Hoovers that were marked skipped.
  24. r58622 - 2010-10-22 18:18:59 -0700 (Fri, 22 Oct 2010) - engsvnbuild - Author: lam <lam@198.18.142.201>
  25. bug 40066
  26. r58361 - 2010-09-29 16:59:02 -0700 (Wed, 29 Sep 2010) - kjing - Author: Jenny Gonsalves <jenny@sugarcrm.com>
  27. Merging with maint_6_0_1 (svn merge -r 58250:58342)
  28. r57813 - 2010-08-19 10:34:44 -0700 (Thu, 19 Aug 2010) - kjing - Author: John Mertic <jmertic@sugarcrm.com>
  29. Bug 39085 - When loading the opposite search panel via ajax on the ListViews, call the index action instead of the ListView action to avoid touching pre-MVC code by accident.
  30. r57707 - 2010-08-10 12:26:13 -0700 (Tue, 10 Aug 2010) - kjing - Author: Stanislav Malyshev <smalyshev@gmail.com>
  31. fix SOAP calls with no parameters
  32. r56990 - 2010-06-16 13:05:36 -0700 (Wed, 16 Jun 2010) - kjing - snapshot "Mango" svn branch to a new one for GitHub sync
  33. r56989 - 2010-06-16 13:01:33 -0700 (Wed, 16 Jun 2010) - kjing - defunt "Mango" svn dev branch before github cutover
  34. r55980 - 2010-04-19 13:31:28 -0700 (Mon, 19 Apr 2010) - kjing - create Mango (6.1) based on windex
  35. r51719 - 2009-10-22 10:18:00 -0700 (Thu, 22 Oct 2009) - mitani - Converted to Build 3 tags and updated the build system
  36. r51634 - 2009-10-19 13:32:22 -0700 (Mon, 19 Oct 2009) - mitani - Windex is the branch for Sugar Sales 1.0 development
  37. r51508 - 2009-10-14 07:40:23 -0700 (Wed, 14 Oct 2009) - jmertic - More fallout fixes from the PHP 5.3 ereg to preg changes.
  38. r51455 - 2009-10-13 07:56:48 -0700 (Tue, 13 Oct 2009) - jmertic - Bug 33202 - Enable install of SugarCRM on PHP 5.3.0, asserting that the minimum supported version is PHP 5.2.x.
  39. r51443 - 2009-10-12 13:34:36 -0700 (Mon, 12 Oct 2009) - jmertic - Bug 33332 - Made application PHP 5.3 compliant with E_DEPRECATED warnings on by:
  40. - Changing all ereg function to either preg or simple string based ones
  41. - No more references to magic quotes.
  42. - Change all the session_unregister() functions to just unset() the correct session variable instead.
  43. r50375 - 2009-08-24 18:07:43 -0700 (Mon, 24 Aug 2009) - dwong - branch kobe2 from tokyo r50372
  44. r45763 - 2009-04-01 12:16:18 -0700 (Wed, 01 Apr 2009) - majed - Removed half of the require_once and include_onces in the product that were redundant or could be handled easily by the auto loader
  45. r45680 - 2009-03-30 14:34:35 -0700 (Mon, 30 Mar 2009) - Samir Gandhi - modifeid serializeSchema to generate WS-I compliant WSDL
  46. r42807 - 2008-12-29 11:16:59 -0800 (Mon, 29 Dec 2008) - dwong - Branch from trunk/sugarcrm r42806 to branches/tokyo/sugarcrm
  47. r42645 - 2008-12-18 13:41:08 -0800 (Thu, 18 Dec 2008) - awu - merging maint_5_2_0 rev41336:HEAD to trunk
  48. r41647 - 2008-11-11 17:44:30 -0800 (Tue, 11 Nov 2008) - majed - Fixes a few bugs
  49. r41596 - 2008-11-10 19:20:04 -0800 (Mon, 10 Nov 2008) - Samir Gandhi - modified to set $method in the code
  50. r41558 - 2008-11-10 14:35:34 -0800 (Mon, 10 Nov 2008) - majed - changes nusoap to allow for registering classes
  51. r39619 - 2008-09-09 13:41:34 -0700 (Tue, 09 Sep 2008) - jmertic - Bug 24827 - Remove all instances where we return a new object and assign it by reference, since this is deprecated in PHP 5 and emits E_DEPRECATED errors in PHP 5.3.
  52. Touched:
  53. - data/SugarBean.php
  54. - include/domit/php_http_client_generic.php
  55. - include/domit/php_http_connector.php
  56. - include/domit/testing_domit.php
  57. - include/domit/xml_domit_getelementsbypath.php
  58. - include/domit/xml_domit_lite_parser.php
  59. - include/domit/xml_domit_nodemaps.php
  60. - include/domit/xml_domit_parser.php
  61. - include/domit/xml_domit_shared.php
  62. - include/generic/SugarWidgets/SugarWidgetField.php
  63. - include/generic/SugarWidgets/SugarWidgetReportField.php
  64. - include/ListView/ProcessView.php
  65. - include/nusoap/class.soapclient.php
  66. - include/nusoap/nusoap.php
  67. - include/nusoap/nusoapmime.php
  68. - include/Pear/HTML_Safe/Safe.php
  69. - include/Pear/XML_HTMLSax3/HTMLSax3.php
  70. - modules/Administration/RebuildWorkFlow.php
  71. - modules/Expressions/RelateSelector.php
  72. - modules/Reports/templates/templates_reports.php
  73. - modules/WorkFlow/Delete.php
  74. - modules/WorkFlow/Save.php
  75. - modules/WorkFlow/SaveSequence.php
  76. - modules/WorkFlow/WorkFlow.php
  77. - modules/WorkFlowActionShells/CreateStep1.php
  78. - modules/WorkFlowActionShells/CreateStep2.php
  79. - modules/WorkFlowActionShells/Save.php
  80. - modules/WorkFlowActionShells/WorkFlowActionShell.php
  81. - modules/WorkFlowAlerts/Save.php
  82. - modules/WorkFlowAlerts/WorkFlowAlert.php
  83. - modules/WorkFlowAlertShells/DetailView.php
  84. - modules/WorkFlowAlertShells/WorkFlowAlertShell.php
  85. - modules/WorkFlowTriggerShells/CreateStep1.php
  86. - modules/WorkFlowTriggerShells/CreateStepFilter.php
  87. - modules/WorkFlowTriggerShells/SaveFilter.php
  88. - modules/WorkFlowTriggerShells/WorkFlowTriggerShell.php
  89. - soap/SoapHelperFunctions.php
  90. - test/modules/DynamicFields/DynamicFields_Bug24095_test.php
  91. - test/simpletest/browser.php
  92. - test/simpletest/default_reporter.php
  93. - test/simpletest/detached.php
  94. - test/simpletest/eclipse.php
  95. - test/simpletest/expectation.php
  96. - test/simpletest/extensions/pear_test_case.php
  97. - test/simpletest/form.php
  98. - test/simpletest/http.php
  99. - test/simpletest/mock_objects.php
  100. - test/simpletest/page.php
  101. - test/simpletest/parser.php
  102. - test/simpletest/remote.php
  103. - test/simpletest/shell_tester.php
  104. - test/simpletest/simple_test.php
  105. - test/simpletest/simpletest.php
  106. - test/simpletest/test/acceptance_test.php
  107. - test/simpletest/test/adapter_test.php
  108. - test/simpletest/test/authentication_test.php
  109. - test/simpletest/test/browser_test.php
  110. - test/simpletest/test/collector_test.php
  111. - test/simpletest/test/compatibility_test.php
  112. - test/simpletest/test/detached_test.php
  113. - test/simpletest/test/eclipse_test.php
  114. - test/simpletest/test/encoding_test.php
  115. - test/simpletest/test/errors_test.php
  116. - test/simpletest/test/expectation_test.php
  117. - test/simpletest/test/form_test.php
  118. - test/simpletest/test/frames_test.php
  119. - test/simpletest/test/http_test.php
  120. - test/simpletest/test/live_test.php
  121. - test/simpletest/test/mock_objects_test.php
  122. - test/simpletest/test/page_test.php
  123. - test/simpletest/test/parse_error_test.php
  124. - test/simpletest/test/parser_test.php
  125. - test/simpletest/test/remote_test.php
  126. - test/simpletest/test/shell_test.php
  127. - test/simpletest/test/shell_tester_test.php
  128. - test/simpletest/test/simpletest_test.php
  129. - test/simpletest/test/site/page_request.php
  130. - test/simpletest/test/tag_test.php
  131. - test/simpletest/test/unit_tester_test.php
  132. - test/simpletest/test/user_agent_test.php
  133. - test/simpletest/test/visual_test.php
  134. - test/simpletest/test/xml_test.php
  135. - test/simpletest/test_case.php
  136. - test/simpletest/ui/array_reporter/test.php
  137. - test/simpletest/ui/recorder/test.php
  138. - test/simpletest/unit_tester.php
  139. - test/simpletest/url.php
  140. - test/simpletest/user_agent.php
  141. - test/simpletest/web_tester.php
  142. - test/spikephpcoverage/src/PEAR.php
  143. - test/spikephpcoverage/src/util/Utility.php
  144. - test/spikephpcoverage/src/XML/Parser.php
  145. - test/spikephpcoverage/src/XML/Parser/Simple.php
  146. - test/test_utilities/SugarTest_SimpleBrowser.php
  147. r38362 - 2008-07-28 14:06:59 -0700 (Mon, 28 Jul 2008) - roger - bug: 23897. Using print_r when using the debug statement in nusoap will print out the statements to the screen if the call is coming from the UI.
  148. r38300 - 2008-07-25 13:33:43 -0700 (Fri, 25 Jul 2008) - Samir Gandhi - put the debug in parseresponse function
  149. r38293 - 2008-07-25 12:32:34 -0700 (Fri, 25 Jul 2008) - Samir Gandhi - to put all the debug statements return value in the call function
  150. r36824 - 2008-06-18 09:26:11 -0700 (Wed, 18 Jun 2008) - roger - bug: 21832
  151. r26422 - 2007-09-05 17:29:12 -0700 (Wed, 05 Sep 2007) - majed - migrate from beta 1 to trunk
  152. r15787 - 2006-08-10 10:14:41 -0700 (Thu, 10 Aug 2006) - roger - RRS: bug 7961
  153. r14701 - 2006-07-17 13:37:26 -0700 (Mon, 17 Jul 2006) - roger - RRS: bug 5801
  154. r13782 - 2006-06-06 10:58:55 -0700 (Tue, 06 Jun 2006) - majed - changes entry point code
  155. r11466 - 2006-02-01 15:49:47 -0800 (Wed, 01 Feb 2006) - jacob - Adding extra !empty check to get around a PHP warning.
  156. r11115 - 2006-01-17 14:54:45 -0800 (Tue, 17 Jan 2006) - majed - add entry point validation
  157. r10585 - 2005-12-13 14:42:26 -0800 (Tue, 13 Dec 2005) - majed - adds new license mechanisim
  158. r10170 - 2005-12-05 18:37:46 -0800 (Mon, 05 Dec 2005) - majed - fixes various issues
  159. r8999 - 2005-11-04 05:26:49 -0800 (Fri, 04 Nov 2005) - roger - When nusoap was upgraded we had an issue with the user's default language not being populated during a soap request. I determined the reason this was happening and have checked in the corresponding change to nusoap.
  160. r8991 - 2005-11-03 19:07:25 -0800 (Thu, 03 Nov 2005) - majed - fixes nusoap issue
  161. r8846 - 2005-10-31 11:01:12 -0800 (Mon, 31 Oct 2005) - majed - new version of nusoap
  162. r7905 - 2005-09-21 19:12:57 -0700 (Wed, 21 Sep 2005) - majed - restores old nusoap pre & with a few fixes
  163. r7861 - 2005-09-20 15:40:25 -0700 (Tue, 20 Sep 2005) - majed - & fix for 3.5.1
  164. r7452 - 2005-08-17 11:32:34 -0700 (Wed, 17 Aug 2005) - majed - changes soap to nusoap
  165. r5820 - 2005-06-21 14:22:24 -0700 (Tue, 21 Jun 2005) - majed - fixes issues with nusoap and with custom fields
  166. r5462 - 2005-05-25 13:50:11 -0700 (Wed, 25 May 2005) - majed - upgraded nusoap to .6.9
  167. r5104 - 2005-05-04 15:33:41 -0700 (Wed, 04 May 2005) - majed - gets rid of HTTP_GET_VARS and what not which has been deprecated
  168. r573 - 2004-09-04 13:03:32 -0700 (Sat, 04 Sep 2004) - sugarclint - undoing copyrights added in inadvertantly. --clint
  169. r546 - 2004-09-03 11:49:38 -0700 (Fri, 03 Sep 2004) - sugarmsi - removed echo count
  170. r354 - 2004-08-02 23:00:37 -0700 (Mon, 02 Aug 2004) - sugarjacob - Adding Soap
  171. */
  172. if(!defined('sugarEntry') || !sugarEntry) die('Not A Valid Entry Point');
  173. /*
  174. $Id: nusoap.php 58622 2010-10-23 01:18:59Z engsvnbuild $
  175. NuSOAP - Web Services Toolkit for PHP
  176. Copyright (c) 2002 NuSphere Corporation
  177. This library is free software; you can redistribute it and/or
  178. modify it under the terms of the GNU Lesser General Public
  179. License as published by the Free Software Foundation; either
  180. version 2.1 of the License, or (at your option) any later version.
  181. n
  182. This library is distributed in the hope that it will be useful,
  183. but WITHOUT ANY WARRANTY; without even the implied warranty of
  184. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  185. Lesser General Public License for more details.
  186. You should have received a copy of the GNU Lesser General Public
  187. License along with this library; if not, write to the Free Software
  188. Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  189. The NuSOAP project home is:
  190. http://sourceforge.net/projects/nusoap/
  191. The primary support for NuSOAP is the Help forum on the project home page.
  192. If you have any questions or comments, please email:
  193. Dietrich Ayala
  194. dietrich@ganx4.com
  195. http://dietrich.ganx4.com/nusoap
  196. NuSphere Corporation
  197. http://www.nusphere.com
  198. */
  199. /*
  200. * Some of the standards implmented in whole or part by NuSOAP:
  201. *
  202. * SOAP 1.1 (http://www.w3.org/TR/2000/NOTE-SOAP-20000508/)
  203. * WSDL 1.1 (http://www.w3.org/TR/2001/NOTE-wsdl-20010315)
  204. * SOAP Messages With Attachments (http://www.w3.org/TR/SOAP-attachments)
  205. * XML 1.0 (http://www.w3.org/TR/2006/REC-xml-20060816/)
  206. * Namespaces in XML 1.0 (http://www.w3.org/TR/2006/REC-xml-names-20060816/)
  207. * XML Schema 1.0 (http://www.w3.org/TR/xmlschema-0/)
  208. * RFC 2045 Multipurpose Internet Mail Extensions (MIME) Part One: Format of Internet Message Bodies
  209. * RFC 2068 Hypertext Transfer Protocol -- HTTP/1.1
  210. * RFC 2617 HTTP Authentication: Basic and Digest Access Authentication
  211. */
  212. /* load classes
  213. // necessary classes
  214. require_once('class.soapclient.php');
  215. require_once('class.soap_val.php');
  216. require_once('class.soap_parser.php');
  217. require_once('class.soap_fault.php');
  218. // transport classes
  219. require_once('class.soap_transport_http.php');
  220. // optional add-on classes
  221. require_once('class.xmlschema.php');
  222. require_once('class.wsdl.php');
  223. // server class
  224. require_once('class.soap_server.php');*/
  225. // class variable emulation
  226. // cf. http://www.webkreator.com/php/techniques/php-static-class-variables.html
  227. $GLOBALS['_transient']['static']['nusoap_base']['globalDebugLevel'] = 0;
  228. /**
  229. *
  230. * nusoap_base
  231. *
  232. * @author Dietrich Ayala <dietrich@ganx4.com>
  233. * @author Scott Nichol <snichol@users.sourceforge.net>
  234. * @access public
  235. */
  236. class nusoap_base {
  237. /**
  238. * Identification for HTTP headers.
  239. *
  240. * @var string
  241. * @access private
  242. */
  243. var $title = 'NuSOAP';
  244. /**
  245. * Version for HTTP headers.
  246. *
  247. * @var string
  248. * @access private
  249. */
  250. var $version = '0.9.5';
  251. /**
  252. * CVS revision for HTTP headers.
  253. *
  254. * @var string
  255. * @access private
  256. */
  257. var $revision = '$Revision: 58622 $';
  258. /**
  259. * Current error string (manipulated by getError/setError)
  260. *
  261. * @var string
  262. * @access private
  263. */
  264. var $error_str = '';
  265. /**
  266. * Current debug string (manipulated by debug/appendDebug/clearDebug/getDebug/getDebugAsXMLComment)
  267. *
  268. * @var string
  269. * @access private
  270. */
  271. var $debug_str = '';
  272. /**
  273. * toggles automatic encoding of special characters as entities
  274. * (should always be true, I think)
  275. *
  276. * @var boolean
  277. * @access private
  278. */
  279. var $charencoding = true;
  280. /**
  281. * the debug level for this instance
  282. *
  283. * @var integer
  284. * @access private
  285. */
  286. var $debugLevel;
  287. /**
  288. * set schema version
  289. *
  290. * @var string
  291. * @access public
  292. */
  293. var $XMLSchemaVersion = 'http://www.w3.org/2001/XMLSchema';
  294. /**
  295. * charset encoding for outgoing messages
  296. *
  297. * @var string
  298. * @access public
  299. */
  300. //var $soap_defencoding = 'ISO-8859-1';
  301. var $soap_defencoding = 'UTF-8';
  302. /**
  303. * namespaces in an array of prefix => uri
  304. *
  305. * this is "seeded" by a set of constants, but it may be altered by code
  306. *
  307. * @var array
  308. * @access public
  309. */
  310. var $namespaces = array(
  311. 'SOAP-ENV' => 'http://schemas.xmlsoap.org/soap/envelope/',
  312. 'xsd' => 'http://www.w3.org/2001/XMLSchema',
  313. 'xsi' => 'http://www.w3.org/2001/XMLSchema-instance',
  314. 'SOAP-ENC' => 'http://schemas.xmlsoap.org/soap/encoding/'
  315. );
  316. /**
  317. * namespaces used in the current context, e.g. during serialization
  318. *
  319. * @var array
  320. * @access private
  321. */
  322. var $usedNamespaces = array();
  323. /**
  324. * XML Schema types in an array of uri => (array of xml type => php type)
  325. * is this legacy yet?
  326. * no, this is used by the nusoap_xmlschema class to verify type => namespace mappings.
  327. * @var array
  328. * @access public
  329. */
  330. var $typemap = array(
  331. 'http://www.w3.org/2001/XMLSchema' => array(
  332. 'string'=>'string','boolean'=>'boolean','float'=>'double','double'=>'double','decimal'=>'double',
  333. 'duration'=>'','dateTime'=>'string','time'=>'string','date'=>'string','gYearMonth'=>'',
  334. 'gYear'=>'','gMonthDay'=>'','gDay'=>'','gMonth'=>'','hexBinary'=>'string','base64Binary'=>'string',
  335. // abstract "any" types
  336. 'anyType'=>'string','anySimpleType'=>'string',
  337. // derived datatypes
  338. 'normalizedString'=>'string','token'=>'string','language'=>'','NMTOKEN'=>'','NMTOKENS'=>'','Name'=>'','NCName'=>'','ID'=>'',
  339. 'IDREF'=>'','IDREFS'=>'','ENTITY'=>'','ENTITIES'=>'','integer'=>'integer','nonPositiveInteger'=>'integer',
  340. 'negativeInteger'=>'integer','long'=>'integer','int'=>'integer','short'=>'integer','byte'=>'integer','nonNegativeInteger'=>'integer',
  341. 'unsignedLong'=>'','unsignedInt'=>'','unsignedShort'=>'','unsignedByte'=>'','positiveInteger'=>''),
  342. 'http://www.w3.org/2000/10/XMLSchema' => array(
  343. 'i4'=>'','int'=>'integer','boolean'=>'boolean','string'=>'string','double'=>'double',
  344. 'float'=>'double','dateTime'=>'string',
  345. 'timeInstant'=>'string','base64Binary'=>'string','base64'=>'string','ur-type'=>'array'),
  346. 'http://www.w3.org/1999/XMLSchema' => array(
  347. 'i4'=>'','int'=>'integer','boolean'=>'boolean','string'=>'string','double'=>'double',
  348. 'float'=>'double','dateTime'=>'string',
  349. 'timeInstant'=>'string','base64Binary'=>'string','base64'=>'string','ur-type'=>'array'),
  350. 'http://soapinterop.org/xsd' => array('SOAPStruct'=>'struct'),
  351. 'http://schemas.xmlsoap.org/soap/encoding/' => array('base64'=>'string','array'=>'array','Array'=>'array'),
  352. 'http://xml.apache.org/xml-soap' => array('Map')
  353. );
  354. /**
  355. * XML entities to convert
  356. *
  357. * @var array
  358. * @access public
  359. * @deprecated
  360. * @see expandEntities
  361. */
  362. var $xmlEntities = array('quot' => '"','amp' => '&',
  363. 'lt' => '<','gt' => '>','apos' => "'");
  364. /**
  365. * Payload override
  366. * This is to allows us to override the payload to resolve issues where we need to take
  367. * control of the xml content
  368. * @var string
  369. * @access public
  370. *
  371. */
  372. var $payloadOverride;
  373. /**
  374. * constructor
  375. *
  376. * @access public
  377. */
  378. function nusoap_base() {
  379. $this->debugLevel = $GLOBALS['_transient']['static']['nusoap_base']['globalDebugLevel'];
  380. }
  381. /**
  382. * gets the global debug level, which applies to future instances
  383. *
  384. * @return integer Debug level 0-9, where 0 turns off
  385. * @access public
  386. */
  387. function getGlobalDebugLevel() {
  388. return $GLOBALS['_transient']['static']['nusoap_base']['globalDebugLevel'];
  389. }
  390. /**
  391. * sets the global debug level, which applies to future instances
  392. *
  393. * @param int $level Debug level 0-9, where 0 turns off
  394. * @access public
  395. */
  396. function setGlobalDebugLevel($level) {
  397. $GLOBALS['_transient']['static']['nusoap_base']['globalDebugLevel'] = $level;
  398. }
  399. /**
  400. * gets the debug level for this instance
  401. *
  402. * @return int Debug level 0-9, where 0 turns off
  403. * @access public
  404. */
  405. function getDebugLevel() {
  406. return $this->debugLevel;
  407. }
  408. /**
  409. * sets the debug level for this instance
  410. *
  411. * @param int $level Debug level 0-9, where 0 turns off
  412. * @access public
  413. */
  414. function setDebugLevel($level) {
  415. $this->debugLevel = $level;
  416. }
  417. /**
  418. * adds debug data to the instance debug string with formatting
  419. *
  420. * @param string $string debug data
  421. * @access private
  422. */
  423. function debug($string){
  424. if ($this->debugLevel > 0) {
  425. $this->appendDebug($this->getmicrotime().' '.get_class($this).": $string\n");
  426. }
  427. }
  428. /**
  429. * adds debug data to the instance debug string without formatting
  430. *
  431. * @param string $string debug data
  432. * @access public
  433. */
  434. function appendDebug($string){
  435. if ($this->debugLevel > 0) {
  436. // it would be nice to use a memory stream here to use
  437. // memory more efficiently
  438. $this->debug_str .= $string;
  439. }
  440. }
  441. /**
  442. * clears the current debug data for this instance
  443. *
  444. * @access public
  445. */
  446. function clearDebug() {
  447. // it would be nice to use a memory stream here to use
  448. // memory more efficiently
  449. $this->debug_str = '';
  450. }
  451. /**
  452. * gets the current debug data for this instance
  453. *
  454. * @return debug data
  455. * @access public
  456. */
  457. function &getDebug() {
  458. // it would be nice to use a memory stream here to use
  459. // memory more efficiently
  460. return $this->debug_str;
  461. }
  462. /**
  463. * gets the current debug data for this instance as an XML comment
  464. * this may change the contents of the debug data
  465. *
  466. * @return debug data as an XML comment
  467. * @access public
  468. */
  469. function &getDebugAsXMLComment() {
  470. // it would be nice to use a memory stream here to use
  471. // memory more efficiently
  472. while (strpos($this->debug_str, '--')) {
  473. $this->debug_str = str_replace('--', '- -', $this->debug_str);
  474. }
  475. $ret = "<!--\n" . $this->debug_str . "\n-->";
  476. return $ret;
  477. }
  478. /**
  479. * expands entities, e.g. changes '<' to '&lt;'.
  480. *
  481. * @param string $val The string in which to expand entities.
  482. * @access private
  483. */
  484. function expandEntities($val) {
  485. if ($this->charencoding) {
  486. $val = htmlspecialchars($val, ENT_QUOTES, $this->soap_defencoding);
  487. // XML 1.0 doesn't allow those...
  488. $val = preg_replace("/([\\x00-\\x08\\x0B\\x0C\\x0E-\\x1F])/", '', $val);
  489. }
  490. return $val;
  491. }
  492. /**
  493. * returns error string if present
  494. *
  495. * @return mixed error string or false
  496. * @access public
  497. */
  498. function getError(){
  499. if($this->error_str != ''){
  500. return $this->error_str;
  501. }
  502. return false;
  503. }
  504. /**
  505. * sets error string
  506. *
  507. * @return boolean $string error string
  508. * @access private
  509. */
  510. function setError($str){
  511. $this->error_str = $str;
  512. }
  513. /**
  514. * detect if array is a simple array or a struct (associative array)
  515. *
  516. * @param mixed $val The PHP array
  517. * @return string (arraySimple|arrayStruct)
  518. * @access private
  519. */
  520. function isArraySimpleOrStruct($val) {
  521. $keyList = array_keys($val);
  522. foreach ($keyList as $keyListValue) {
  523. if (!is_int($keyListValue)) {
  524. return 'arrayStruct';
  525. }
  526. }
  527. return 'arraySimple';
  528. }
  529. /**
  530. * serializes PHP values in accordance w/ section 5. Type information is
  531. * not serialized if $use == 'literal'.
  532. *
  533. * @param mixed $val The value to serialize
  534. * @param string $name The name (local part) of the XML element
  535. * @param string $type The XML schema type (local part) for the element
  536. * @param string $name_ns The namespace for the name of the XML element
  537. * @param string $type_ns The namespace for the type of the element
  538. * @param array $attributes The attributes to serialize as name=>value pairs
  539. * @param string $use The WSDL "use" (encoded|literal)
  540. * @param boolean $soapval Whether this is called from soapval.
  541. * @return string The serialized element, possibly with child elements
  542. * @access public
  543. */
  544. function serialize_val($val,$name=false,$type=false,$name_ns=false,$type_ns=false,$attributes=false,$use='encoded',$soapval=false) {
  545. $this->debug("in serialize_val: name=$name, type=$type, name_ns=$name_ns, type_ns=$type_ns, use=$use, soapval=$soapval");
  546. $this->appendDebug('value=' . $this->varDump($val));
  547. $this->appendDebug('attributes=' . $this->varDump($attributes));
  548. if (is_object($val) && get_class($val) == 'soapval' && (! $soapval)) {
  549. $this->debug("serialize_val: serialize soapval");
  550. $xml = $val->serialize($use);
  551. $this->appendDebug($val->getDebug());
  552. $val->clearDebug();
  553. $this->debug("serialize_val of soapval returning $xml");
  554. return $xml;
  555. }
  556. // force valid name if necessary
  557. if (is_numeric($name)) {
  558. $name = '__numeric_' . $name;
  559. } elseif (! $name) {
  560. $name = 'noname';
  561. }
  562. // if name has ns, add ns prefix to name
  563. $xmlns = '';
  564. if($name_ns){
  565. $prefix = 'nu'.rand(1000,9999);
  566. $name = $prefix.':'.$name;
  567. $xmlns .= " xmlns:$prefix=\"$name_ns\"";
  568. }
  569. // if type is prefixed, create type prefix
  570. if($type_ns != '' && $type_ns == $this->namespaces['xsd']){
  571. // need to fix this. shouldn't default to xsd if no ns specified
  572. // w/o checking against typemap
  573. $type_prefix = 'xsd';
  574. } elseif($type_ns){
  575. $type_prefix = 'ns'.rand(1000,9999);
  576. $xmlns .= " xmlns:$type_prefix=\"$type_ns\"";
  577. }
  578. // serialize attributes if present
  579. $atts = '';
  580. if($attributes){
  581. foreach($attributes as $k => $v){
  582. $atts .= " $k=\"".$this->expandEntities($v).'"';
  583. }
  584. }
  585. // serialize null value
  586. if (is_null($val)) {
  587. $this->debug("serialize_val: serialize null");
  588. if ($use == 'literal') {
  589. // TODO: depends on minOccurs
  590. $xml = "<$name$xmlns$atts/>";
  591. $this->debug("serialize_val returning $xml");
  592. return $xml;
  593. } else {
  594. if (isset($type) && isset($type_prefix)) {
  595. $type_str = " xsi:type=\"$type_prefix:$type\"";
  596. } else {
  597. $type_str = '';
  598. }
  599. $xml = "<$name$xmlns$type_str$atts xsi:nil=\"true\"/>";
  600. $this->debug("serialize_val returning $xml");
  601. return $xml;
  602. }
  603. }
  604. // serialize if an xsd built-in primitive type
  605. if($type != '' && isset($this->typemap[$this->XMLSchemaVersion][$type])){
  606. $this->debug("serialize_val: serialize xsd built-in primitive type");
  607. if (is_bool($val)) {
  608. if ($type == 'boolean') {
  609. $val = $val ? 'true' : 'false';
  610. } elseif (! $val) {
  611. $val = 0;
  612. }
  613. } else if (is_string($val)) {
  614. $val = $this->expandEntities($val);
  615. }
  616. if ($use == 'literal') {
  617. $xml = "<$name$xmlns$atts>$val</$name>";
  618. $this->debug("serialize_val returning $xml");
  619. return $xml;
  620. } else {
  621. $xml = "<$name$xmlns xsi:type=\"xsd:$type\"$atts>$val</$name>";
  622. $this->debug("serialize_val returning $xml");
  623. return $xml;
  624. }
  625. }
  626. // detect type and serialize
  627. $xml = '';
  628. switch(true) {
  629. case (is_bool($val) || $type == 'boolean'):
  630. $this->debug("serialize_val: serialize boolean");
  631. if ($type == 'boolean') {
  632. $val = $val ? 'true' : 'false';
  633. } elseif (! $val) {
  634. $val = 0;
  635. }
  636. if ($use == 'literal') {
  637. $xml .= "<$name$xmlns$atts>$val</$name>";
  638. } else {
  639. $xml .= "<$name$xmlns xsi:type=\"xsd:boolean\"$atts>$val</$name>";
  640. }
  641. break;
  642. case (is_int($val) || is_long($val) || $type == 'int'):
  643. $this->debug("serialize_val: serialize int");
  644. if ($use == 'literal') {
  645. $xml .= "<$name$xmlns$atts>$val</$name>";
  646. } else {
  647. $xml .= "<$name$xmlns xsi:type=\"xsd:int\"$atts>$val</$name>";
  648. }
  649. break;
  650. case (is_float($val)|| is_double($val) || $type == 'float'):
  651. $this->debug("serialize_val: serialize float");
  652. if ($use == 'literal') {
  653. $xml .= "<$name$xmlns$atts>$val</$name>";
  654. } else {
  655. $xml .= "<$name$xmlns xsi:type=\"xsd:float\"$atts>$val</$name>";
  656. }
  657. break;
  658. case (is_string($val) || $type == 'string'):
  659. $this->debug("serialize_val: serialize string");
  660. $val = $this->expandEntities($val);
  661. if ($use == 'literal') {
  662. $xml .= "<$name$xmlns$atts>$val</$name>";
  663. } else {
  664. $xml .= "<$name$xmlns xsi:type=\"xsd:string\"$atts>$val</$name>";
  665. }
  666. break;
  667. case is_object($val):
  668. $this->debug("serialize_val: serialize object");
  669. if (get_class($val) == 'soapval') {
  670. $this->debug("serialize_val: serialize soapval object");
  671. $pXml = $val->serialize($use);
  672. $this->appendDebug($val->getDebug());
  673. $val->clearDebug();
  674. } else {
  675. if (! $name) {
  676. $name = get_class($val);
  677. $this->debug("In serialize_val, used class name $name as element name");
  678. } else {
  679. $this->debug("In serialize_val, do not override name $name for element name for class " . get_class($val));
  680. }
  681. foreach(get_object_vars($val) as $k => $v){
  682. $pXml = isset($pXml) ? $pXml.$this->serialize_val($v,$k,false,false,false,false,$use) : $this->serialize_val($v,$k,false,false,false,false,$use);
  683. }
  684. }
  685. if(isset($type) && isset($type_prefix)){
  686. $type_str = " xsi:type=\"$type_prefix:$type\"";
  687. } else {
  688. $type_str = '';
  689. }
  690. if ($use == 'literal') {
  691. $xml .= "<$name$xmlns$atts>$pXml</$name>";
  692. } else {
  693. $xml .= "<$name$xmlns$type_str$atts>$pXml</$name>";
  694. }
  695. break;
  696. break;
  697. case (is_array($val) || $type):
  698. // detect if struct or array
  699. $valueType = $this->isArraySimpleOrStruct($val);
  700. if($valueType=='arraySimple' || preg_match('/^ArrayOf/',$type)){
  701. $this->debug("serialize_val: serialize array");
  702. $i = 0;
  703. if(is_array($val) && count($val)> 0){
  704. foreach($val as $v){
  705. if(is_object($v) && get_class($v) == 'soapval'){
  706. $tt_ns = $v->type_ns;
  707. $tt = $v->type;
  708. } elseif (is_array($v)) {
  709. $tt = $this->isArraySimpleOrStruct($v);
  710. } else {
  711. $tt = gettype($v);
  712. }
  713. $array_types[$tt] = 1;
  714. // TODO: for literal, the name should be $name
  715. $xml .= $this->serialize_val($v,'item',false,false,false,false,$use);
  716. ++$i;
  717. }
  718. if(count($array_types) > 1){
  719. $array_typename = 'xsd:anyType';
  720. } elseif(isset($tt) && isset($this->typemap[$this->XMLSchemaVersion][$tt])) {
  721. if ($tt == 'integer') {
  722. $tt = 'int';
  723. }
  724. $array_typename = 'xsd:'.$tt;
  725. } elseif(isset($tt) && $tt == 'arraySimple'){
  726. $array_typename = 'SOAP-ENC:Array';
  727. } elseif(isset($tt) && $tt == 'arrayStruct'){
  728. $array_typename = 'unnamed_struct_use_soapval';
  729. } else {
  730. // if type is prefixed, create type prefix
  731. if ($tt_ns != '' && $tt_ns == $this->namespaces['xsd']){
  732. $array_typename = 'xsd:' . $tt;
  733. } elseif ($tt_ns) {
  734. $tt_prefix = 'ns' . rand(1000, 9999);
  735. $array_typename = "$tt_prefix:$tt";
  736. $xmlns .= " xmlns:$tt_prefix=\"$tt_ns\"";
  737. } else {
  738. $array_typename = $tt;
  739. }
  740. }
  741. $array_type = $i;
  742. if ($use == 'literal') {
  743. $type_str = '';
  744. } else if (isset($type) && isset($type_prefix)) {
  745. $type_str = " xsi:type=\"$type_prefix:$type\"";
  746. } else {
  747. $type_str = " xsi:type=\"SOAP-ENC:Array\" SOAP-ENC:arrayType=\"".$array_typename."[$array_type]\"";
  748. }
  749. // empty array
  750. } else {
  751. if ($use == 'literal') {
  752. $type_str = '';
  753. } else if (isset($type) && isset($type_prefix)) {
  754. $type_str = " xsi:type=\"$type_prefix:$type\"";
  755. } else {
  756. $type_str = " xsi:type=\"SOAP-ENC:Array\" SOAP-ENC:arrayType=\"xsd:anyType[0]\"";
  757. }
  758. }
  759. // TODO: for array in literal, there is no wrapper here
  760. $xml = "<$name$xmlns$type_str$atts>".$xml."</$name>";
  761. } else {
  762. // got a struct
  763. $this->debug("serialize_val: serialize struct");
  764. if(isset($type) && isset($type_prefix)){
  765. $type_str = " xsi:type=\"$type_prefix:$type\"";
  766. } else {
  767. $type_str = '';
  768. }
  769. if ($use == 'literal') {
  770. $xml .= "<$name$xmlns$atts>";
  771. } else {
  772. $xml .= "<$name$xmlns$type_str$atts>";
  773. }
  774. foreach($val as $k => $v){
  775. // Apache Map
  776. if ($type == 'Map' && $type_ns == 'http://xml.apache.org/xml-soap') {
  777. $xml .= '<item>';
  778. $xml .= $this->serialize_val($k,'key',false,false,false,false,$use);
  779. $xml .= $this->serialize_val($v,'value',false,false,false,false,$use);
  780. $xml .= '</item>';
  781. } else {
  782. $xml .= $this->serialize_val($v,$k,false,false,false,false,$use);
  783. }
  784. }
  785. $xml .= "</$name>";
  786. }
  787. break;
  788. default:
  789. $this->debug("serialize_val: serialize unknown");
  790. $xml .= 'not detected, got '.gettype($val).' for '.$val;
  791. break;
  792. }
  793. $this->debug("serialize_val returning $xml");
  794. return $xml;
  795. }
  796. /**
  797. * serializes a message
  798. *
  799. * @param string $body the XML of the SOAP body
  800. * @param mixed $headers optional string of XML with SOAP header content, or array of soapval objects for SOAP headers, or associative array
  801. * @param array $namespaces optional the namespaces used in generating the body and headers
  802. * @param string $style optional (rpc|document)
  803. * @param string $use optional (encoded|literal)
  804. * @param string $encodingStyle optional (usually 'http://schemas.xmlsoap.org/soap/encoding/' for encoded)
  805. * @return string the message
  806. * @access public
  807. */
  808. function serializeEnvelope($body,$headers=false,$namespaces=array(),$style='rpc',$use='encoded',$encodingStyle='http://schemas.xmlsoap.org/soap/encoding/'){
  809. // TODO: add an option to automatically run utf8_encode on $body and $headers
  810. // if $this->soap_defencoding is UTF-8. Not doing this automatically allows
  811. // one to send arbitrary UTF-8 characters, not just characters that map to ISO-8859-1
  812. $this->debug("In serializeEnvelope length=" . strlen($body) . " body (max 1000 characters)=" . substr($body, 0, 1000) . " style=$style use=$use encodingStyle=$encodingStyle");
  813. $this->debug("headers:");
  814. $this->appendDebug($this->varDump($headers));
  815. $this->debug("namespaces:");
  816. $this->appendDebug($this->varDump($namespaces));
  817. // serialize namespaces
  818. $ns_string = '';
  819. foreach(array_merge($this->namespaces,$namespaces) as $k => $v){
  820. $ns_string .= " xmlns:$k=\"$v\"";
  821. }
  822. if($encodingStyle) {
  823. $ns_string = " SOAP-ENV:encodingStyle=\"$encodingStyle\"$ns_string";
  824. }
  825. // serialize headers
  826. if($headers){
  827. if (is_array($headers)) {
  828. $xml = '';
  829. foreach ($headers as $k => $v) {
  830. if (is_object($v) && get_class($v) == 'soapval') {
  831. $xml .= $this->serialize_val($v, false, false, false, false, false, $use);
  832. } else {
  833. $xml .= $this->serialize_val($v, $k, false, false, false, false, $use);
  834. }
  835. }
  836. $headers = $xml;
  837. $this->debug("In serializeEnvelope, serialized array of headers to $headers");
  838. }
  839. $headers = "<SOAP-ENV:Header>".$headers."</SOAP-ENV:Header>";
  840. }
  841. // serialize envelope
  842. return
  843. '<?xml version="1.0" encoding="'.$this->soap_defencoding .'"?'.">".
  844. '<SOAP-ENV:Envelope'.$ns_string.">".
  845. $headers.
  846. "<SOAP-ENV:Body>".
  847. $body.
  848. "</SOAP-ENV:Body>".
  849. "</SOAP-ENV:Envelope>";
  850. }
  851. /**
  852. * formats a string to be inserted into an HTML stream
  853. *
  854. * @param string $str The string to format
  855. * @return string The formatted string
  856. * @access public
  857. * @deprecated
  858. */
  859. function formatDump($str){
  860. $str = htmlspecialchars($str);
  861. return nl2br($str);
  862. }
  863. /**
  864. * contracts (changes namespace to prefix) a qualified name
  865. *
  866. * @param string $qname qname
  867. * @return string contracted qname
  868. * @access private
  869. */
  870. function contractQname($qname){
  871. // get element namespace
  872. //$this->xdebug("Contract $qname");
  873. if (strrpos($qname, ':')) {
  874. // get unqualified name
  875. $name = substr($qname, strrpos($qname, ':') + 1);
  876. // get ns
  877. $ns = substr($qname, 0, strrpos($qname, ':'));
  878. $p = $this->getPrefixFromNamespace($ns);
  879. if ($p) {
  880. return $p . ':' . $name;
  881. }
  882. return $qname;
  883. } else {
  884. return $qname;
  885. }
  886. }
  887. /**
  888. * expands (changes prefix to namespace) a qualified name
  889. *
  890. * @param string $qname qname
  891. * @return string expanded qname
  892. * @access private
  893. */
  894. function expandQname($qname){
  895. // get element prefix
  896. if(strpos($qname,':') && !preg_match('/^http:\/\//',$qname)){
  897. // get unqualified name
  898. $name = substr(strstr($qname,':'),1);
  899. // get ns prefix
  900. $prefix = substr($qname,0,strpos($qname,':'));
  901. if(isset($this->namespaces[$prefix])){
  902. return $this->namespaces[$prefix].':'.$name;
  903. } else {
  904. return $qname;
  905. }
  906. } else {
  907. return $qname;
  908. }
  909. }
  910. /**
  911. * returns the local part of a prefixed string
  912. * returns the original string, if not prefixed
  913. *
  914. * @param string $str The prefixed string
  915. * @return string The local part
  916. * @access public
  917. */
  918. function getLocalPart($str){
  919. if($sstr = strrchr($str,':')){
  920. // get unqualified name
  921. return substr( $sstr, 1 );
  922. } else {
  923. return $str;
  924. }
  925. }
  926. /**
  927. * returns the prefix part of a prefixed string
  928. * returns false, if not prefixed
  929. *
  930. * @param string $str The prefixed string
  931. * @return mixed The prefix or false if there is no prefix
  932. * @access public
  933. */
  934. function getPrefix($str){
  935. if($pos = strrpos($str,':')){
  936. // get prefix
  937. return substr($str,0,$pos);
  938. }
  939. return false;
  940. }
  941. /**
  942. * pass it a prefix, it returns a namespace
  943. *
  944. * @param string $prefix The prefix
  945. * @return mixed The namespace, false if no namespace has the specified prefix
  946. * @access public
  947. */
  948. function getNamespaceFromPrefix($prefix){
  949. if (isset($this->namespaces[$prefix])) {
  950. return $this->namespaces[$prefix];
  951. }
  952. //$this->setError("No namespace registered for prefix '$prefix'");
  953. return false;
  954. }
  955. /**
  956. * returns the prefix for a given namespace (or prefix)
  957. * or false if no prefixes registered for the given namespace
  958. *
  959. * @param string $ns The namespace
  960. * @return mixed The prefix, false if the namespace has no prefixes
  961. * @access public
  962. */
  963. function getPrefixFromNamespace($ns) {
  964. foreach ($this->namespaces as $p => $n) {
  965. if ($ns == $n || $ns == $p) {
  966. $this->usedNamespaces[$p] = $n;
  967. return $p;
  968. }
  969. }
  970. return false;
  971. }
  972. /**
  973. * returns the time in ODBC canonical form with microseconds
  974. *
  975. * @return string The time in ODBC canonical form with microseconds
  976. * @access public
  977. */
  978. function getmicrotime() {
  979. if (function_exists('gettimeofday')) {
  980. $tod = gettimeofday();
  981. $sec = $tod['sec'];
  982. $usec = $tod['usec'];
  983. } else {
  984. $sec = time();
  985. $usec = 0;
  986. }
  987. return strftime('%Y-%m-%d %H:%M:%S', $sec) . '.' . sprintf('%06d', $usec);
  988. }
  989. /**
  990. * Returns a string with the output of var_dump
  991. *
  992. * @param mixed $data The variable to var_dump
  993. * @return string The output of var_dump
  994. * @access public
  995. */
  996. function varDump($data) {
  997. if ($this->debugLevel <= 0) {
  998. return '';
  999. }
  1000. ob_start();
  1001. var_dump($data);
  1002. $ret_val = ob_get_contents();
  1003. ob_end_clean();
  1004. return $ret_val;
  1005. }
  1006. /**
  1007. * represents the object as a string
  1008. *
  1009. * @return string
  1010. * @access public
  1011. */
  1012. function __toString() {
  1013. return $this->varDump($this);
  1014. }
  1015. }
  1016. // XML Schema Datatype Helper Functions
  1017. //xsd:dateTime helpers
  1018. /**
  1019. * convert unix timestamp to ISO 8601 compliant date string
  1020. *
  1021. * @param int $timestamp Unix time stamp
  1022. * @param boolean $utc Whether the time stamp is UTC or local
  1023. * @return mixed ISO 8601 date string or false
  1024. * @access public
  1025. */
  1026. function timestamp_to_iso8601($timestamp,$utc=true){
  1027. $datestr = date('Y-m-d\TH:i:sO',$timestamp);
  1028. $pos = strrpos($datestr, "+");
  1029. if ($pos === FALSE) {
  1030. $pos = strrpos($datestr, "-");
  1031. }
  1032. if ($pos !== FALSE) {
  1033. if (strlen($datestr) == $pos + 5) {
  1034. $datestr = substr($datestr, 0, $pos + 3) . ':' . substr($datestr, -2);
  1035. }
  1036. }
  1037. if($utc){
  1038. $pattern = '/'.
  1039. '([0-9]{4})-'. // centuries & years CCYY-
  1040. '([0-9]{2})-'. // months MM-
  1041. '([0-9]{2})'. // days DD
  1042. 'T'. // separator T
  1043. '([0-9]{2}):'. // hours hh:
  1044. '([0-9]{2}):'. // minutes mm:
  1045. '([0-9]{2})(\.[0-9]*)?'. // seconds ss.ss...
  1046. '(Z|[+\-][0-9]{2}:?[0-9]{2})?'. // Z to indicate UTC, -/+HH:MM:SS.SS... for local tz's
  1047. '/';
  1048. if(preg_match($pattern,$datestr,$regs)){
  1049. return sprintf('%04d-%02d-%02dT%02d:%02d:%02dZ',$regs[1],$regs[2],$regs[3],$regs[4],$regs[5],$regs[6]);
  1050. }
  1051. return false;
  1052. } else {
  1053. return $datestr;
  1054. }
  1055. }
  1056. /**
  1057. * convert ISO 8601 compliant date string to unix timestamp
  1058. *
  1059. * @param string $datestr ISO 8601 compliant date string
  1060. * @return mixed Unix timestamp (int) or false
  1061. * @access public
  1062. */
  1063. function iso8601_to_timestamp($datestr){
  1064. $pattern = '/'.
  1065. '([0-9]{4})-'. // centuries & years CCYY-
  1066. '([0-9]{2})-'. // months MM-
  1067. '([0-9]{2})'. // days DD
  1068. 'T'. // separator T
  1069. '([0-9]{2}):'. // hours hh:
  1070. '([0-9]{2}):'. // minutes mm:
  1071. '([0-9]{2})(\.[0-9]+)?'. // seconds ss.ss...
  1072. '(Z|[+\-][0-9]{2}:?[0-9]{2})?'. // Z to indicate UTC, -/+HH:MM:SS.SS... for local tz's
  1073. '/';
  1074. if(preg_match($pattern,$datestr,$regs)){
  1075. // not utc
  1076. if($regs[8] != 'Z'){
  1077. $op = substr($regs[8],0,1);
  1078. $h = substr($regs[8],1,2);
  1079. $m = substr($regs[8],strlen($regs[8])-2,2);
  1080. if($op == '-'){
  1081. $regs[4] = $regs[4] + $h;
  1082. $regs[5] = $regs[5] + $m;
  1083. } elseif($op == '+'){
  1084. $regs[4] = $regs[4] - $h;
  1085. $regs[5] = $regs[5] - $m;
  1086. }
  1087. }
  1088. return gmmktime($regs[4], $regs[5], $regs[6], $regs[2], $regs[3], $regs[1]);
  1089. // return strtotime("$regs[1]-$regs[2]-$regs[3] $regs[4]:$regs[5]:$regs[6]Z");
  1090. } else {
  1091. return false;
  1092. }
  1093. }
  1094. /**
  1095. * sleeps some number of microseconds
  1096. *
  1097. * @param string $usec the number of microseconds to sleep
  1098. * @access public
  1099. * @deprecated
  1100. */
  1101. function usleepWindows($usec)
  1102. {
  1103. $start = gettimeofday();
  1104. do
  1105. {
  1106. $stop = gettimeofday();
  1107. $timePassed = 1000000 * ($stop['sec'] - $start['sec'])
  1108. + $stop['usec'] - $start['usec'];
  1109. }
  1110. while ($timePassed < $usec);
  1111. }
  1112. ?><?php
  1113. /*
  1114. Modification information for LGPL compliance
  1115. r58622 - 2010-10-22 18:18:59 -0700 (Fri, 22 Oct 2010) - engsvnbuild - Author: lam <lam@198.18.142.201>
  1116. bug 40066
  1117. r58361 - 2010-09-29 16:59:02 -0700 (Wed, 29 Sep 2010) - kjing - Author: Jenny Gonsalves <jenny@sugarcrm.com>
  1118. Merging with maint_6_0_1 (svn merge -r 58250:58342)
  1119. r57813 - 2010-08-19 10:34:44 -0700 (Thu, 19 Aug 2010) - kjing - Author: John Mertic <jmertic@sugarcrm.com>
  1120. Bug 39085 - When loading the opposite search panel via ajax on the ListViews, call the index action instead of the ListView action to avoid touching pre-MVC code by accident.
  1121. r57707 - 2010-08-10 12:26:13 -0700 (Tue, 10 Aug 2010) - kjing - Author: Stanislav Malyshev <smalyshev@gmail.com>
  1122. fix SOAP calls with no parameters
  1123. r56990 - 2010-06-16 13:05:36 -0700 (Wed, 16 Jun 2010) - kjing - snapshot "Mango" svn branch to a new one for GitHub sync
  1124. r56989 - 2010-06-16 13:01:33 -0700 (Wed, 16 Jun 2010) - kjing - defunt "Mango" svn dev branch before github cutover
  1125. r55980 - 2010-04-19 13:31:28 -0700 (Mon, 19 Apr 2010) - kjing - create Mango (6.1) based on windex
  1126. r51719 - 2009-10-22 10:18:00 -0700 (Thu, 22 Oct 2009) - mitani - Converted to Build 3 tags and updated the build system
  1127. r51634 - 2009-10-19 13:32:22 -0700 (Mon, 19 Oct 2009) - mitani - Windex is the branch for Sugar Sales 1.0 development
  1128. r51508 - 2009-10-14 07:40:23 -0700 (Wed, 14 Oct 2009) - jmertic - More fallout fixes from the PHP 5.3 ereg to preg changes.
  1129. r51455 - 2009-10-13 07:56:48 -0700 (Tue, 13 Oct 2009) - jmertic - Bug 33202 - Enable install of SugarCRM on PHP 5.3.0, asserting that the minimum supported version is PHP 5.2.x.
  1130. r51443 - 2009-10-12 13:34:36 -0700 (Mon, 12 Oct 2009) - jmertic - Bug 33332 - Made application PHP 5.3 compliant with E_DEPRECATED warnings on by:
  1131. - Changing all ereg function to either preg or simple string based ones
  1132. - No more references to magic quotes.
  1133. - Change all the session_unregister() functions to just unset() the correct session variable instead.
  1134. r50375 - 2009-08-24 18:07:43 -0700 (Mon, 24 Aug 2009) - dwong - branch kobe2 from tokyo r50372
  1135. r45763 - 2009-04-01 12:16:18 -0700 (Wed, 01 Apr 2009) - majed - Removed half of the require_once and include_onces in the product that were redundant or could be handled easily by the auto loader
  1136. r45680 - 2009-03-30 14:34:35 -0700 (Mon, 30 Mar 2009) - Samir Gandhi - modifeid serializeSchema to generate WS-I compliant WSDL
  1137. r42807 - 2008-12-29 11:16:59 -0800 (Mon, 29 Dec 2008) - dwong - Branch from trunk/sugarcrm r42806 to branches/tokyo/sugarcrm
  1138. r42645 - 2008-12-18 13:41:08 -0800 (Thu, 18 Dec 2008) - awu - merging maint_5_2_0 rev41336:HEAD to trunk
  1139. r41647 - 2008-11-11 17:44:30 -0800 (Tue, 11 Nov 2008) - majed - Fixes a few bugs
  1140. r41596 - 2008-11-10 19:20:04 -0800 (Mon, 10 Nov 2008) - Samir Gandhi - modified to set $method in the code
  1141. r41558 - 2008-11-10 14:35:34 -0800 (Mon, 10 Nov 2008) - majed - changes nusoap to allow for registering classes
  1142. r39619 - 2008-09-09 13:41:34 -0700 (Tue, 09 Sep 2008) - jmertic - Bug 24827 - Remove all instances where we return a new object and assign it by reference, since this is deprecated in PHP 5 and emits E_DEPRECATED errors in PHP 5.3.
  1143. Touched:
  1144. - data/SugarBean.php
  1145. - include/domit/php_http_client_generic.php
  1146. - include/domit/php_http_connector.php
  1147. - include/domit/testing_domit.php
  1148. - include/domit/xml_domit_getelementsbypath.php
  1149. - include/domit/xml_domit_lite_parser.php
  1150. - include/domit/xml_domit_nodemaps.php
  1151. - include/domit/xml_domit_parser.php
  1152. - include/domit/xml_domit_shared.php
  1153. - include/generic/SugarWidgets/SugarWidgetField.php
  1154. - include/generic/SugarWidgets/SugarWidgetReportField.php
  1155. - include/ListView/ProcessView.php
  1156. - include/nusoap/class.soapclient.php
  1157. - include/nusoap/nusoap.php
  1158. - include/nusoap/nusoapmime.php
  1159. - include/Pear/HTML_Safe/Safe.php
  1160. - include/Pear/XML_HTMLSax3/HTMLSax3.php
  1161. - modules/Administration/RebuildWorkFlow.php
  1162. - modules/Expressions/RelateSelector.php
  1163. - modules/Reports/templates/templates_reports.php
  1164. - modules/WorkFlow/Delete.php
  1165. - modules/WorkFlow/Save.php
  1166. - modules/WorkFlow/SaveSequence.php
  1167. - modules/WorkFlow/WorkFlow.php
  1168. - modules/WorkFlowActionShells/CreateStep1.php
  1169. - modules/WorkFlowActionShells/CreateStep2.php
  1170. - modules/WorkFlowActionShells/Save.php
  1171. - modules/WorkFlowActionShells/WorkFlowActionShell.php
  1172. - modules/WorkFlowAlerts/Save.php
  1173. - modules/WorkFlowAlerts/WorkFlowAlert.php
  1174. - modules/WorkFlowAlertShells/DetailView.php
  1175. - modules/WorkFlowAlertShells/WorkFlowAlertShell.php
  1176. - modules/WorkFlowTriggerShells/CreateStep1.php
  1177. - modules/WorkFlowTriggerShells/CreateStepFilter.php
  1178. - modules/WorkFlowTriggerShells/SaveFilter.php
  1179. - modules/WorkFlowTriggerShells/WorkFlowTriggerShell.php
  1180. - soap/SoapHelperFunctions.php
  1181. - test/modules/DynamicFields/DynamicFields_Bug24095_test.php
  1182. - test/simpletest/browser.php
  1183. - test/simpletest/default_reporter.php
  1184. - test/simpletest/detached.php
  1185. - test/simpletest/eclipse.php
  1186. - test/simpletest/expectation.php
  1187. - test/simpletest/extensions/pear_test_case.php
  1188. - test/simpletest/form.php
  1189. - test/simpletest/http.php
  1190. - test/simpletest/mock_objects.php
  1191. - test/simpletest/page.php
  1192. - test/simpletest/parser.php
  1193. - test/simpletest/remote.php
  1194. - test/simpletest/shell_tester.php
  1195. - test/simpletest/simple_test.php
  1196. - test/simpletest/simpletest.php
  1197. - test/simpletest/test/acceptance_test.php
  1198. - test/simpletest/test/adapter_test.php
  1199. - test/simpletest/test/authentication_test.php
  1200. - test/simpletest/test/browser_test.php
  1201. - test/simpletest/test/collector_test.php
  1202. - test/simpletest/test/compatibility_test.php
  1203. - test/simpletest/test/detached_test.php
  1204. - test/simpletest/test/eclipse_test.php
  1205. - test/simpletest/test/encoding_test.php
  1206. - test/simpletest/test/errors_test.php
  1207. - test/simpletest/test/expectation_test.php
  1208. - test/simpletest/test/form_test.php
  1209. - test/simpletest/test/frames_test.php
  1210. - test/simpletest/test/http_test.php
  1211. - test/simpletest/test/live_test.php
  1212. - test/simpletest/test/mock_objects_test.php
  1213. - test/simpletest/test/page_test.php
  1214. - test/simpletest/test/parse_error_test.php
  1215. - test/simpletest/test/parser_test.php
  1216. - test/simpletest/test/remote_test.php
  1217. - test/simpletest/test/shell_test.php
  1218. - test/simpletest/test/shell_tester_test.php
  1219. - test/simpletest/test/simpletest_test.php
  1220. - test/simpletest/test/site/page_request.php
  1221. - test/simpletest/test/tag_test.php
  1222. - test/simpletest/test/unit_tester_test.php
  1223. - test/simpletest/test/user_agent_test.php
  1224. - test/simpletest/test/visual_test.php
  1225. - test/simpletest/test/xml_test.php
  1226. - test/simpletest/test_case.php
  1227. - test/simpletest/ui/array_reporter/test.php
  1228. - test/simpletest/ui/recorder/test.php
  1229. - test/simpletest/unit_tester.php
  1230. - test/simpletest/url.php
  1231. - test/simpletest/user_agent.php
  1232. - test/simpletest/web_tester.php
  1233. - test/spikephpcoverage/src/PEAR.php
  1234. - test/spikephpcoverage/src/util/Utility.php
  1235. - test/spikephpcoverage/src/XML/Parser.php
  1236. - test/spikephpcoverage/src/XML/Parser/Simple.php
  1237. - test/test_utilities/SugarTest_SimpleBrowser.php
  1238. r38362 - 2008-07-28 14:06:59 -0700 (Mon, 28 Jul 2008) - roger - bug: 23897. Using print_r when using the debug statement in nusoap will print out the statements to the screen if the call is coming from the UI.
  1239. r38300 - 2008-07-25 13:33:43 -0700 (Fri, 25 Jul 2008) - Samir Gandhi - put the debug in parseresponse function
  1240. r38293 - 2008-07-25 12:32:34 -0700 (Fri, 25 Jul 2008) - Samir Gandhi - to put all the debug statements return value in the call function
  1241. r36824 - 2008-06-18 09:26:11 -0700 (Wed, 18 Jun 2008) - roger - bug: 21832
  1242. r26422 - 2007-09-05 17:29:12 -0700 (Wed, 05 Sep 2007) - majed - migrate from beta 1 to trunk
  1243. r15787 - 2006-08-10 10:14:41 -0700 (Thu, 10 Aug 2006) - roger - RRS: bug 7961
  1244. r14701 - 2006-07-17 13:37:26 -0700 (Mon, 17 Jul 2006) - roger - RRS: bug 5801
  1245. r13782 - 2006-06-06 10:58:55 -0700 (Tue, 06 Jun 2006) - majed - changes entry point code
  1246. r11466 - 2006-02-01 15:49:47 -0800 (Wed, 01 Feb 2006) - jacob - Adding extra !empty check to get around a PHP warning.
  1247. r11115 - 2006-01-17 14:54:45 -0800 (Tue, 17 Jan 2006) - majed - add entry point validation
  1248. r10585 - 2005-12-13 14:42:26 -0800 (Tue, 13 Dec 2005) - majed - adds new license mechanisim
  1249. r10170 - 2005-12-05 18:37:46 -0800 (Mon, 05 Dec 2005) - majed - fixes various issues
  1250. r8999 - 2005-11-04 05:26:49 -0800 (Fri, 04 Nov 2005) - roger - When nusoap was upgraded we had an issue with the user's default language not being populated during a soap request. I determined the reason this was happening and have checked in the corresponding change to nusoap.
  1251. r8991 - 2005-11-03 19:07:25 -0800 (Thu, 03 Nov 2005) - majed - fixes nusoap issue
  1252. r8846 - 2005-10-31 11:01:12 -0800 (Mon, 31 Oct 2005) - majed - new version of nusoap
  1253. r7905 - 2005-09-21 19:12:57 -0700 (Wed, 21 Sep 2005) - majed - restores old nusoap pre & with a few fixes
  1254. r7861 - 2005-09-20 15:40:25 -0700 (Tue, 20 Sep 2005) - majed - & fix for 3.5.1
  1255. r7452 - 2005-08-17 11:32:34 -0700 (Wed, 17 Aug 2005) - majed - changes soap to nusoap
  1256. r5820 - 2005-06-21 14:22:24 -0700 (Tue, 21 Jun 2005) - majed - fixes issues with nusoap and with custom fields
  1257. r5462 - 2005-05-25 13:50:11 -0700 (Wed, 25 May 2005) - majed - upgraded nusoap to .6.9
  1258. r5104 - 2005-05-04 15:33:41 -0700 (Wed, 04 May 2005) - majed - gets rid of HTTP_GET_VARS and what not which has been deprecated
  1259. r573 - 2004-09-04 13:03:32 -0700 (Sat, 04 Sep 2004) - sugarclint - undoing copyrights added in inadvertantly. --clint
  1260. r546 - 2004-09-03 11:49:38 -0700 (Fri, 03 Sep 2004) - sugarmsi - removed echo count
  1261. r354 - 2004-08-02 23:00:37 -0700 (Mon, 02 Aug 2004) - sugarjacob - Adding Soap
  1262. */
  1263. /**
  1264. * Contains information for a SOAP fault.
  1265. * Mainly used for returning faults from deployed functions
  1266. * in a server instance.
  1267. * @author Dietrich Ayala <dietrich@ganx4.com>
  1268. * @access public
  1269. */
  1270. class nusoap_fault extends nusoap_base {
  1271. /**
  1272. * The fault code (client|server)
  1273. * @var string
  1274. * @access private
  1275. */
  1276. var $faultcode;
  1277. /**
  1278. * The fault actor
  1279. * @var string
  1280. * @access private
  1281. */
  1282. var $faultactor;
  1283. /**
  1284. * The fault string, a description of the fault
  1285. * @var string
  1286. * @access private
  1287. */
  1288. var $faultstring;
  1289. /**
  1290. * The fault detail, typically a string or array of string
  1291. * @var mixed
  1292. * @access private
  1293. */
  1294. var $faultdetail;
  1295. /**
  1296. * constructor
  1297. *
  1298. * @param string $faultcode (SOAP-ENV:Client | SOAP-ENV:Server)
  1299. * @param string $faultactor only used when msg routed between multiple actors
  1300. * @param string $faultstring human readable error message
  1301. * @param mixed $faultdetail detail, typically a string or array of string
  1302. */
  1303. function nusoap_fault($faultcode,$faultactor='',$faultstring='',$faultdetail=''){
  1304. parent::nusoap_base();
  1305. $this->faultcode = $faultcode;
  1306. $this->faultactor = $faultactor;
  1307. $this->faultstring = $faultstring;
  1308. $this->faultdetail = $faultdetail;
  1309. }
  1310. /**
  1311. * serialize a fault
  1312. *
  1313. * @return string The serialization of the fault instance.
  1314. * @access public
  1315. */
  1316. function serialize(){
  1317. $ns_string = '';
  1318. foreach($this->namespaces as $k => $v){
  1319. $ns_string .= "\n xmlns:$k=\"$v\"";
  1320. }
  1321. $return_msg =
  1322. '<?xml version="1.0" encoding="'.$this->soap_defencoding.'"?>'.
  1323. '<SOAP-ENV:Envelope SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"'.$ns_string.">\n".
  1324. '<SOAP-ENV:Body>'.
  1325. '<SOAP-ENV:Fault>'.
  1326. $this->serialize_val($this->faultcode, 'faultcode').
  1327. $this->serialize_val($this->faultactor, 'faultactor').
  1328. $this->serialize_val($this->faultstring, 'faultstring').
  1329. $this->serialize_val($this->faultdetail, 'detail').
  1330. '</SOAP-ENV:Fault>'.
  1331. '</SOAP-ENV:Body>'.
  1332. '</SOAP-ENV:Envelope>';
  1333. return $return_msg;
  1334. }
  1335. }
  1336. /**
  1337. * Backward compatibility
  1338. */
  1339. class soap_fault extends nusoap_fault {
  1340. }
  1341. ?><?php
  1342. /*
  1343. Modification information for LGPL compliance
  1344. r58622 - 2010-10-22 18:18:59 -0700 (Fri, 22 Oct 2010) - engsvnbuild - Author: lam <lam@198.18.142.201>
  1345. bug 40066
  1346. r58361 - 2010-09-29 16:59:02 -0700 (Wed, 29 Sep 2010) - kjing - Author: Jenny Gonsalves <jenny@sugarcrm.com>
  1347. Merging with maint_6_0_1 (svn merge -r 58250:58342)
  1348. r57813 - 2010-08-19 10:34:44 -0700 (Thu, 19 Aug 2010) - kjing - Author: John Mertic <jmertic@sugarcrm.com>
  1349. Bug 39085 - When loading the opposite search panel via ajax on the ListViews, call the index action instead of the ListView action to avoid touching pre-MVC code by accident.
  1350. r57707 - 2010-08-10 12:26:13 -0700 (Tue, 10 Aug 2010) - kjing - Author: Stanislav Malyshev <smalyshev@gmail.com>
  1351. fix SOAP calls with no parameters
  1352. r56990 - 2010-06-16 13:05:36 -0700 (Wed, 16 Jun 2010) - kjing - snapshot "Mango" svn branch to a new one for GitHub sync
  1353. r56989 - 2010-06-16 13:01:33 -0700 (Wed, 16 Jun 2010) - kjing - defunt "Mango" svn dev branch before github cutover
  1354. r55980 - 2010-04-19 13:31:28 -0700 (Mon, 19 Apr 2010) - kjing - create Mango (6.1) based on windex
  1355. r51719 - 2009-10-22 10:18:00 -0700 (Thu, 22 Oct 2009) - mitani - Converted to Build 3 tags and updated the build system
  1356. r51634 - 2009-10-19 13:32:22 -0700 (Mon, 19 Oct 2009) - mitani - Windex is the branch for Sugar Sales 1.0 development
  1357. r51508 - 2009-10-14 07:40:23 -0700 (Wed, 14 Oct 2009) - jmertic - More fallout fixes from the PHP 5.3 ereg to preg changes.
  1358. r51455 - 2009-10-13 07:56:48 -0700 (Tue, 13 Oct 2009) - jmertic - Bug 33202 - Enable install of SugarCRM on PHP 5.3.0, asserting that the minimum supported version is PHP 5.2.x.
  1359. r51443 - 2009-10-12 13:34:36 -0700 (Mon, 12 Oct 2009) - jmertic - Bug 33332 - Made application PHP 5.3 compliant with E_DEPRECATED warnings on by:
  1360. - Changing all ereg function to either preg or simple string based ones
  1361. - No more references to magic quotes.
  1362. - Change all the session_unregister() functions to just unset() the correct session variable instead.
  1363. r50375 - 2009-08-24 18:07:43 -0700 (Mon, 24 Aug 2009) - dwong - branch kobe2 from tokyo r50372
  1364. r45763 - 2009-04-01 12:16:18 -0700 (Wed, 01 Apr 2009) - majed - Removed half of the require_once and include_onces in the product that were redundant or could be handled easily by the auto loader
  1365. r45680 - 2009-03-30 14:34:35 -0700 (Mon, 30 Mar 2009) - Samir Gandhi - modifeid serializeSchema to generate WS-I compliant WSDL
  1366. r42807 - 2008-12-29 11:16:59 -0800 (Mon, 29 Dec 2008) - dwong - Branch from trunk/sugarcrm r42806 to branches/tokyo/sugarcrm
  1367. r42645 - 2008-12-18 13:41:08 -0800 (Thu, 18 Dec 2008) - awu - merging maint_5_2_0 rev41336:HEAD to trunk
  1368. r41647 - 2008-11-11 17:44:30 -0800 (Tue, 11 Nov 2008) - majed - Fixes a few bugs
  1369. r41596 - 2008-11-10 19:20:04 -0800 (Mon, 10 Nov 2008) - Samir Gandhi - modified to set $method in the code
  1370. r41558 - 2008-11-10 14:35:34 -0800 (Mon, 10 Nov 2008) - majed - changes nusoap to allow for registering classes
  1371. r39619 - 2008-09-09 13:41:34 -0700 (Tue, 09 Sep 2008) - jmertic - Bug 24827 - Remove all instances where we return a new object and assign it by reference, since this is deprecated in PHP 5 and emits E_DEPRECATED errors in PHP 5.3.
  1372. Touched:
  1373. - data/SugarBean.php
  1374. - include/domit/php_http_client_generic.php
  1375. - include/domit/php_http_connector.php
  1376. - include/domit/testing_domit.php
  1377. - include/domit/xml_domit_getelementsbypath.php
  1378. - include/domit/xml_domit_lite_parser.php
  1379. - include/domit/xml_domit_nodemaps.php
  1380. - include/domit/xml_domit_parser.php
  1381. - include/domit/xml_domit_shared.php
  1382. - include/generic/SugarWidgets/SugarWidgetField.php
  1383. - include/generic/SugarWidgets/SugarWidgetReportField.php
  1384. - include/ListView/ProcessView.php
  1385. - include/nusoap/class.soapclient.php
  1386. - include/nusoap/nusoap.php
  1387. - include/nusoap/nusoapmime.php
  1388. - include/Pear/HTML_Safe/Safe.php
  1389. - include/Pear/XML_HTMLSax3/HTMLSax3.php
  1390. - modules/Administration/RebuildWorkFlow.php
  1391. - modules/Expressions/RelateSelector.php
  1392. - modules/Reports/templates/templates_reports.php
  1393. - modules/WorkFlow/Delete.php
  1394. - modules/WorkFlow/Save.php
  1395. - modules/WorkFlow/SaveSequence.php
  1396. - modules/WorkFlow/WorkFlow.php
  1397. - modules/WorkFlowActionShells/CreateStep1.php
  1398. - modules/WorkFlowActionShells/CreateStep2.php
  1399. - modules/WorkFlowActionShells/Save.php
  1400. - modules/WorkFlowActionShells/WorkFlowActionShell.php
  1401. - modules/WorkFlowAlerts/Save.php
  1402. - modules/WorkFlowAlerts/WorkFlowAlert.php
  1403. - modules/WorkFlowAlertShells/DetailView.php
  1404. - modules/WorkFlowAlertShells/WorkFlowAlertShell.php
  1405. - modules/WorkFlowTriggerShells/CreateStep1.php
  1406. - modules/WorkFlowTriggerShells/CreateStepFilter.php
  1407. - modules/WorkFlowTriggerShells/SaveFilter.php
  1408. - modules/WorkFlowTriggerShells/WorkFlowTriggerShell.php
  1409. - soap/SoapHelperFunctions.php
  1410. - test/modules/DynamicFields/DynamicFields_Bug24095_test.php
  1411. - test/simpletest/browser.php
  1412. - test/simpletest/default_reporter.php
  1413. - test/simpletest/detached.php
  1414. - test/simpletest/eclipse.php
  1415. - test/simpletest/expectation.php
  1416. - test/simpletest/extensions/pear_test_case.php
  1417. - test/simpletest/form.php
  1418. - test/simpletest/http.php
  1419. - test/simpletest/mock_objects.php
  1420. - test/simpletest/page.php
  1421. - test/simpletest/parser.php
  1422. - test/simpletest/remote.php
  1423. - test/simpletest/shell_tester.php
  1424. - test/simpletest/simple_test.php
  1425. - test/simpletest/simpletest.php
  1426. - test/simpletest/test/acceptance_test.php
  1427. - test/simpletest/test/adapter_test.php
  1428. - test/simpletest/test/authentication_test.php
  1429. - test/simpletest/test/browser_test.php
  1430. - test/simpletest/test/collector_test.php
  1431. - test/simpletest/test/compatibility_test.php
  1432. - test/simpletest/test/detached_test.php
  1433. - test/simpletest/test/eclipse_test.php
  1434. - test/simpletest/test/encoding_test.php
  1435. - test/simpletest/test/errors_test.php
  1436. - test/simpletest/test/expectation_test.php
  1437. - test/simpletest/test/form_test.php
  1438. - test/simpletest/test/frames_test.php
  1439. - test/simpletest/test/http_test.php
  1440. - test/simpletest/test/live_test.php
  1441. - test/simpletest/test/mock_objects_test.php
  1442. - test/simpletest/test/page_test.php
  1443. - test/simpletest/test/parse_error_test.php
  1444. - test/simpletest/test/parser_test.php
  1445. - test/simpletest/test/remote_test.php
  1446. - test/simpletest/test/shell_test.php
  1447. - test/simpletest/test/shell_tester_test.php
  1448. - test/simpletest/test/simpletest_test.php
  1449. - test/simpletest/test/site/page_request.php
  1450. - test/simpletest/test/tag_test.php
  1451. - test/simpletest/test/unit_tester_test.php
  1452. - test/simpletest/test/user_agent_test.php
  1453. - test/simpletest/test/visual_test.php
  1454. - test/simpletest/test/xml_test.php
  1455. - test/simpletest/test_case.php
  1456. - test/simpletest/ui/array_reporter/test.php
  1457. - test/simpletest/ui/recorder/test.php
  1458. - test/simpletest/unit_tester.php
  1459. - test/simpletest/url.php
  1460. - test/simpletest/user_agent.php
  1461. - test/simpletest/web_tester.php
  1462. - test/spikephpcoverage/src/PEAR.php
  1463. - test/spikephpcoverage/src/util/Utility.php
  1464. - test/spikephpcoverage/src/XML/Parser.php
  1465. - test/spikephpcoverage/src/XML/Parser/Simple.php
  1466. - test/test_utilities/SugarTest_SimpleBrowser.php
  1467. r38362 - 2008-07-28 14:06:59 -0700 (Mon, 28 Jul 2008) - roger - bug: 23897. Using print_r when using the debug statement in nusoap will print out the statements to the screen if the call is coming from the UI.
  1468. r38300 - 2008-07-25 13:33:43 -0700 (Fri, 25 Jul 2008) - Samir Gandhi - put the debug in parseresponse function
  1469. r38293 - 2008-07-25 12:32:34 -0700 (Fri, 25 Jul 2008) - Samir Gandhi - to put all the debug statements return value in the call function
  1470. r36824 - 2008-06-18 09:26:11 -0700 (Wed, 18 Jun 2008) - roger - bug: 21832
  1471. r26422 - 2007-09-05 17:29:12 -0700 (Wed, 05 Sep 2007) - majed - migrate from beta 1 to trunk
  1472. r15787 - 2006-08-10 10:14:41 -0700 (Thu, 10 Aug 2006) - roger - RRS: bug 7961
  1473. r14701 - 2006-07-17 13:37:26 -0700 (Mon, 17 Jul 2006) - roger - RRS: bug 5801
  1474. r13782 - 2006-06-06 10:58:55 -0700 (Tue, 06 Jun 2006) - majed - changes entry point code
  1475. r11466 - 2006-02-01 15:49:47 -0800 (Wed, 01 Feb 2006) - jacob - Adding extra !empty check to get around a PHP warning.
  1476. r11115 - 2006-01-17 14:54:45 -0800 (Tue, 17 Jan 2006) - majed - add entry point validation
  1477. r10585 - 2005-12-13 14:42:26 -0800 (Tue, 13 Dec 2005) - majed - adds new license mechanisim
  1478. r10170 - 2005-12-05 18:37:46 -0800 (Mon, 05 Dec 2005) - majed - fixes various issues
  1479. r8999 - 2005-11-04 05:26:49 -0800 (Fri, 04 Nov 2005) - roger - When nusoap was upgraded we had an issue with the user's default language not being populated during a soap request. I determined the reason this was happening and have checked in the corresponding change to nusoap.
  1480. r8991 - 2005-11-03 19:07:25 -0800 (Thu, 03 Nov 2005) - majed - fixes nusoap issue
  1481. r8846 - 2005-10-31 11:01:12 -0800 (Mon, 31 Oct 2005) - majed - new version of nusoap
  1482. r7905 - 2005-09-21 19:12:57 -0700 (Wed, 21 Sep 2005) - majed - restores old nusoap pre & with a few fixes
  1483. r7861 - 2005-09-20 15:40:25 -0700 (Tue, 20 Sep 2005) - majed - & fix for 3.5.1
  1484. r7452 - 2005-08-17 11:32:34 -0700 (Wed, 17 Aug 2005) - majed - changes soap to nusoap
  1485. r5820 - 2005-06-21 14:22:24 -0700 (Tue, 21 Jun 2005) - majed - fixes issues with nusoap and with custom fields
  1486. r5462 - 2005-05-25 13:50:11 -0700 (Wed, 25 May 2005) - majed - upgraded nusoap to .6.9
  1487. r5104 - 2005-05-04 15:33:41 -0700 (Wed, 04 May 2005) - majed - gets rid of HTTP_GET_VARS and what not which has been deprecated
  1488. r573 - 2004-09-04 13:03:32 -0700 (Sat, 04 Sep 2004) - sugarclint - undoing copyrights added in inadvertantly. --clint
  1489. r546 - 2004-09-03 11:49:38 -0700 (Fri, 03 Sep 2004) - sugarmsi - removed echo count
  1490. r354 - 2004-08-02 23:00:37 -0700 (Mon, 02 Aug 2004) - sugarjacob - Adding Soap
  1491. */
  1492. /**
  1493. * parses an XML Schema, allows access to it's data, other utility methods.
  1494. * imperfect, no validation... yet, but quite functional.
  1495. *
  1496. * @author Dietrich Ayala <dietrich@ganx4.com>
  1497. * @author Scott Nichol <snichol@users.sourceforge.net>
  1498. * @access public
  1499. */
  1500. class nusoap_xmlschema extends nusoap_base {
  1501. // files
  1502. var $schema = '';
  1503. var $xml = '';
  1504. // namespaces
  1505. var $enclosingNamespaces;
  1506. // schema info
  1507. var $schemaInfo = array();
  1508. var $schemaTargetNamespace = '';
  1509. // types, elements, attributes defined by the schema
  1510. var $attributes = array();
  1511. var $complexTypes = array();
  1512. var $complexTypeStack = array();
  1513. var $currentComplexType = null;
  1514. var $elements = array();
  1515. var $elementStack = array();
  1516. var $currentElement = null;
  1517. var $simpleTypes = array();
  1518. var $simpleTypeStack = array();
  1519. var $currentSimpleType = null;
  1520. // imports
  1521. var $imports = array();
  1522. // parser vars
  1523. var $parser;
  1524. var $position = 0;
  1525. var $depth = 0;
  1526. var $depth_array = array();
  1527. var $message = array();
  1528. var $defaultNamespace = array();
  1529. /**
  1530. * constructor
  1531. *
  1532. * @param string $schema schema document URI
  1533. * @param string $xml xml document URI
  1534. * @param string $namespaces namespaces defined in enclosing XML
  1535. * @access public
  1536. */
  1537. function nusoap_xmlschema($schema='',$xml='',$namespaces=array()){
  1538. parent::nusoap_base();
  1539. $this->debug('nusoap_xmlschema class instantiated, inside constructor');
  1540. // files
  1541. $this->schema = $schema;
  1542. $this->xml = $xml;
  1543. // namespaces
  1544. $this->enclosingNamespaces = $namespaces;
  1545. $this->namespaces = array_merge($this->namespaces, $namespaces);
  1546. // parse schema file
  1547. if($schema != ''){
  1548. $this->debug('initial schema file: '.$schema);
  1549. $this->parseFile($schema, 'schema');
  1550. }
  1551. // parse xml file
  1552. if($xml != ''){
  1553. $this->debug('initial xml file: '.$xml);
  1554. $this->parseFile($xml, 'xml');
  1555. }
  1556. }
  1557. /**
  1558. * parse an XML file
  1559. *
  1560. * @param string $xml path/URL to XML file
  1561. * @param string $type (schema | xml)
  1562. * @return boolean
  1563. * @access public
  1564. */
  1565. function parseFile($xml,$type){
  1566. // parse xml file
  1567. if($xml != ""){
  1568. $xmlStr = @join("",@file($xml));
  1569. if($xmlStr == ""){
  1570. $msg = 'Error reading XML from '.$xml;
  1571. $this->setError($msg);
  1572. $this->debug($msg);
  1573. return false;
  1574. } else {
  1575. $this->debug("parsing $xml");
  1576. $this->parseString($xmlStr,$type);
  1577. $this->debug("done parsing $xml");
  1578. return true;
  1579. }
  1580. }
  1581. return false;
  1582. }
  1583. /**
  1584. * parse an XML string
  1585. *
  1586. * @param string $xml path or URL
  1587. * @param string $type (schema|xml)
  1588. * @access private
  1589. */
  1590. function parseString($xml,$type){
  1591. // parse xml string
  1592. if($xml != ""){
  1593. // Create an XML parser.
  1594. $this->parser = xml_parser_create();
  1595. // Set the options for parsing the XML data.
  1596. xml_parser_set_option($this->parser, XML_OPTION_CASE_FOLDING, 0);
  1597. // Set the object for the parser.
  1598. xml_set_object($this->parser, $this);
  1599. // Set the element handlers for the parser.
  1600. if($type == "schema"){
  1601. xml_set_element_handler($this->parser, 'schemaStartElement','schemaEndElement');
  1602. xml_set_character_data_handler($this->parser,'schemaCharacterData');
  1603. } elseif($type == "xml"){
  1604. xml_set_element_handler($this->parser, 'xmlStartElement','xmlEndElement');
  1605. xml_set_character_data_handler($this->parser,'xmlCharacterData');
  1606. }
  1607. // Parse the XML file.
  1608. if(!xml_parse($this->parser,$xml,true)){
  1609. // Display an error message.
  1610. $errstr = sprintf('XML error parsing XML schema on line %d: %s',
  1611. xml_get_current_line_number($this->parser),
  1612. xml_error_string(xml_get_error_code($this->parser))
  1613. );
  1614. $this->debug($errstr);
  1615. $this->debug("XML payload:\n" . $xml);
  1616. $this->setError($errstr);
  1617. }
  1618. xml_parser_free($this->parser);
  1619. } else{
  1620. $this->debug('no xml passed to parseString()!!');
  1621. $this->setError('no xml passed to parseString()!!');
  1622. }
  1623. }
  1624. /**
  1625. * gets a type name for an unnamed type
  1626. *
  1627. * @param string Element name
  1628. * @return string A type name for an unnamed type
  1629. * @access private
  1630. */
  1631. function CreateTypeName($ename) {
  1632. $scope = '';
  1633. for ($i = 0; $i < count($this->complexTypeStack); $i++) {
  1634. $scope .= $this->complexTypeStack[$i] . '_';
  1635. }
  1636. return $scope . $ename . '_ContainedType';
  1637. }
  1638. /**
  1639. * start-element handler
  1640. *
  1641. * @param string $parser XML parser object
  1642. * @param string $name element name
  1643. * @param string $attrs associative array of attributes
  1644. * @access private
  1645. */
  1646. function schemaStartElement($parser, $name, $attrs) {
  1647. // position in the total number of elements, starting from 0
  1648. $pos = $this->position++;
  1649. $depth = $this->depth++;
  1650. // set self as current value for this depth
  1651. $this->depth_array[$depth] = $pos;
  1652. $this->message[$pos] = array('cdata' => '');
  1653. if ($depth > 0) {
  1654. $this->defaultNamespace[$pos] = $this->defaultNamespace[$this->depth_array[$depth - 1]];
  1655. } else {
  1656. $this->defaultNamespace[$pos] = false;
  1657. }
  1658. // get element prefix
  1659. if($prefix = $this->getPrefix($name)){
  1660. // get unqualified name
  1661. $name = $this->getLocalPart($name);
  1662. } else {
  1663. $prefix = '';
  1664. }
  1665. // loop thru attributes, expanding, and registering namespace declarations
  1666. if(count($attrs) > 0){
  1667. foreach($attrs as $k => $v){
  1668. // if ns declarations, add to class level array of valid namespaces
  1669. if(preg_match('/^xmlns/',$k)){
  1670. //$this->xdebug("$k: $v");
  1671. //$this->xdebug('ns_prefix: '.$this->getPrefix($k));
  1672. if($ns_prefix = substr(strrchr($k,':'),1)){
  1673. //$this->xdebug("Add namespace[$ns_prefix] = $v");
  1674. $this->namespaces[$ns_prefix] = $v;
  1675. } else {
  1676. $this->defaultNamespace[$pos] = $v;
  1677. if (! $this->getPrefixFromNamespace($v)) {
  1678. $this->namespaces['ns'.(count($this->namespaces)+1)] = $v;
  1679. }
  1680. }
  1681. if($v == 'http://www.w3.org/2001/XMLSchema' || $v == 'http://www.w3.org/1999/XMLSchema' || $v == 'http://www.w3.org/2000/10/XMLSchema'){
  1682. $this->XMLSchemaVersion = $v;
  1683. $this->namespaces['xsi'] = $v.'-instance';
  1684. }
  1685. }
  1686. }
  1687. foreach($attrs as $k => $v){
  1688. // expand each attribute
  1689. $k = strpos($k,':') ? $this->expandQname($k) : $k;
  1690. $v = strpos($v,':') ? $this->expandQname($v) : $v;
  1691. $eAttrs[$k] = $v;
  1692. }
  1693. $attrs = $eAttrs;
  1694. } else {
  1695. $attrs = array();
  1696. }
  1697. // find status, register data
  1698. switch($name){
  1699. case 'all': // (optional) compositor content for a complexType
  1700. case 'choice':
  1701. case 'group':
  1702. case 'sequence':
  1703. //$this->xdebug("compositor $name for currentComplexType: $this->currentComplexType and currentElement: $this->currentElement");
  1704. $this->complexTypes[$this->currentComplexType]['compositor'] = $name;
  1705. //if($name == 'all' || $name == 'sequence'){
  1706. // $this->complexTypes[$this->currentComplexType]['phpType'] = 'struct';
  1707. //}
  1708. break;
  1709. case 'attribute': // complexType attribute
  1710. //$this->xdebug("parsing attribute $attrs[name] $attrs[ref] of value: ".$attrs['http://schemas.xmlsoap.org/wsdl/:arrayType']);
  1711. $this->xdebug("parsing attribute:");
  1712. $this->appendDebug($this->varDump($attrs));
  1713. if (!isset($attrs['form'])) {
  1714. // TODO: handle globals
  1715. $attrs['form'] = $this->schemaInfo['attributeFormDefault'];
  1716. }
  1717. if (isset($attrs['http://schemas.xmlsoap.org/wsdl/:arrayType'])) {
  1718. $v = $attrs['http://schemas.xmlsoap.org/wsdl/:arrayType'];
  1719. if (!strpos($v, ':')) {
  1720. // no namespace in arrayType attribute value...
  1721. if ($this->defaultNamespace[$pos]) {
  1722. // ...so use the default
  1723. $attrs['http://schemas.xmlsoap.org/wsdl/:arrayType'] = $this->defaultNamespace[$pos] . ':' . $attrs['http://schemas.xmlsoap.org/wsdl/:arrayType'];
  1724. }
  1725. }
  1726. }
  1727. if(isset($attrs['name'])){
  1728. $this->attributes[$attrs['name']] = $attrs;
  1729. $aname = $attrs['name'];
  1730. } elseif(isset($attrs['ref']) && $attrs['ref'] == 'http://schemas.xmlsoap.org/soap/encoding/:arrayType'){
  1731. if (isset($attrs['http://schemas.xmlsoap.org/wsdl/:arrayType'])) {
  1732. $aname = $attrs['http://schemas.xmlsoap.org/wsdl/:arrayType'];
  1733. } else {
  1734. $aname = '';
  1735. }
  1736. } elseif(isset($attrs['ref'])){
  1737. $aname = $attrs['ref'];
  1738. $this->attributes[$attrs['ref']] = $attrs;
  1739. }
  1740. if($this->currentComplexType){ // This should *always* be
  1741. $this->complexTypes[$this->currentComplexType]['attrs'][$aname] = $attrs;
  1742. }
  1743. // arrayType attribute
  1744. if(isset($attrs['http://schemas.xmlsoap.org/wsdl/:arrayType']) || $this->getLocalPart($aname) == 'arrayType'){
  1745. $this->complexTypes[$this->currentComplexType]['phpType'] = 'array';
  1746. $prefix = $this->getPrefix($aname);
  1747. if(isset($attrs['http://schemas.xmlsoap.org/wsdl/:arrayType'])){
  1748. $v = $attrs['http://schemas.xmlsoap.org/wsdl/:arrayType'];
  1749. } else {
  1750. $v = '';
  1751. }
  1752. if(strpos($v,'[,]')){
  1753. $this->complexTypes[$this->currentComplexType]['multidimensional'] = true;
  1754. }
  1755. $v = substr($v,0,strpos($v,'[')); // clip the []
  1756. if(!strpos($v,':') && isset($this->typemap[$this->XMLSchemaVersion][$v])){
  1757. $v = $this->XMLSchemaVersion.':'.$v;
  1758. }
  1759. $this->complexTypes[$this->currentComplexType]['arrayType'] = $v;
  1760. }
  1761. break;
  1762. case 'complexContent': // (optional) content for a complexType
  1763. $this->xdebug("do nothing for element $name");
  1764. break;
  1765. case 'complexType':
  1766. array_push($this->complexTypeStack, $this->currentComplexType);
  1767. if(isset($attrs['name'])){
  1768. // TODO: what is the scope of named complexTypes that appear
  1769. // nested within other c complexTypes?
  1770. $this->xdebug('processing named complexType '.$attrs['name']);
  1771. //$this->currentElement = false;
  1772. $this->currentComplexType = $attrs['name'];
  1773. $this->complexTypes[$this->currentComplexType] = $attrs;
  1774. $this->complexTypes[$this->currentComplexType]['typeClass'] = 'complexType';
  1775. // This is for constructs like
  1776. // <complexType name="ListOfString" base="soap:Array">
  1777. // <sequence>
  1778. // <element name="string" type="xsd:string"
  1779. // minOccurs="0" maxOccurs="unbounded" />
  1780. // </sequence>
  1781. // </complexType>
  1782. if(isset($attrs['base']) && preg_match('/:Array$/',$attrs['base'])){
  1783. $this->xdebug('complexType is unusual array');
  1784. $this->complexTypes[$this->currentComplexType]['phpType'] = 'array';
  1785. } else {
  1786. $this->complexTypes[$this->currentComplexType]['phpType'] = 'struct';
  1787. }
  1788. } else {
  1789. $name = $this->CreateTypeName($this->currentElement);
  1790. $this->xdebug('processing unnamed complexType for element ' . $this->currentElement . ' named ' . $name);
  1791. $this->currentComplexType = $name;
  1792. //$this->currentElement = false;
  1793. $this->complexTypes[$this->currentComplexType] = $attrs;
  1794. $this->complexTypes[$this->currentComplexType]['typeClass'] = 'complexType';
  1795. // This is for constructs like
  1796. // <complexType name="ListOfString" base="soap:Array">
  1797. // <sequence>
  1798. // <element name="string" type="xsd:string"
  1799. // minOccurs="0" maxOccurs="unbounded" />
  1800. // </sequence>
  1801. // </complexType>
  1802. if(isset($attrs['base']) && preg_match('/:Array$/',$attrs['base'])){
  1803. $this->xdebug('complexType is unusual array');
  1804. $this->complexTypes[$this->currentComplexType]['phpType'] = 'array';
  1805. } else {
  1806. $this->complexTypes[$this->currentComplexType]['phpType'] = 'struct';
  1807. }
  1808. }
  1809. $this->complexTypes[$this->currentComplexType]['simpleContent'] = 'false';
  1810. break;
  1811. case 'element':
  1812. array_push($this->elementStack, $this->currentElement);
  1813. if (!isset($attrs['form'])) {
  1814. if ($this->currentComplexType) {
  1815. $attrs['form'] = $this->schemaInfo['elementFormDefault'];
  1816. } else {
  1817. // global
  1818. $attrs['form'] = 'qualified';
  1819. }
  1820. }
  1821. if(isset($attrs['type'])){
  1822. $this->xdebug("processing typed element ".$attrs['name']." of type ".$attrs['type']);
  1823. if (! $this->getPrefix($attrs['type'])) {
  1824. if ($this->defaultNamespace[$pos]) {
  1825. $attrs['type'] = $this->defaultNamespace[$pos] . ':' . $attrs['type'];
  1826. $this->xdebug('used default namespace to make type ' . $attrs['type']);
  1827. }
  1828. }
  1829. // This is for constructs like
  1830. // <complexType name="ListOfString" base="soap:Array">
  1831. // <sequence>
  1832. // <element name="string" type="xsd:string"
  1833. // minOccurs="0" maxOccurs="unbounded" />
  1834. // </sequence>
  1835. // </complexType>
  1836. if ($this->currentComplexType && $this->complexTypes[$this->currentComplexType]['phpType'] == 'array') {
  1837. $this->xdebug('arrayType for unusual array is ' . $attrs['type']);
  1838. $this->complexTypes[$this->currentComplexType]['arrayType'] = $attrs['type'];
  1839. }
  1840. $this->currentElement = $attrs['name'];
  1841. $ename = $attrs['name'];
  1842. } elseif(isset($attrs['ref'])){
  1843. $this->xdebug("processing element as ref to ".$attrs['ref']);
  1844. $this->currentElement = "ref to ".$attrs['ref'];
  1845. $ename = $this->getLocalPart($attrs['ref']);
  1846. } else {
  1847. $type = $this->CreateTypeName($this->currentComplexType . '_' . $attrs['name']);
  1848. $this->xdebug("processing untyped element " . $attrs['name'] . ' type ' . $type);
  1849. $this->currentElement = $attrs['name'];
  1850. $attrs['type'] = $this->schemaTargetNamespace . ':' . $type;
  1851. $ename = $attrs['name'];
  1852. }
  1853. if (isset($ename) && $this->currentComplexType) {
  1854. $this->xdebug("add element $ename to complexType $this->currentComplexType");
  1855. $this->complexTypes[$this->currentComplexType]['elements'][$ename] = $attrs;
  1856. } elseif (!isset($attrs['ref'])) {
  1857. $this->xdebug("add element $ename to elements array");
  1858. $this->elements[ $attrs['name'] ] = $attrs;
  1859. $this->elements[ $attrs['name'] ]['typeClass'] = 'element';
  1860. }
  1861. break;
  1862. case 'enumeration': // restriction value list member
  1863. $this->xdebug('enumeration ' . $attrs['value']);
  1864. if ($this->currentSimpleType) {
  1865. $this->simpleTypes[$this->currentSimpleType]['enumeration'][] = $attrs['value'];
  1866. } elseif ($this->currentComplexType) {
  1867. $this->complexTypes[$this->currentComplexType]['enumeration'][] = $attrs['value'];
  1868. }
  1869. break;
  1870. case 'extension': // simpleContent or complexContent type extension
  1871. $this->xdebug('extension ' . $attrs['base']);
  1872. if ($this->currentComplexType) {
  1873. $ns = $this->getPrefix($attrs['base']);
  1874. if ($ns == '') {
  1875. $this->complexTypes[$this->currentComplexType]['extensionBase'] = $this->schemaTargetNamespace . ':' . $attrs['base'];
  1876. } else {
  1877. $this->complexTypes[$this->currentComplexType]['extensionBase'] = $attrs['base'];
  1878. }
  1879. } else {
  1880. $this->xdebug('no current complexType to set extensionBase');
  1881. }
  1882. break;
  1883. case 'import':
  1884. if (isset($attrs['schemaLocation'])) {
  1885. $this->xdebug('import namespace ' . $attrs['namespace'] . ' from ' . $attrs['schemaLocation']);
  1886. $this->imports[$attrs['namespace']][] = array('location' => $attrs['schemaLocation'], 'loaded' => false);
  1887. } else {
  1888. $this->xdebug('import namespace ' . $attrs['namespace']);
  1889. $this->imports[$attrs['namespace']][] = array('location' => '', 'loaded' => true);
  1890. if (! $this->getPrefixFromNamespace($attrs['namespace'])) {
  1891. $this->namespaces['ns'.(count($this->namespaces)+1)] = $attrs['namespace'];
  1892. }
  1893. }
  1894. break;
  1895. case 'include':
  1896. if (isset($attrs['schemaLocation'])) {
  1897. $this->xdebug('include into namespace ' . $this->schemaTargetNamespace . ' from ' . $attrs['schemaLocation']);
  1898. $this->imports[$this->schemaTargetNamespace][] = array('location' => $attrs['schemaLocation'], 'loaded' => false);
  1899. } else {
  1900. $this->xdebug('ignoring invalid XML Schema construct: include without schemaLocation attribute');
  1901. }
  1902. break;
  1903. case 'list': // simpleType value list
  1904. $this->xdebug("do nothing for element $name");
  1905. break;
  1906. case 'restriction': // simpleType, simpleContent or complexContent value restriction
  1907. $this->xdebug('restriction ' . $attrs['base']);
  1908. if($this->currentSimpleType){
  1909. $this->simpleTypes[$this->currentSimpleType]['type'] = $attrs['base'];
  1910. } elseif($this->currentComplexType){
  1911. $this->complexTypes[$this->currentComplexType]['restrictionBase'] = $attrs['base'];
  1912. if(strstr($attrs['base'],':') == ':Array'){
  1913. $this->complexTypes[$this->currentComplexType]['phpType'] = 'array';
  1914. }
  1915. }
  1916. break;
  1917. case 'schema':
  1918. $this->schemaInfo = $attrs;
  1919. $this->schemaInfo['schemaVersion'] = $this->getNamespaceFromPrefix($prefix);
  1920. if (isset($attrs['targetNamespace'])) {
  1921. $this->schemaTargetNamespace = $attrs['targetNamespace'];
  1922. }
  1923. if (!isset($attrs['elementFormDefault'])) {
  1924. $this->schemaInfo['elementFormDefault'] = 'unqualified';
  1925. }
  1926. if (!isset($attrs['attributeFormDefault'])) {
  1927. $this->schemaInfo['attributeFormDefault'] = 'unqualified';
  1928. }
  1929. break;
  1930. case 'simpleContent': // (optional) content for a complexType
  1931. if ($this->currentComplexType) { // This should *always* be
  1932. $this->complexTypes[$this->currentComplexType]['simpleContent'] = 'true';
  1933. } else {
  1934. $this->xdebug("do nothing for element $name because there is no current complexType");
  1935. }
  1936. break;
  1937. case 'simpleType':
  1938. array_push($this->simpleTypeStack, $this->currentSimpleType);
  1939. if(isset($attrs['name'])){
  1940. $this->xdebug("processing simpleType for name " . $attrs['name']);
  1941. $this->currentSimpleType = $attrs['name'];
  1942. $this->simpleTypes[ $attrs['name'] ] = $attrs;
  1943. $this->simpleTypes[ $attrs['name'] ]['typeClass'] = 'simpleType';
  1944. $this->simpleTypes[ $attrs['name'] ]['phpType'] = 'scalar';
  1945. } else {
  1946. $name = $this->CreateTypeName($this->currentComplexType . '_' . $this->currentElement);
  1947. $this->xdebug('processing unnamed simpleType for element ' . $this->currentElement . ' named ' . $name);
  1948. $this->currentSimpleType = $name;
  1949. //$this->currentElement = false;
  1950. $this->simpleTypes[$this->currentSimpleType] = $attrs;
  1951. $this->simpleTypes[$this->currentSimpleType]['phpType'] = 'scalar';
  1952. }
  1953. break;
  1954. case 'union': // simpleType type list
  1955. $this->xdebug("do nothing for element $name");
  1956. break;
  1957. default:
  1958. $this->xdebug("do not have any logic to process element $name");
  1959. }
  1960. }
  1961. /**
  1962. * end-element handler
  1963. *
  1964. * @param string $parser XML parser object
  1965. * @param string $name element name
  1966. * @access private
  1967. */
  1968. function schemaEndElement($parser, $name) {
  1969. // bring depth down a notch
  1970. $this->depth--;
  1971. // position of current element is equal to the last value left in depth_array for my depth
  1972. if(isset($this->depth_array[$this->depth])){
  1973. $pos = $this->depth_array[$this->depth];
  1974. }
  1975. // get element prefix
  1976. if ($prefix = $this->getPrefix($name)){
  1977. // get unqualified name
  1978. $name = $this->getLocalPart($name);
  1979. } else {
  1980. $prefix = '';
  1981. }
  1982. // move on...
  1983. if($name == 'complexType'){
  1984. $this->xdebug('done processing complexType ' . ($this->currentComplexType ? $this->currentComplexType : '(unknown)'));
  1985. $this->xdebug($this->varDump($this->complexTypes[$this->currentComplexType]));
  1986. $this->currentComplexType = array_pop($this->complexTypeStack);
  1987. //$this->currentElement = false;
  1988. }
  1989. if($name == 'element'){
  1990. $this->xdebug('done processing element ' . ($this->currentElement ? $this->currentElement : '(unknown)'));
  1991. $this->currentElement = array_pop($this->elementStack);
  1992. }
  1993. if($name == 'simpleType'){
  1994. $this->xdebug('done processing simpleType ' . ($this->currentSimpleType ? $this->currentSimpleType : '(unknown)'));
  1995. $this->xdebug($this->varDump($this->simpleTypes[$this->currentSimpleType]));
  1996. $this->currentSimpleType = array_pop($this->simpleTypeStack);
  1997. }
  1998. }
  1999. /**
  2000. * element content handler
  2001. *
  2002. * @param string $parser XML parser object
  2003. * @param string $data element content
  2004. * @access private
  2005. */
  2006. function schemaCharacterData($parser, $data){
  2007. $pos = $this->depth_array[$this->depth - 1];
  2008. $this->message[$pos]['cdata'] .= $data;
  2009. }
  2010. /**
  2011. * serialize the schema
  2012. *
  2013. * @access public
  2014. */
  2015. function serializeSchema(){
  2016. $schemaPrefix = $this->getPrefixFromNamespace($this->XMLSchemaVersion);
  2017. $xml = '';
  2018. // imports
  2019. $schemaLocationCount = 0;
  2020. if (sizeof($this->imports) > 0) {
  2021. foreach($this->imports as $ns => $list) {
  2022. foreach ($list as $ii) {
  2023. if ($ii['location'] != '') {
  2024. $xml .= " <$schemaPrefix:import location=\"" . $ii['location'] . '" namespace="' . $ns . "\" />\n";
  2025. } else {
  2026. if ($schemaLocationCount == 0) {
  2027. $xml .= " <$schemaPrefix:import namespace=\"" . $ns . "\" schemaLocation=\"" . $ns . "\"/>\n";
  2028. } else {
  2029. $xml .= " <$schemaPrefix:import namespace=\"" . $ns . "\" />\n";
  2030. }
  2031. }
  2032. }
  2033. }
  2034. }
  2035. // complex types
  2036. foreach($this->complexTypes as $typeName => $attrs){
  2037. $contentStr = '';
  2038. // serialize child elements
  2039. if(isset($attrs['elements']) && (count($attrs['elements']) > 0)){
  2040. foreach($attrs['elements'] as $element => $eParts){
  2041. if(isset($eParts['ref'])){
  2042. $contentStr .= " <$schemaPrefix:element ref=\"$element\"/>\n";
  2043. } else {
  2044. $contentStr .= " <$schemaPrefix:element name=\"$element\" type=\"" . $this->contractQName($eParts['type']) . "\"";
  2045. foreach ($eParts as $aName => $aValue) {
  2046. // handle, e.g., abstract, default, form, minOccurs, maxOccurs, nillable
  2047. if ($aName != 'name' && $aName != 'type') {
  2048. $contentStr .= " $aName=\"$aValue\"";
  2049. }
  2050. }
  2051. $contentStr .= "/>\n";
  2052. }
  2053. }
  2054. // compositor wraps elements
  2055. if (isset($attrs['compositor']) && ($attrs['compositor'] != '')) {
  2056. $contentStr = " <$schemaPrefix:$attrs[compositor]>\n".$contentStr." </$schemaPrefix:$attrs[compositor]>\n";
  2057. }
  2058. }
  2059. // attributes
  2060. if(isset($attrs['attrs']) && (count($attrs['attrs']) >= 1)){
  2061. foreach($attrs['attrs'] as $attr => $aParts){
  2062. $contentStr .= " <$schemaPrefix:attribute";
  2063. foreach ($aParts as $a => $v) {
  2064. if ($a == 'ref' || $a == 'type') {
  2065. $contentStr .= " $a=\"".$this->contractQName($v).'"';
  2066. } elseif ($a == 'http://schemas.xmlsoap.org/wsdl/:arrayType') {
  2067. $this->usedNamespaces['wsdl'] = $this->namespaces['wsdl'];
  2068. $contentStr .= ' wsdl:arrayType="'.$this->contractQName($v).'"';
  2069. } else {
  2070. $contentStr .= " $a=\"$v\"";
  2071. }
  2072. }
  2073. $contentStr .= "/>\n";
  2074. }
  2075. }
  2076. // if restriction
  2077. if (isset($attrs['restrictionBase']) && $attrs['restrictionBase'] != ''){
  2078. $contentStr = " <$schemaPrefix:restriction base=\"".$this->contractQName($attrs['restrictionBase'])."\">\n".$contentStr." </$schemaPrefix:restriction>\n";
  2079. // complex or simple content
  2080. if ((isset($attrs['elements']) && count($attrs['elements']) > 0) || (isset($attrs['attrs']) && count($attrs['attrs']) > 0)){
  2081. $contentStr = " <$schemaPrefix:complexContent>\n".$contentStr." </$schemaPrefix:complexContent>\n";
  2082. }
  2083. }
  2084. // finalize complex type
  2085. if($contentStr != ''){
  2086. $contentStr = " <$schemaPrefix:complexType name=\"$typeName\">\n".$contentStr." </$schemaPrefix:complexType>\n";
  2087. } else {
  2088. $contentStr = " <$schemaPrefix:complexType name=\"$typeName\"/>\n";
  2089. }
  2090. $xml .= $contentStr;
  2091. }
  2092. // simple types
  2093. if(isset($this->simpleTypes) && count($this->simpleTypes) > 0){
  2094. foreach($this->simpleTypes as $typeName => $eParts){
  2095. $xml .= " <$schemaPrefix:simpleType name=\"$typeName\">\n <$schemaPrefix:restriction base=\"".$this->contractQName($eParts['type'])."\">\n";
  2096. if (isset($eParts['enumeration'])) {
  2097. foreach ($eParts['enumeration'] as $e) {
  2098. $xml .= " <$schemaPrefix:enumeration value=\"$e\"/>\n";
  2099. }
  2100. }
  2101. $xml .= " </$schemaPrefix:restriction>\n </$schemaPrefix:simpleType>";
  2102. }
  2103. }
  2104. // elements
  2105. if(isset($this->elements) && count($this->elements) > 0){
  2106. foreach($this->elements as $element => $eParts){
  2107. $xml .= " <$schemaPrefix:element name=\"$element\" type=\"".$this->contractQName($eParts['type'])."\"/>\n";
  2108. }
  2109. }
  2110. // attributes
  2111. if(isset($this->attributes) && count($this->attributes) > 0){
  2112. foreach($this->attributes as $attr => $aParts){
  2113. $xml .= " <$schemaPrefix:attribute name=\"$attr\" type=\"".$this->contractQName($aParts['type'])."\"\n/>";
  2114. }
  2115. }
  2116. // finish 'er up
  2117. $attr = '';
  2118. foreach ($this->schemaInfo as $k => $v) {
  2119. if ($k == 'elementFormDefault' || $k == 'attributeFormDefault') {
  2120. $attr .= " $k=\"$v\"";
  2121. }
  2122. }
  2123. $el = "<$schemaPrefix:schema$attr targetNamespace=\"$this->schemaTargetNamespace\"\n";
  2124. foreach (array_diff($this->usedNamespaces, $this->enclosingNamespaces) as $nsp => $ns) {
  2125. $el .= " xmlns:$nsp=\"$ns\"";
  2126. }
  2127. $xml = $el . ">\n".$xml."</$schemaPrefix:schema>\n";
  2128. return $xml;
  2129. }
  2130. /**
  2131. * adds debug data to the clas level debug string
  2132. *
  2133. * @param string $string debug data
  2134. * @access private
  2135. */
  2136. function xdebug($string){
  2137. if($this->debugLevel > 0) {
  2138. $this->debug('<' . $this->schemaTargetNamespace . '> '.$string);
  2139. }
  2140. }
  2141. /**
  2142. * get the PHP type of a user defined type in the schema
  2143. * PHP type is kind of a misnomer since it actually returns 'struct' for assoc. arrays
  2144. * returns false if no type exists, or not w/ the given namespace
  2145. * else returns a string that is either a native php type, or 'struct'
  2146. *
  2147. * @param string $type name of defined type
  2148. * @param string $ns namespace of type
  2149. * @return mixed
  2150. * @access public
  2151. * @deprecated
  2152. */
  2153. function getPHPType($type,$ns){
  2154. if(isset($this->typemap[$ns][$type])){
  2155. //print "found type '$type' and ns $ns in typemap<br>";
  2156. return $this->typemap[$ns][$type];
  2157. } elseif(isset($this->complexTypes[$type])){
  2158. //print "getting type '$type' and ns $ns from complexTypes array<br>";
  2159. return $this->complexTypes[$type]['phpType'];
  2160. }
  2161. return false;
  2162. }
  2163. /**
  2164. * returns an associative array of information about a given type
  2165. * returns false if no type exists by the given name
  2166. *
  2167. * For a complexType typeDef = array(
  2168. * 'restrictionBase' => '',
  2169. * 'phpType' => '',
  2170. * 'compositor' => '(sequence|all)',
  2171. * 'elements' => array(), // refs to elements array
  2172. * 'attrs' => array() // refs to attributes array
  2173. * ... and so on (see addComplexType)
  2174. * )
  2175. *
  2176. * For simpleType or element, the array has different keys.
  2177. *
  2178. * @param string $type
  2179. * @return mixed
  2180. * @access public
  2181. * @see addComplexType
  2182. * @see addSimpleType
  2183. * @see addElement
  2184. */
  2185. function getTypeDef($type){
  2186. //$this->debug("in getTypeDef for type $type");
  2187. if (substr($type, -1) == '^') {
  2188. $is_element = 1;
  2189. $type = substr($type, 0, -1);
  2190. } else {
  2191. $is_element = 0;
  2192. }
  2193. if((! $is_element) && isset($this->complexTypes[$type])){
  2194. $this->xdebug("in getTypeDef, found complexType $type");
  2195. return $this->complexTypes[$type];
  2196. } elseif((! $is_element) && isset($this->simpleTypes[$type])){
  2197. $this->xdebug("in getTypeDef, found simpleType $type");
  2198. if (!isset($this->simpleTypes[$type]['phpType'])) {
  2199. // get info for type to tack onto the simple type
  2200. // TODO: can this ever really apply (i.e. what is a simpleType really?)
  2201. $uqType = substr($this->simpleTypes[$type]['type'], strrpos($this->simpleTypes[$type]['type'], ':') + 1);
  2202. $ns = substr($this->simpleTypes[$type]['type'], 0, strrpos($this->simpleTypes[$type]['type'], ':'));
  2203. $etype = $this->getTypeDef($uqType);
  2204. if ($etype) {
  2205. $this->xdebug("in getTypeDef, found type for simpleType $type:");
  2206. $this->xdebug($this->varDump($etype));
  2207. if (isset($etype['phpType'])) {
  2208. $this->simpleTypes[$type]['phpType'] = $etype['phpType'];
  2209. }
  2210. if (isset($etype['elements'])) {
  2211. $this->simpleTypes[$type]['elements'] = $etype['elements'];
  2212. }
  2213. }
  2214. }
  2215. return $this->simpleTypes[$type];
  2216. } elseif(isset($this->elements[$type])){
  2217. $this->xdebug("in getTypeDef, found element $type");
  2218. if (!isset($this->elements[$type]['phpType'])) {
  2219. // get info for type to tack onto the element
  2220. $uqType = substr($this->elements[$type]['type'], strrpos($this->elements[$type]['type'], ':') + 1);
  2221. $ns = substr($this->elements[$type]['type'], 0, strrpos($this->elements[$type]['type'], ':'));
  2222. $etype = $this->getTypeDef($uqType);
  2223. if ($etype) {
  2224. $this->xdebug("in getTypeDef, found type for element $type:");
  2225. $this->xdebug($this->varDump($etype));
  2226. if (isset($etype['phpType'])) {
  2227. $this->elements[$type]['phpType'] = $etype['phpType'];
  2228. }
  2229. if (isset($etype['elements'])) {
  2230. $this->elements[$type]['elements'] = $etype['elements'];
  2231. }
  2232. if (isset($etype['extensionBase'])) {
  2233. $this->elements[$type]['extensionBase'] = $etype['extensionBase'];
  2234. }
  2235. } elseif ($ns == 'http://www.w3.org/2001/XMLSchema') {
  2236. $this->xdebug("in getTypeDef, element $type is an XSD type");
  2237. $this->elements[$type]['phpType'] = 'scalar';
  2238. }
  2239. }
  2240. return $this->elements[$type];
  2241. } elseif(isset($this->attributes[$type])){
  2242. $this->xdebug("in getTypeDef, found attribute $type");
  2243. return $this->attributes[$type];
  2244. } elseif (preg_match('/_ContainedType$/', $type)) {
  2245. $this->xdebug("in getTypeDef, have an untyped element $type");
  2246. $typeDef['typeClass'] = 'simpleType';
  2247. $typeDef['phpType'] = 'scalar';
  2248. $typeDef['type'] = 'http://www.w3.org/2001/XMLSchema:string';
  2249. return $typeDef;
  2250. }
  2251. $this->xdebug("in getTypeDef, did not find $type");
  2252. return false;
  2253. }
  2254. /**
  2255. * returns a sample serialization of a given type, or false if no type by the given name
  2256. *
  2257. * @param string $type name of type
  2258. * @return mixed
  2259. * @access public
  2260. * @deprecated
  2261. */
  2262. function serializeTypeDef($type){
  2263. //print "in sTD() for type $type<br>";
  2264. if($typeDef = $this->getTypeDef($type)){
  2265. $str .= '<'.$type;
  2266. if(is_array($typeDef['attrs'])){
  2267. foreach($typeDef['attrs'] as $attName => $data){
  2268. $str .= " $attName=\"{type = ".$data['type']."}\"";
  2269. }
  2270. }
  2271. $str .= " xmlns=\"".$this->schema['targetNamespace']."\"";
  2272. if(count($typeDef['elements']) > 0){
  2273. $str .= ">";
  2274. foreach($typeDef['elements'] as $element => $eData){
  2275. $str .= $this->serializeTypeDef($element);
  2276. }
  2277. $str .= "</$type>";
  2278. } elseif($typeDef['typeClass'] == 'element') {
  2279. $str .= "></$type>";
  2280. } else {
  2281. $str .= "/>";
  2282. }
  2283. return $str;
  2284. }
  2285. return false;
  2286. }
  2287. /**
  2288. * returns HTML form elements that allow a user
  2289. * to enter values for creating an instance of the given type.
  2290. *
  2291. * @param string $name name for type instance
  2292. * @param string $type name of type
  2293. * @return string
  2294. * @access public
  2295. * @deprecated
  2296. */
  2297. function typeToForm($name,$type){
  2298. // get typedef
  2299. if($typeDef = $this->getTypeDef($type)){
  2300. // if struct
  2301. if($typeDef['phpType'] == 'struct'){
  2302. $buffer .= '<table>';
  2303. foreach($typeDef['elements'] as $child => $childDef){
  2304. $buffer .= "
  2305. <tr><td align='right'>$childDef[name] (type: ".$this->getLocalPart($childDef['type'])."):</td>
  2306. <td><input type='text' name='parameters[".$name."][$childDef[name]]'></td></tr>";
  2307. }
  2308. $buffer .= '</table>';
  2309. // if array
  2310. } elseif($typeDef['phpType'] == 'array'){
  2311. $buffer .= '<table>';
  2312. for($i=0;$i < 3; $i++){
  2313. $buffer .= "
  2314. <tr><td align='right'>array item (type: $typeDef[arrayType]):</td>
  2315. <td><input type='text' name='parameters[".$name."][]'></td></tr>";
  2316. }
  2317. $buffer .= '</table>';
  2318. // if scalar
  2319. } else {
  2320. $buffer .= "<input type='text' name='parameters[$name]'>";
  2321. }
  2322. } else {
  2323. $buffer .= "<input type='text' name='parameters[$name]'>";
  2324. }
  2325. return $buffer;
  2326. }
  2327. /**
  2328. * adds a complex type to the schema
  2329. *
  2330. * example: array
  2331. *
  2332. * addType(
  2333. * 'ArrayOfstring',
  2334. * 'complexType',
  2335. * 'array',
  2336. * '',
  2337. * 'SOAP-ENC:Array',
  2338. * array('ref'=>'SOAP-ENC:arrayType','wsdl:arrayType'=>'string[]'),
  2339. * 'xsd:string'
  2340. * );
  2341. *
  2342. * example: PHP associative array ( SOAP Struct )
  2343. *
  2344. * addType(
  2345. * 'SOAPStruct',
  2346. * 'complexType',
  2347. * 'struct',
  2348. * 'all',
  2349. * array('myVar'=> array('name'=>'myVar','type'=>'string')
  2350. * );
  2351. *
  2352. * @param name
  2353. * @param typeClass (complexType|simpleType|attribute)
  2354. * @param phpType: currently supported are array and struct (php assoc array)
  2355. * @param compositor (all|sequence|choice)
  2356. * @param restrictionBase namespace:name (http://schemas.xmlsoap.org/soap/encoding/:Array)
  2357. * @param elements = array ( name = array(name=>'',type=>'') )
  2358. * @param attrs = array(
  2359. * array(
  2360. * 'ref' => "http://schemas.xmlsoap.org/soap/encoding/:arrayType",
  2361. * "http://schemas.xmlsoap.org/wsdl/:arrayType" => "string[]"
  2362. * )
  2363. * )
  2364. * @param arrayType: namespace:name (http://www.w3.org/2001/XMLSchema:string)
  2365. * @access public
  2366. * @see getTypeDef
  2367. */
  2368. function addComplexType($name,$typeClass='complexType',$phpType='array',$compositor='',$restrictionBase='',$elements=array(),$attrs=array(),$arrayType=''){
  2369. $this->complexTypes[$name] = array(
  2370. 'name' => $name,
  2371. 'typeClass' => $typeClass,
  2372. 'phpType' => $phpType,
  2373. 'compositor'=> $compositor,
  2374. 'restrictionBase' => $restrictionBase,
  2375. 'elements' => $elements,
  2376. 'attrs' => $attrs,
  2377. 'arrayType' => $arrayType
  2378. );
  2379. $this->xdebug("addComplexType $name:");
  2380. $this->appendDebug($this->varDump($this->complexTypes[$name]));
  2381. }
  2382. /**
  2383. * adds a simple type to the schema
  2384. *
  2385. * @param string $name
  2386. * @param string $restrictionBase namespace:name (http://schemas.xmlsoap.org/soap/encoding/:Array)
  2387. * @param string $typeClass (should always be simpleType)
  2388. * @param string $phpType (should always be scalar)
  2389. * @param array $enumeration array of values
  2390. * @access public
  2391. * @see nusoap_xmlschema
  2392. * @see getTypeDef
  2393. */
  2394. function addSimpleType($name, $restrictionBase='', $typeClass='simpleType', $phpType='scalar', $enumeration=array()) {
  2395. $this->simpleTypes[$name] = array(
  2396. 'name' => $name,
  2397. 'typeClass' => $typeClass,
  2398. 'phpType' => $phpType,
  2399. 'type' => $restrictionBase,
  2400. 'enumeration' => $enumeration
  2401. );
  2402. $this->xdebug("addSimpleType $name:");
  2403. $this->appendDebug($this->varDump($this->simpleTypes[$name]));
  2404. }
  2405. /**
  2406. * adds an element to the schema
  2407. *
  2408. * @param array $attrs attributes that must include name and type
  2409. * @see nusoap_xmlschema
  2410. * @access public
  2411. */
  2412. function addElement($attrs) {
  2413. if (! $this->getPrefix($attrs['type'])) {
  2414. $attrs['type'] = $this->schemaTargetNamespace . ':' . $attrs['type'];
  2415. }
  2416. $this->elements[ $attrs['name'] ] = $attrs;
  2417. $this->elements[ $attrs['name'] ]['typeClass'] = 'element';
  2418. $this->xdebug("addElement " . $attrs['name']);
  2419. $this->appendDebug($this->varDump($this->elements[ $attrs['name'] ]));
  2420. }
  2421. }
  2422. /**
  2423. * Backward compatibility
  2424. */
  2425. class XMLSchema extends nusoap_xmlschema {
  2426. }
  2427. ?><?php
  2428. /*
  2429. Modification information for LGPL compliance
  2430. r58622 - 2010-10-22 18:18:59 -0700 (Fri, 22 Oct 2010) - engsvnbuild - Author: lam <lam@198.18.142.201>
  2431. bug 40066
  2432. r58361 - 2010-09-29 16:59:02 -0700 (Wed, 29 Sep 2010) - kjing - Author: Jenny Gonsalves <jenny@sugarcrm.com>
  2433. Merging with maint_6_0_1 (svn merge -r 58250:58342)
  2434. r57813 - 2010-08-19 10:34:44 -0700 (Thu, 19 Aug 2010) - kjing - Author: John Mertic <jmertic@sugarcrm.com>
  2435. Bug 39085 - When loading the opposite search panel via ajax on the ListViews, call the index action instead of the ListView action to avoid touching pre-MVC code by accident.
  2436. r57707 - 2010-08-10 12:26:13 -0700 (Tue, 10 Aug 2010) - kjing - Author: Stanislav Malyshev <smalyshev@gmail.com>
  2437. fix SOAP calls with no parameters
  2438. r56990 - 2010-06-16 13:05:36 -0700 (Wed, 16 Jun 2010) - kjing - snapshot "Mango" svn branch to a new one for GitHub sync
  2439. r56989 - 2010-06-16 13:01:33 -0700 (Wed, 16 Jun 2010) - kjing - defunt "Mango" svn dev branch before github cutover
  2440. r55980 - 2010-04-19 13:31:28 -0700 (Mon, 19 Apr 2010) - kjing - create Mango (6.1) based on windex
  2441. r51719 - 2009-10-22 10:18:00 -0700 (Thu, 22 Oct 2009) - mitani - Converted to Build 3 tags and updated the build system
  2442. r51634 - 2009-10-19 13:32:22 -0700 (Mon, 19 Oct 2009) - mitani - Windex is the branch for Sugar Sales 1.0 development
  2443. r51508 - 2009-10-14 07:40:23 -0700 (Wed, 14 Oct 2009) - jmertic - More fallout fixes from the PHP 5.3 ereg to preg changes.
  2444. r51455 - 2009-10-13 07:56:48 -0700 (Tue, 13 Oct 2009) - jmertic - Bug 33202 - Enable install of SugarCRM on PHP 5.3.0, asserting that the minimum supported version is PHP 5.2.x.
  2445. r51443 - 2009-10-12 13:34:36 -0700 (Mon, 12 Oct 2009) - jmertic - Bug 33332 - Made application PHP 5.3 compliant with E_DEPRECATED warnings on by:
  2446. - Changing all ereg function to either preg or simple string based ones
  2447. - No more references to magic quotes.
  2448. - Change all the session_unregister() functions to just unset() the correct session variable instead.
  2449. r50375 - 2009-08-24 18:07:43 -0700 (Mon, 24 Aug 2009) - dwong - branch kobe2 from tokyo r50372
  2450. r45763 - 2009-04-01 12:16:18 -0700 (Wed, 01 Apr 2009) - majed - Removed half of the require_once and include_onces in the product that were redundant or could be handled easily by the auto loader
  2451. r45680 - 2009-03-30 14:34:35 -0700 (Mon, 30 Mar 2009) - Samir Gandhi - modifeid serializeSchema to generate WS-I compliant WSDL
  2452. r42807 - 2008-12-29 11:16:59 -0800 (Mon, 29 Dec 2008) - dwong - Branch from trunk/sugarcrm r42806 to branches/tokyo/sugarcrm
  2453. r42645 - 2008-12-18 13:41:08 -0800 (Thu, 18 Dec 2008) - awu - merging maint_5_2_0 rev41336:HEAD to trunk
  2454. r41647 - 2008-11-11 17:44:30 -0800 (Tue, 11 Nov 2008) - majed - Fixes a few bugs
  2455. r41596 - 2008-11-10 19:20:04 -0800 (Mon, 10 Nov 2008) - Samir Gandhi - modified to set $method in the code
  2456. r41558 - 2008-11-10 14:35:34 -0800 (Mon, 10 Nov 2008) - majed - changes nusoap to allow for registering classes
  2457. r39619 - 2008-09-09 13:41:34 -0700 (Tue, 09 Sep 2008) - jmertic - Bug 24827 - Remove all instances where we return a new object and assign it by reference, since this is deprecated in PHP 5 and emits E_DEPRECATED errors in PHP 5.3.
  2458. Touched:
  2459. - data/SugarBean.php
  2460. - include/domit/php_http_client_generic.php
  2461. - include/domit/php_http_connector.php
  2462. - include/domit/testing_domit.php
  2463. - include/domit/xml_domit_getelementsbypath.php
  2464. - include/domit/xml_domit_lite_parser.php
  2465. - include/domit/xml_domit_nodemaps.php
  2466. - include/domit/xml_domit_parser.php
  2467. - include/domit/xml_domit_shared.php
  2468. - include/generic/SugarWidgets/SugarWidgetField.php
  2469. - include/generic/SugarWidgets/SugarWidgetReportField.php
  2470. - include/ListView/ProcessView.php
  2471. - include/nusoap/class.soapclient.php
  2472. - include/nusoap/nusoap.php
  2473. - include/nusoap/nusoapmime.php
  2474. - include/Pear/HTML_Safe/Safe.php
  2475. - include/Pear/XML_HTMLSax3/HTMLSax3.php
  2476. - modules/Administration/RebuildWorkFlow.php
  2477. - modules/Expressions/RelateSelector.php
  2478. - modules/Reports/templates/templates_reports.php
  2479. - modules/WorkFlow/Delete.php
  2480. - modules/WorkFlow/Save.php
  2481. - modules/WorkFlow/SaveSequence.php
  2482. - modules/WorkFlow/WorkFlow.php
  2483. - modules/WorkFlowActionShells/CreateStep1.php
  2484. - modules/WorkFlowActionShells/CreateStep2.php
  2485. - modules/WorkFlowActionShells/Save.php
  2486. - modules/WorkFlowActionShells/WorkFlowActionShell.php
  2487. - modules/WorkFlowAlerts/Save.php
  2488. - modules/WorkFlowAlerts/WorkFlowAlert.php
  2489. - modules/WorkFlowAlertShells/DetailView.php
  2490. - modules/WorkFlowAlertShells/WorkFlowAlertShell.php
  2491. - modules/WorkFlowTriggerShells/CreateStep1.php
  2492. - modules/WorkFlowTriggerShells/CreateStepFilter.php
  2493. - modules/WorkFlowTriggerShells/SaveFilter.php
  2494. - modules/WorkFlowTriggerShells/WorkFlowTriggerShell.php
  2495. - soap/SoapHelperFunctions.php
  2496. - test/modules/DynamicFields/DynamicFields_Bug24095_test.php
  2497. - test/simpletest/browser.php
  2498. - test/simpletest/default_reporter.php
  2499. - test/simpletest/detached.php
  2500. - test/simpletest/eclipse.php
  2501. - test/simpletest/expectation.php
  2502. - test/simpletest/extensions/pear_test_case.php
  2503. - test/simpletest/form.php
  2504. - test/simpletest/http.php
  2505. - test/simpletest/mock_objects.php
  2506. - test/simpletest/page.php
  2507. - test/simpletest/parser.php
  2508. - test/simpletest/remote.php
  2509. - test/simpletest/shell_tester.php
  2510. - test/simpletest/simple_test.php
  2511. - test/simpletest/simpletest.php
  2512. - test/simpletest/test/acceptance_test.php
  2513. - test/simpletest/test/adapter_test.php
  2514. - test/simpletest/test/authentication_test.php
  2515. - test/simpletest/test/browser_test.php
  2516. - test/simpletest/test/collector_test.php
  2517. - test/simpletest/test/compatibility_test.php
  2518. - test/simpletest/test/detached_test.php
  2519. - test/simpletest/test/eclipse_test.php
  2520. - test/simpletest/test/encoding_test.php
  2521. - test/simpletest/test/errors_test.php
  2522. - test/simpletest/test/expectation_test.php
  2523. - test/simpletest/test/form_test.php
  2524. - test/simpletest/test/frames_test.php
  2525. - test/simpletest/test/http_test.php
  2526. - test/simpletest/test/live_test.php
  2527. - test/simpletest/test/mock_objects_test.php
  2528. - test/simpletest/test/page_test.php
  2529. - test/simpletest/test/parse_error_test.php
  2530. - test/simpletest/test/parser_test.php
  2531. - test/simpletest/test/remote_test.php
  2532. - test/simpletest/test/shell_test.php
  2533. - test/simpletest/test/shell_tester_test.php
  2534. - test/simpletest/test/simpletest_test.php
  2535. - test/simpletest/test/site/page_request.php
  2536. - test/simpletest/test/tag_test.php
  2537. - test/simpletest/test/unit_tester_test.php
  2538. - test/simpletest/test/user_agent_test.php
  2539. - test/simpletest/test/visual_test.php
  2540. - test/simpletest/test/xml_test.php
  2541. - test/simpletest/test_case.php
  2542. - test/simpletest/ui/array_reporter/test.php
  2543. - test/simpletest/ui/recorder/test.php
  2544. - test/simpletest/unit_tester.php
  2545. - test/simpletest/url.php
  2546. - test/simpletest/user_agent.php
  2547. - test/simpletest/web_tester.php
  2548. - test/spikephpcoverage/src/PEAR.php
  2549. - test/spikephpcoverage/src/util/Utility.php
  2550. - test/spikephpcoverage/src/XML/Parser.php
  2551. - test/spikephpcoverage/src/XML/Parser/Simple.php
  2552. - test/test_utilities/SugarTest_SimpleBrowser.php
  2553. r38362 - 2008-07-28 14:06:59 -0700 (Mon, 28 Jul 2008) - roger - bug: 23897. Using print_r when using the debug statement in nusoap will print out the statements to the screen if the call is coming from the UI.
  2554. r38300 - 2008-07-25 13:33:43 -0700 (Fri, 25 Jul 2008) - Samir Gandhi - put the debug in parseresponse function
  2555. r38293 - 2008-07-25 12:32:34 -0700 (Fri, 25 Jul 2008) - Samir Gandhi - to put all the debug statements return value in the call function
  2556. r36824 - 2008-06-18 09:26:11 -0700 (Wed, 18 Jun 2008) - roger - bug: 21832
  2557. r26422 - 2007-09-05 17:29:12 -0700 (Wed, 05 Sep 2007) - majed - migrate from beta 1 to trunk
  2558. r15787 - 2006-08-10 10:14:41 -0700 (Thu, 10 Aug 2006) - roger - RRS: bug 7961
  2559. r14701 - 2006-07-17 13:37:26 -0700 (Mon, 17 Jul 2006) - roger - RRS: bug 5801
  2560. r13782 - 2006-06-06 10:58:55 -0700 (Tue, 06 Jun 2006) - majed - changes entry point code
  2561. r11466 - 2006-02-01 15:49:47 -0800 (Wed, 01 Feb 2006) - jacob - Adding extra !empty check to get around a PHP warning.
  2562. r11115 - 2006-01-17 14:54:45 -0800 (Tue, 17 Jan 2006) - majed - add entry point validation
  2563. r10585 - 2005-12-13 14:42:26 -0800 (Tue, 13 Dec 2005) - majed - adds new license mechanisim
  2564. r10170 - 2005-12-05 18:37:46 -0800 (Mon, 05 Dec 2005) - majed - fixes various issues
  2565. r8999 - 2005-11-04 05:26:49 -0800 (Fri, 04 Nov 2005) - roger - When nusoap was upgraded we had an issue with the user's default language not being populated during a soap request. I determined the reason this was happening and have checked in the corresponding change to nusoap.
  2566. r8991 - 2005-11-03 19:07:25 -0800 (Thu, 03 Nov 2005) - majed - fixes nusoap issue
  2567. r8846 - 2005-10-31 11:01:12 -0800 (Mon, 31 Oct 2005) - majed - new version of nusoap
  2568. r7905 - 2005-09-21 19:12:57 -0700 (Wed, 21 Sep 2005) - majed - restores old nusoap pre & with a few fixes
  2569. r7861 - 2005-09-20 15:40:25 -0700 (Tue, 20 Sep 2005) - majed - & fix for 3.5.1
  2570. r7452 - 2005-08-17 11:32:34 -0700 (Wed, 17 Aug 2005) - majed - changes soap to nusoap
  2571. r5820 - 2005-06-21 14:22:24 -0700 (Tue, 21 Jun 2005) - majed - fixes issues with nusoap and with custom fields
  2572. r5462 - 2005-05-25 13:50:11 -0700 (Wed, 25 May 2005) - majed - upgraded nusoap to .6.9
  2573. r5104 - 2005-05-04 15:33:41 -0700 (Wed, 04 May 2005) - majed - gets rid of HTTP_GET_VARS and what not which has been deprecated
  2574. r573 - 2004-09-04 13:03:32 -0700 (Sat, 04 Sep 2004) - sugarclint - undoing copyrights added in inadvertantly. --clint
  2575. r546 - 2004-09-03 11:49:38 -0700 (Fri, 03 Sep 2004) - sugarmsi - removed echo count
  2576. r354 - 2004-08-02 23:00:37 -0700 (Mon, 02 Aug 2004) - sugarjacob - Adding Soap
  2577. */
  2578. /**
  2579. * For creating serializable abstractions of native PHP types. This class
  2580. * allows element name/namespace, XSD type, and XML attributes to be
  2581. * associated with a value. This is extremely useful when WSDL is not
  2582. * used, but is also useful when WSDL is used with polymorphic types, including
  2583. * xsd:anyType and user-defined types.
  2584. *
  2585. * @author Dietrich Ayala <dietrich@ganx4.com>
  2586. * @access public
  2587. */
  2588. class soapval extends nusoap_base {
  2589. /**
  2590. * The XML element name
  2591. *
  2592. * @var string
  2593. * @access private
  2594. */
  2595. var $name;
  2596. /**
  2597. * The XML type name (string or false)
  2598. *
  2599. * @var mixed
  2600. * @access private
  2601. */
  2602. var $type;
  2603. /**
  2604. * The PHP value
  2605. *
  2606. * @var mixed
  2607. * @access private
  2608. */
  2609. var $value;
  2610. /**
  2611. * The XML element namespace (string or false)
  2612. *
  2613. * @var mixed
  2614. * @access private
  2615. */
  2616. var $element_ns;
  2617. /**
  2618. * The XML type namespace (string or false)
  2619. *
  2620. * @var mixed
  2621. * @access private
  2622. */
  2623. var $type_ns;
  2624. /**
  2625. * The XML element attributes (array or false)
  2626. *
  2627. * @var mixed
  2628. * @access private
  2629. */
  2630. var $attributes;
  2631. /**
  2632. * constructor
  2633. *
  2634. * @param string $name optional name
  2635. * @param mixed $type optional type name
  2636. * @param mixed $value optional value
  2637. * @param mixed $element_ns optional namespace of value
  2638. * @param mixed $type_ns optional namespace of type
  2639. * @param mixed $attributes associative array of attributes to add to element serialization
  2640. * @access public
  2641. */
  2642. function soapval($name='soapval',$type=false,$value=-1,$element_ns=false,$type_ns=false,$attributes=false) {
  2643. parent::nusoap_base();
  2644. $this->name = $name;
  2645. $this->type = $type;
  2646. $this->value = $value;
  2647. $this->element_ns = $element_ns;
  2648. $this->type_ns = $type_ns;
  2649. $this->attributes = $attributes;
  2650. }
  2651. /**
  2652. * return serialized value
  2653. *
  2654. * @param string $use The WSDL use value (encoded|literal)
  2655. * @return string XML data
  2656. * @access public
  2657. */
  2658. function serialize($use='encoded') {
  2659. return $this->serialize_val($this->value, $this->name, $this->type, $this->element_ns, $this->type_ns, $this->attributes, $use, true);
  2660. }
  2661. /**
  2662. * decodes a soapval object into a PHP native type
  2663. *
  2664. * @return mixed
  2665. * @access public
  2666. */
  2667. function decode(){
  2668. return $this->value;
  2669. }
  2670. }
  2671. ?><?php
  2672. /*
  2673. Modification information for LGPL compliance
  2674. r58622 - 2010-10-22 18:18:59 -0700 (Fri, 22 Oct 2010) - engsvnbuild - Author: lam <lam@198.18.142.201>
  2675. bug 40066
  2676. r58361 - 2010-09-29 16:59:02 -0700 (Wed, 29 Sep 2010) - kjing - Author: Jenny Gonsalves <jenny@sugarcrm.com>
  2677. Merging with maint_6_0_1 (svn merge -r 58250:58342)
  2678. r57813 - 2010-08-19 10:34:44 -0700 (Thu, 19 Aug 2010) - kjing - Author: John Mertic <jmertic@sugarcrm.com>
  2679. Bug 39085 - When loading the opposite search panel via ajax on the ListViews, call the index action instead of the ListView action to avoid touching pre-MVC code by accident.
  2680. r57707 - 2010-08-10 12:26:13 -0700 (Tue, 10 Aug 2010) - kjing - Author: Stanislav Malyshev <smalyshev@gmail.com>
  2681. fix SOAP calls with no parameters
  2682. r56990 - 2010-06-16 13:05:36 -0700 (Wed, 16 Jun 2010) - kjing - snapshot "Mango" svn branch to a new one for GitHub sync
  2683. r56989 - 2010-06-16 13:01:33 -0700 (Wed, 16 Jun 2010) - kjing - defunt "Mango" svn dev branch before github cutover
  2684. r55980 - 2010-04-19 13:31:28 -0700 (Mon, 19 Apr 2010) - kjing - create Mango (6.1) based on windex
  2685. r51719 - 2009-10-22 10:18:00 -0700 (Thu, 22 Oct 2009) - mitani - Converted to Build 3 tags and updated the build system
  2686. r51634 - 2009-10-19 13:32:22 -0700 (Mon, 19 Oct 2009) - mitani - Windex is the branch for Sugar Sales 1.0 development
  2687. r51508 - 2009-10-14 07:40:23 -0700 (Wed, 14 Oct 2009) - jmertic - More fallout fixes from the PHP 5.3 ereg to preg changes.
  2688. r51455 - 2009-10-13 07:56:48 -0700 (Tue, 13 Oct 2009) - jmertic - Bug 33202 - Enable install of SugarCRM on PHP 5.3.0, asserting that the minimum supported version is PHP 5.2.x.
  2689. r51443 - 2009-10-12 13:34:36 -0700 (Mon, 12 Oct 2009) - jmertic - Bug 33332 - Made application PHP 5.3 compliant with E_DEPRECATED warnings on by:
  2690. - Changing all ereg function to either preg or simple string based ones
  2691. - No more references to magic quotes.
  2692. - Change all the session_unregister() functions to just unset() the correct session variable instead.
  2693. r50375 - 2009-08-24 18:07:43 -0700 (Mon, 24 Aug 2009) - dwong - branch kobe2 from tokyo r50372
  2694. r45763 - 2009-04-01 12:16:18 -0700 (Wed, 01 Apr 2009) - majed - Removed half of the require_once and include_onces in the product that were redundant or could be handled easily by the auto loader
  2695. r45680 - 2009-03-30 14:34:35 -0700 (Mon, 30 Mar 2009) - Samir Gandhi - modifeid serializeSchema to generate WS-I compliant WSDL
  2696. r42807 - 2008-12-29 11:16:59 -0800 (Mon, 29 Dec 2008) - dwong - Branch from trunk/sugarcrm r42806 to branches/tokyo/sugarcrm
  2697. r42645 - 2008-12-18 13:41:08 -0800 (Thu, 18 Dec 2008) - awu - merging maint_5_2_0 rev41336:HEAD to trunk
  2698. r41647 - 2008-11-11 17:44:30 -0800 (Tue, 11 Nov 2008) - majed - Fixes a few bugs
  2699. r41596 - 2008-11-10 19:20:04 -0800 (Mon, 10 Nov 2008) - Samir Gandhi - modified to set $method in the code
  2700. r41558 - 2008-11-10 14:35:34 -0800 (Mon, 10 Nov 2008) - majed - changes nusoap to allow for registering classes
  2701. r39619 - 2008-09-09 13:41:34 -0700 (Tue, 09 Sep 2008) - jmertic - Bug 24827 - Remove all instances where we return a new object and assign it by reference, since this is deprecated in PHP 5 and emits E_DEPRECATED errors in PHP 5.3.
  2702. Touched:
  2703. - data/SugarBean.php
  2704. - include/domit/php_http_client_generic.php
  2705. - include/domit/php_http_connector.php
  2706. - include/domit/testing_domit.php
  2707. - include/domit/xml_domit_getelementsbypath.php
  2708. - include/domit/xml_domit_lite_parser.php
  2709. - include/domit/xml_domit_nodemaps.php
  2710. - include/domit/xml_domit_parser.php
  2711. - include/domit/xml_domit_shared.php
  2712. - include/generic/SugarWidgets/SugarWidgetField.php
  2713. - include/generic/SugarWidgets/SugarWidgetReportField.php
  2714. - include/ListView/ProcessView.php
  2715. - include/nusoap/class.soapclient.php
  2716. - include/nusoap/nusoap.php
  2717. - include/nusoap/nusoapmime.php
  2718. - include/Pear/HTML_Safe/Safe.php
  2719. - include/Pear/XML_HTMLSax3/HTMLSax3.php
  2720. - modules/Administration/RebuildWorkFlow.php
  2721. - modules/Expressions/RelateSelector.php
  2722. - modules/Reports/templates/templates_reports.php
  2723. - modules/WorkFlow/Delete.php
  2724. - modules/WorkFlow/Save.php
  2725. - modules/WorkFlow/SaveSequence.php
  2726. - modules/WorkFlow/WorkFlow.php
  2727. - modules/WorkFlowActionShells/CreateStep1.php
  2728. - modules/WorkFlowActionShells/CreateStep2.php
  2729. - modules/WorkFlowActionShells/Save.php
  2730. - modules/WorkFlowActionShells/WorkFlowActionShell.php
  2731. - modules/WorkFlowAlerts/Save.php
  2732. - modules/WorkFlowAlerts/WorkFlowAlert.php
  2733. - modules/WorkFlowAlertShells/DetailView.php
  2734. - modules/WorkFlowAlertShells/WorkFlowAlertShell.php
  2735. - modules/WorkFlowTriggerShells/CreateStep1.php
  2736. - modules/WorkFlowTriggerShells/CreateStepFilter.php
  2737. - modules/WorkFlowTriggerShells/SaveFilter.php
  2738. - modules/WorkFlowTriggerShells/WorkFlowTriggerShell.php
  2739. - soap/SoapHelperFunctions.php
  2740. - test/modules/DynamicFields/DynamicFields_Bug24095_test.php
  2741. - test/simpletest/browser.php
  2742. - test/simpletest/default_reporter.php
  2743. - test/simpletest/detached.php
  2744. - test/simpletest/eclipse.php
  2745. - test/simpletest/expectation.php
  2746. - test/simpletest/extensions/pear_test_case.php
  2747. - test/simpletest/form.php
  2748. - test/simpletest/http.php
  2749. - test/simpletest/mock_objects.php
  2750. - test/simpletest/page.php
  2751. - test/simpletest/parser.php
  2752. - test/simpletest/remote.php
  2753. - test/simpletest/shell_tester.php
  2754. - test/simpletest/simple_test.php
  2755. - test/simpletest/simpletest.php
  2756. - test/simpletest/test/acceptance_test.php
  2757. - test/simpletest/test/adapter_test.php
  2758. - test/simpletest/test/authentication_test.php
  2759. - test/simpletest/test/browser_test.php
  2760. - test/simpletest/test/collector_test.php
  2761. - test/simpletest/test/compatibility_test.php
  2762. - test/simpletest/test/detached_test.php
  2763. - test/simpletest/test/eclipse_test.php
  2764. - test/simpletest/test/encoding_test.php
  2765. - test/simpletest/test/errors_test.php
  2766. - test/simpletest/test/expectation_test.php
  2767. - test/simpletest/test/form_test.php
  2768. - test/simpletest/test/frames_test.php
  2769. - test/simpletest/test/http_test.php
  2770. - test/simpletest/test/live_test.php
  2771. - test/simpletest/test/mock_objects_test.php
  2772. - test/simpletest/test/page_test.php
  2773. - test/simpletest/test/parse_error_test.php
  2774. - test/simpletest/test/parser_test.php
  2775. - test/simpletest/test/remote_test.php
  2776. - test/simpletest/test/shell_test.php
  2777. - test/simpletest/test/shell_tester_test.php
  2778. - test/simpletest/test/simpletest_test.php
  2779. - test/simpletest/test/site/page_request.php
  2780. - test/simpletest/test/tag_test.php
  2781. - test/simpletest/test/unit_tester_test.php
  2782. - test/simpletest/test/user_agent_test.php
  2783. - test/simpletest/test/visual_test.php
  2784. - test/simpletest/test/xml_test.php
  2785. - test/simpletest/test_case.php
  2786. - test/simpletest/ui/array_reporter/test.php
  2787. - test/simpletest/ui/recorder/test.php
  2788. - test/simpletest/unit_tester.php
  2789. - test/simpletest/url.php
  2790. - test/simpletest/user_agent.php
  2791. - test/simpletest/web_tester.php
  2792. - test/spikephpcoverage/src/PEAR.php
  2793. - test/spikephpcoverage/src/util/Utility.php
  2794. - test/spikephpcoverage/src/XML/Parser.php
  2795. - test/spikephpcoverage/src/XML/Parser/Simple.php
  2796. - test/test_utilities/SugarTest_SimpleBrowser.php
  2797. r38362 - 2008-07-28 14:06:59 -0700 (Mon, 28 Jul 2008) - roger - bug: 23897. Using print_r when using the debug statement in nusoap will print out the statements to the screen if the call is coming from the UI.
  2798. r38300 - 2008-07-25 13:33:43 -0700 (Fri, 25 Jul 2008) - Samir Gandhi - put the debug in parseresponse function
  2799. r38293 - 2008-07-25 12:32:34 -0700 (Fri, 25 Jul 2008) - Samir Gandhi - to put all the debug statements return value in the call function
  2800. r36824 - 2008-06-18 09:26:11 -0700 (Wed, 18 Jun 2008) - roger - bug: 21832
  2801. r26422 - 2007-09-05 17:29:12 -0700 (Wed, 05 Sep 2007) - majed - migrate from beta 1 to trunk
  2802. r15787 - 2006-08-10 10:14:41 -0700 (Thu, 10 Aug 2006) - roger - RRS: bug 7961
  2803. r14701 - 2006-07-17 13:37:26 -0700 (Mon, 17 Jul 2006) - roger - RRS: bug 5801
  2804. r13782 - 2006-06-06 10:58:55 -0700 (Tue, 06 Jun 2006) - majed - changes entry point code
  2805. r11466 - 2006-02-01 15:49:47 -0800 (Wed, 01 Feb 2006) - jacob - Adding extra !empty check to get around a PHP warning.
  2806. r11115 - 2006-01-17 14:54:45 -0800 (Tue, 17 Jan 2006) - majed - add entry point validation
  2807. r10585 - 2005-12-13 14:42:26 -0800 (Tue, 13 Dec 2005) - majed - adds new license mechanisim
  2808. r10170 - 2005-12-05 18:37:46 -0800 (Mon, 05 Dec 2005) - majed - fixes various issues
  2809. r8999 - 2005-11-04 05:26:49 -0800 (Fri, 04 Nov 2005) - roger - When nusoap was upgraded we had an issue with the user's default language not being populated during a soap request. I determined the reason this was happening and have checked in the corresponding change to nusoap.
  2810. r8991 - 2005-11-03 19:07:25 -0800 (Thu, 03 Nov 2005) - majed - fixes nusoap issue
  2811. r8846 - 2005-10-31 11:01:12 -0800 (Mon, 31 Oct 2005) - majed - new version of nusoap
  2812. r7905 - 2005-09-21 19:12:57 -0700 (Wed, 21 Sep 2005) - majed - restores old nusoap pre & with a few fixes
  2813. r7861 - 2005-09-20 15:40:25 -0700 (Tue, 20 Sep 2005) - majed - & fix for 3.5.1
  2814. r7452 - 2005-08-17 11:32:34 -0700 (Wed, 17 Aug 2005) - majed - changes soap to nusoap
  2815. r5820 - 2005-06-21 14:22:24 -0700 (Tue, 21 Jun 2005) - majed - fixes issues with nusoap and with custom fields
  2816. r5462 - 2005-05-25 13:50:11 -0700 (Wed, 25 May 2005) - majed - upgraded nusoap to .6.9
  2817. r5104 - 2005-05-04 15:33:41 -0700 (Wed, 04 May 2005) - majed - gets rid of HTTP_GET_VARS and what not which has been deprecated
  2818. r573 - 2004-09-04 13:03:32 -0700 (Sat, 04 Sep 2004) - sugarclint - undoing copyrights added in inadvertantly. --clint
  2819. r546 - 2004-09-03 11:49:38 -0700 (Fri, 03 Sep 2004) - sugarmsi - removed echo count
  2820. r354 - 2004-08-02 23:00:37 -0700 (Mon, 02 Aug 2004) - sugarjacob - Adding Soap
  2821. */
  2822. /**
  2823. * transport class for sending/receiving data via HTTP and HTTPS
  2824. * NOTE: PHP must be compiled with the CURL extension for HTTPS support
  2825. *
  2826. * @author Dietrich Ayala <dietrich@ganx4.com>
  2827. * @author Scott Nichol <snichol@users.sourceforge.net>
  2828. * @access public
  2829. */
  2830. class soap_transport_http extends nusoap_base {
  2831. var $url = '';
  2832. var $uri = '';
  2833. var $digest_uri = '';
  2834. var $scheme = '';
  2835. var $host = '';
  2836. var $port = '';
  2837. var $path = '';
  2838. var $request_method = 'POST';
  2839. var $protocol_version = '1.0';
  2840. var $encoding = '';
  2841. var $outgoing_headers = array();
  2842. var $incoming_headers = array();
  2843. var $incoming_cookies = array();
  2844. var $outgoing_payload = '';
  2845. var $incoming_payload = '';
  2846. var $response_status_line; // HTTP response status line
  2847. var $useSOAPAction = true;
  2848. var $persistentConnection = false;
  2849. var $ch = false; // cURL handle
  2850. var $ch_options = array(); // cURL custom options
  2851. var $use_curl = false; // force cURL use
  2852. var $proxy = null; // proxy information (associative array)
  2853. var $username = '';
  2854. var $password = '';
  2855. var $authtype = '';
  2856. var $digestRequest = array();
  2857. var $certRequest = array(); // keys must be cainfofile (optional), sslcertfile, sslkeyfile, passphrase, certpassword (optional), verifypeer (optional), verifyhost (optional)
  2858. // cainfofile: certificate authority file, e.g. '$pathToPemFiles/rootca.pem'
  2859. // sslcertfile: SSL certificate file, e.g. '$pathToPemFiles/mycert.pem'
  2860. // sslkeyfile: SSL key file, e.g. '$pathToPemFiles/mykey.pem'
  2861. // passphrase: SSL key password/passphrase
  2862. // certpassword: SSL certificate password
  2863. // verifypeer: default is 1
  2864. // verifyhost: default is 1
  2865. /**
  2866. * constructor
  2867. *
  2868. * @param string $url The URL to which to connect
  2869. * @param array $curl_options User-specified cURL options
  2870. * @param boolean $use_curl Whether to try to force cURL use
  2871. * @access public
  2872. */
  2873. function soap_transport_http($url, $curl_options = NULL, $use_curl = false){
  2874. parent::nusoap_base();
  2875. $this->debug("ctor url=$url use_curl=$use_curl curl_options:");
  2876. $this->appendDebug($this->varDump($curl_options));
  2877. $this->setURL($url);
  2878. if (is_array($curl_options)) {
  2879. $this->ch_options = $curl_options;
  2880. }
  2881. $this->use_curl = $use_curl;
  2882. preg_match('/\$Revisio' . 'n: ([^ ]+)/', $this->revision, $rev);
  2883. $this->setHeader('User-Agent', $this->title.'/'.$this->version.' ('.$rev[1].')');
  2884. }
  2885. /**
  2886. * sets a cURL option
  2887. *
  2888. * @param mixed $option The cURL option (always integer?)
  2889. * @param mixed $value The cURL option value
  2890. * @access private
  2891. */
  2892. function setCurlOption($option, $value) {
  2893. $this->debug("setCurlOption option=$option, value=");
  2894. $this->appendDebug($this->varDump($value));
  2895. curl_setopt($this->ch, $option, $value);
  2896. }
  2897. /**
  2898. * sets an HTTP header
  2899. *
  2900. * @param string $name The name of the header
  2901. * @param string $value The value of the header
  2902. * @access private
  2903. */
  2904. function setHeader($name, $value) {
  2905. $this->outgoing_headers[$name] = $value;
  2906. $this->debug("set header $name: $value");
  2907. }
  2908. /**
  2909. * unsets an HTTP header
  2910. *
  2911. * @param string $name The name of the header
  2912. * @access private
  2913. */
  2914. function unsetHeader($name) {
  2915. if (isset($this->outgoing_headers[$name])) {
  2916. $this->debug("unset header $name");
  2917. unset($this->outgoing_headers[$name]);
  2918. }
  2919. }
  2920. /**
  2921. * sets the URL to which to connect
  2922. *
  2923. * @param string $url The URL to which to connect
  2924. * @access private
  2925. */
  2926. function setURL($url) {
  2927. $this->url = $url;
  2928. $u = parse_url($url);
  2929. foreach($u as $k => $v){
  2930. $this->debug("parsed URL $k = $v");
  2931. $this->$k = $v;
  2932. }
  2933. // add any GET params to path
  2934. if(isset($u['query']) && $u['query'] != ''){
  2935. $this->path .= '?' . $u['query'];
  2936. }
  2937. // set default port
  2938. if(!isset($u['port'])){
  2939. if($u['scheme'] == 'https'){
  2940. $this->port = 443;
  2941. } else {
  2942. $this->port = 80;
  2943. }
  2944. }
  2945. $this->uri = $this->path;
  2946. $this->digest_uri = $this->uri;
  2947. // build headers
  2948. if (!isset($u['port'])) {
  2949. $this->setHeader('Host', $this->host);
  2950. } else {
  2951. $this->setHeader('Host', $this->host.':'.$this->port);
  2952. }
  2953. if (isset($u['user']) && $u['user'] != '') {
  2954. $this->setCredentials(urldecode($u['user']), isset($u['pass']) ? urldecode($u['pass']) : '');
  2955. }
  2956. }
  2957. /**
  2958. * gets the I/O method to use
  2959. *
  2960. * @return string I/O method to use (socket|curl|unknown)
  2961. * @access private
  2962. */
  2963. function io_method() {
  2964. if ($this->use_curl || ($this->scheme == 'https') || ($this->scheme == 'http' && $this->authtype == 'ntlm') || ($this->scheme == 'http' && is_array($this->proxy) && $this->proxy['authtype'] == 'ntlm'))
  2965. return 'curl';
  2966. if (($this->scheme == 'http' || $this->scheme == 'ssl') && $this->authtype != 'ntlm' && (!is_array($this->proxy) || $this->proxy['authtype'] != 'ntlm'))
  2967. return 'socket';
  2968. return 'unknown';
  2969. }
  2970. /**
  2971. * establish an HTTP connection
  2972. *
  2973. * @param integer $timeout set connection timeout in seconds
  2974. * @param integer $response_timeout set response timeout in seconds
  2975. * @return boolean true if connected, false if not
  2976. * @access private
  2977. */
  2978. function connect($connection_timeout=0,$response_timeout=30){
  2979. // For PHP 4.3 with OpenSSL, change https scheme to ssl, then treat like
  2980. // "regular" socket.
  2981. // TODO: disabled for now because OpenSSL must be *compiled* in (not just
  2982. // loaded), and until PHP5 stream_get_wrappers is not available.
  2983. // if ($this->scheme == 'https') {
  2984. // if (version_compare(phpversion(), '4.3.0') >= 0) {
  2985. // if (extension_loaded('openssl')) {
  2986. // $this->scheme = 'ssl';
  2987. // $this->debug('Using SSL over OpenSSL');
  2988. // }
  2989. // }
  2990. // }
  2991. $this->debug("connect connection_timeout $connection_timeout, response_timeout $response_timeout, scheme $this->scheme, host $this->host, port $this->port");
  2992. if ($this->io_method() == 'socket') {
  2993. if (!is_array($this->proxy)) {
  2994. $host = $this->host;
  2995. $port = $this->port;
  2996. } else {
  2997. $host = $this->proxy['host'];
  2998. $port = $this->proxy['port'];
  2999. }
  3000. // use persistent connection
  3001. if($this->persistentConnection && isset($this->fp) && is_resource($this->fp)){
  3002. if (!feof($this->fp)) {
  3003. $this->debug('Re-use persistent connection');
  3004. return true;
  3005. }
  3006. fclose($this->fp);
  3007. $this->debug('Closed persistent connection at EOF');
  3008. }
  3009. // munge host if using OpenSSL
  3010. if ($this->scheme == 'ssl') {
  3011. $host = 'ssl://' . $host;
  3012. }
  3013. $this->debug('calling fsockopen with host ' . $host . ' connection_timeout ' . $connection_timeout);
  3014. // open socket
  3015. if($connection_timeout > 0){
  3016. $this->fp = @fsockopen( $host, $this->port, $this->errno, $this->error_str, $connection_timeout);
  3017. } else {
  3018. $this->fp = @fsockopen( $host, $this->port, $this->errno, $this->error_str);
  3019. }
  3020. // test pointer
  3021. if(!$this->fp) {
  3022. $msg = 'Couldn\'t open socket connection to server ' . $this->url;
  3023. if ($this->errno) {
  3024. $msg .= ', Error ('.$this->errno.'): '.$this->error_str;
  3025. } else {
  3026. $msg .= ' prior to connect(). This is often a problem looking up the host name.';
  3027. }
  3028. $this->debug($msg);
  3029. $this->setError($msg);
  3030. return false;
  3031. }
  3032. // set response timeout
  3033. $this->debug('set response timeout to ' . $response_timeout);
  3034. socket_set_timeout( $this->fp, $response_timeout);
  3035. $this->debug('socket connected');
  3036. return true;
  3037. } else if ($this->io_method() == 'curl') {
  3038. if (!extension_loaded('curl')) {
  3039. // $this->setError('cURL Extension, or OpenSSL extension w/ PHP version >= 4.3 is required for HTTPS');
  3040. $this->setError('The PHP cURL Extension is required for HTTPS or NLTM. You will need to re-build or update your PHP to include cURL or change php.ini to load the PHP cURL extension.');
  3041. return false;
  3042. }
  3043. // Avoid warnings when PHP does not have these options
  3044. if (defined('CURLOPT_CONNECTIONTIMEOUT'))
  3045. $CURLOPT_CONNECTIONTIMEOUT = CURLOPT_CONNECTIONTIMEOUT;
  3046. else
  3047. $CURLOPT_CONNECTIONTIMEOUT = 78;
  3048. if (defined('CURLOPT_HTTPAUTH'))
  3049. $CURLOPT_HTTPAUTH = CURLOPT_HTTPAUTH;
  3050. else
  3051. $CURLOPT_HTTPAUTH = 107;
  3052. if (defined('CURLOPT_PROXYAUTH'))
  3053. $CURLOPT_PROXYAUTH = CURLOPT_PROXYAUTH;
  3054. else
  3055. $CURLOPT_PROXYAUTH = 111;
  3056. if (defined('CURLAUTH_BASIC'))
  3057. $CURLAUTH_BASIC = CURLAUTH_BASIC;
  3058. else
  3059. $CURLAUTH_BASIC = 1;
  3060. if (defined('CURLAUTH_DIGEST'))
  3061. $CURLAUTH_DIGEST = CURLAUTH_DIGEST;
  3062. else
  3063. $CURLAUTH_DIGEST = 2;
  3064. if (defined('CURLAUTH_NTLM'))
  3065. $CURLAUTH_NTLM = CURLAUTH_NTLM;
  3066. else
  3067. $CURLAUTH_NTLM = 8;
  3068. $this->debug('connect using cURL');
  3069. // init CURL
  3070. $this->ch = curl_init();
  3071. // set url
  3072. $hostURL = ($this->port != '') ? "$this->scheme://$this->host:$this->port" : "$this->scheme://$this->host";
  3073. // add path
  3074. $hostURL .= $this->path;
  3075. $this->setCurlOption(CURLOPT_URL, $hostURL);
  3076. // follow location headers (re-directs)
  3077. if (ini_get('safe_mode') || ini_get('open_basedir')) {
  3078. $this->debug('safe_mode or open_basedir set, so do not set CURLOPT_FOLLOWLOCATION');
  3079. $this->debug('safe_mode = ');
  3080. $this->appendDebug($this->varDump(ini_get('safe_mode')));
  3081. $this->debug('open_basedir = ');
  3082. $this->appendDebug($this->varDump(ini_get('open_basedir')));
  3083. } else {
  3084. $this->setCurlOption(CURLOPT_FOLLOWLOCATION, 1);
  3085. }
  3086. // ask for headers in the response output
  3087. $this->setCurlOption(CURLOPT_HEADER, 1);
  3088. // ask for the response output as the return value
  3089. $this->setCurlOption(CURLOPT_RETURNTRANSFER, 1);
  3090. // encode
  3091. // We manage this ourselves through headers and encoding
  3092. // if(function_exists('gzuncompress')){
  3093. // $this->setCurlOption(CURLOPT_ENCODING, 'deflate');
  3094. // }
  3095. // persistent connection
  3096. if ($this->persistentConnection) {
  3097. // I believe the following comment is now bogus, having applied to
  3098. // the code when it used CURLOPT_CUSTOMREQUEST to send the request.
  3099. // The way we send data, we cannot use persistent connections, since
  3100. // there will be some "junk" at the end of our request.
  3101. //$this->setCurlOption(CURL_HTTP_VERSION_1_1, true);
  3102. $this->persistentConnection = false;
  3103. $this->setHeader('Connection', 'close');
  3104. }
  3105. // set timeouts
  3106. if ($connection_timeout != 0) {
  3107. $this->setCurlOption($CURLOPT_CONNECTIONTIMEOUT, $connection_timeout);
  3108. }
  3109. if ($response_timeout != 0) {
  3110. $this->setCurlOption(CURLOPT_TIMEOUT, $response_timeout);
  3111. }
  3112. if ($this->scheme == 'https') {
  3113. $this->debug('set cURL SSL verify options');
  3114. // recent versions of cURL turn on peer/host checking by default,
  3115. // while PHP binaries are not compiled with a default location for the
  3116. // CA cert bundle, so disable peer/host checking.
  3117. //$this->setCurlOption(CURLOPT_CAINFO, 'f:\php-4.3.2-win32\extensions\curl-ca-bundle.crt');
  3118. $this->setCurlOption(CURLOPT_SSL_VERIFYPEER, 0);
  3119. $this->setCurlOption(CURLOPT_SSL_VERIFYHOST, 0);
  3120. // support client certificates (thanks Tobias Boes, Doug Anarino, Eryan Ariobowo)
  3121. if ($this->authtype == 'certificate') {
  3122. $this->debug('set cURL certificate options');
  3123. if (isset($this->certRequest['cainfofile'])) {
  3124. $this->setCurlOption(CURLOPT_CAINFO, $this->certRequest['cainfofile']);
  3125. }
  3126. if (isset($this->certRequest['verifypeer'])) {
  3127. $this->setCurlOption(CURLOPT_SSL_VERIFYPEER, $this->certRequest['verifypeer']);
  3128. } else {
  3129. $this->setCurlOption(CURLOPT_SSL_VERIFYPEER, 1);
  3130. }
  3131. if (isset($this->certRequest['verifyhost'])) {
  3132. $this->setCurlOption(CURLOPT_SSL_VERIFYHOST, $this->certRequest['verifyhost']);
  3133. } else {
  3134. $this->setCurlOption(CURLOPT_SSL_VERIFYHOST, 1);
  3135. }
  3136. if (isset($this->certRequest['sslcertfile'])) {
  3137. $this->setCurlOption(CURLOPT_SSLCERT, $this->certRequest['sslcertfile']);
  3138. }
  3139. if (isset($this->certRequest['sslkeyfile'])) {
  3140. $this->setCurlOption(CURLOPT_SSLKEY, $this->certRequest['sslkeyfile']);
  3141. }
  3142. if (isset($this->certRequest['passphrase'])) {
  3143. $this->setCurlOption(CURLOPT_SSLKEYPASSWD, $this->certRequest['passphrase']);
  3144. }
  3145. if (isset($this->certRequest['certpassword'])) {
  3146. $this->setCurlOption(CURLOPT_SSLCERTPASSWD, $this->certRequest['certpassword']);
  3147. }
  3148. }
  3149. }
  3150. if ($this->authtype && ($this->authtype != 'certificate')) {
  3151. if ($this->username) {
  3152. $this->debug('set cURL username/password');
  3153. $this->setCurlOption(CURLOPT_USERPWD, "$this->username:$this->password");
  3154. }
  3155. if ($this->authtype == 'basic') {
  3156. $this->debug('set cURL for Basic authentication');
  3157. $this->setCurlOption($CURLOPT_HTTPAUTH, $CURLAUTH_BASIC);
  3158. }
  3159. if ($this->authtype == 'digest') {
  3160. $this->debug('set cURL for digest authentication');
  3161. $this->setCurlOption($CURLOPT_HTTPAUTH, $CURLAUTH_DIGEST);
  3162. }
  3163. if ($this->authtype == 'ntlm') {
  3164. $this->debug('set cURL for NTLM authentication');
  3165. $this->setCurlOption($CURLOPT_HTTPAUTH, $CURLAUTH_NTLM);
  3166. }
  3167. }
  3168. if (is_array($this->proxy)) {
  3169. $this->debug('set cURL proxy options');
  3170. if ($this->proxy['port'] != '') {
  3171. $this->setCurlOption(CURLOPT_PROXY, $this->proxy['host'].':'.$this->proxy['port']);
  3172. } else {
  3173. $this->setCurlOption(CURLOPT_PROXY, $this->proxy['host']);
  3174. }
  3175. if ($this->proxy['username'] || $this->proxy['password']) {
  3176. $this->debug('set cURL proxy authentication options');
  3177. $this->setCurlOption(CURLOPT_PROXYUSERPWD, $this->proxy['username'].':'.$this->proxy['password']);
  3178. if ($this->proxy['authtype'] == 'basic') {
  3179. $this->setCurlOption($CURLOPT_PROXYAUTH, $CURLAUTH_BASIC);
  3180. }
  3181. if ($this->proxy['authtype'] == 'ntlm') {
  3182. $this->setCurlOption($CURLOPT_PROXYAUTH, $CURLAUTH_NTLM);
  3183. }
  3184. }
  3185. }
  3186. $this->debug('cURL connection set up');
  3187. return true;
  3188. } else {
  3189. $this->setError('Unknown scheme ' . $this->scheme);
  3190. $this->debug('Unknown scheme ' . $this->scheme);
  3191. return false;
  3192. }
  3193. }
  3194. /**
  3195. * sends the SOAP request and gets the SOAP response via HTTP[S]
  3196. *
  3197. * @param string $data message data
  3198. * @param integer $timeout set connection timeout in seconds
  3199. * @param integer $response_timeout set response timeout in seconds
  3200. * @param array $cookies cookies to send
  3201. * @return string data
  3202. * @access public
  3203. */
  3204. function send($data, $timeout=0, $response_timeout=30, $cookies=NULL) {
  3205. $this->debug('entered send() with data of length: '.strlen($data));
  3206. $this->tryagain = true;
  3207. $tries = 0;
  3208. while ($this->tryagain) {
  3209. $this->tryagain = false;
  3210. if ($tries++ < 2) {
  3211. // make connnection
  3212. if (!$this->connect($timeout, $response_timeout)){
  3213. return false;
  3214. }
  3215. // send request
  3216. if (!$this->sendRequest($data, $cookies)){
  3217. return false;
  3218. }
  3219. // get response
  3220. $respdata = $this->getResponse();
  3221. } else {
  3222. $this->setError("Too many tries to get an OK response ($this->response_status_line)");
  3223. }
  3224. }
  3225. $this->debug('end of send()');
  3226. return $respdata;
  3227. }
  3228. /**
  3229. * sends the SOAP request and gets the SOAP response via HTTPS using CURL
  3230. *
  3231. * @param string $data message data
  3232. * @param integer $timeout set connection timeout in seconds
  3233. * @param integer $response_timeout set response timeout in seconds
  3234. * @param array $cookies cookies to send
  3235. * @return string data
  3236. * @access public
  3237. * @deprecated
  3238. */
  3239. function sendHTTPS($data, $timeout=0, $response_timeout=30, $cookies) {
  3240. return $this->send($data, $timeout, $response_timeout, $cookies);
  3241. }
  3242. /**
  3243. * if authenticating, set user credentials here
  3244. *
  3245. * @param string $username
  3246. * @param string $password
  3247. * @param string $authtype (basic|digest|certificate|ntlm)
  3248. * @param array $digestRequest (keys must be nonce, nc, realm, qop)
  3249. * @param array $certRequest (keys must be cainfofile (optional), sslcertfile, sslkeyfile, passphrase, certpassword (optional), verifypeer (optional), verifyhost (optional): see corresponding options in cURL docs)
  3250. * @access public
  3251. */
  3252. function setCredentials($username, $password, $authtype = 'basic', $digestRequest = array(), $certRequest = array()) {
  3253. $this->debug("setCredentials username=$username authtype=$authtype digestRequest=");
  3254. $this->appendDebug($this->varDump($digestRequest));
  3255. $this->debug("certRequest=");
  3256. $this->appendDebug($this->varDump($certRequest));
  3257. // cf. RFC 2617
  3258. if ($authtype == 'basic') {
  3259. $this->setHeader('Authorization', 'Basic '.base64_encode(str_replace(':','',$username).':'.$password));
  3260. } elseif ($authtype == 'digest') {
  3261. if (isset($digestRequest['nonce'])) {
  3262. $digestRequest['nc'] = isset($digestRequest['nc']) ? $digestRequest['nc']++ : 1;
  3263. // calculate the Digest hashes (calculate code based on digest implementation found at: http://www.rassoc.com/gregr/weblog/stories/2002/07/09/webServicesSecurityHttpDigestAuthenticationWithoutActiveDirectory.html)
  3264. // A1 = unq(username-value) ":" unq(realm-value) ":" passwd
  3265. $A1 = $username. ':' . (isset($digestRequest['realm']) ? $digestRequest['realm'] : '') . ':' . $password;
  3266. // H(A1) = MD5(A1)
  3267. $HA1 = md5($A1);
  3268. // A2 = Method ":" digest-uri-value
  3269. $A2 = $this->request_method . ':' . $this->digest_uri;
  3270. // H(A2)
  3271. $HA2 = md5($A2);
  3272. // KD(secret, data) = H(concat(secret, ":", data))
  3273. // if qop == auth:
  3274. // request-digest = <"> < KD ( H(A1), unq(nonce-value)
  3275. // ":" nc-value
  3276. // ":" unq(cnonce-value)
  3277. // ":" unq(qop-value)
  3278. // ":" H(A2)
  3279. // ) <">
  3280. // if qop is missing,
  3281. // request-digest = <"> < KD ( H(A1), unq(nonce-value) ":" H(A2) ) > <">
  3282. $unhashedDigest = '';
  3283. $nonce = isset($digestRequest['nonce']) ? $digestRequest['nonce'] : '';
  3284. $cnonce = $nonce;
  3285. if ($digestRequest['qop'] != '') {
  3286. $unhashedDigest = $HA1 . ':' . $nonce . ':' . sprintf("%08d", $digestRequest['nc']) . ':' . $cnonce . ':' . $digestRequest['qop'] . ':' . $HA2;
  3287. } else {
  3288. $unhashedDigest = $HA1 . ':' . $nonce . ':' . $HA2;
  3289. }
  3290. $hashedDigest = md5($unhashedDigest);
  3291. $opaque = '';
  3292. if (isset($digestRequest['opaque'])) {
  3293. $opaque = ', opaque="' . $digestRequest['opaque'] . '"';
  3294. }
  3295. $this->setHeader('Authorization', 'Digest username="' . $username . '", realm="' . $digestRequest['realm'] . '", nonce="' . $nonce . '", uri="' . $this->digest_uri . $opaque . '", cnonce="' . $cnonce . '", nc=' . sprintf("%08x", $digestRequest['nc']) . ', qop="' . $digestRequest['qop'] . '", response="' . $hashedDigest . '"');
  3296. }
  3297. } elseif ($authtype == 'certificate') {
  3298. $this->certRequest = $certRequest;
  3299. $this->debug('Authorization header not set for certificate');
  3300. } elseif ($authtype == 'ntlm') {
  3301. // do nothing
  3302. $this->debug('Authorization header not set for ntlm');
  3303. }
  3304. $this->username = $username;
  3305. $this->password = $password;
  3306. $this->authtype = $authtype;
  3307. $this->digestRequest = $digestRequest;
  3308. }
  3309. /**
  3310. * set the soapaction value
  3311. *
  3312. * @param string $soapaction
  3313. * @access public
  3314. */
  3315. function setSOAPAction($soapaction) {
  3316. $this->setHeader('SOAPAction', '"' . $soapaction . '"');
  3317. }
  3318. /**
  3319. * use http encoding
  3320. *
  3321. * @param string $enc encoding style. supported values: gzip, deflate, or both
  3322. * @access public
  3323. */
  3324. function setEncoding($enc='gzip, deflate') {
  3325. if (function_exists('gzdeflate')) {
  3326. $this->protocol_version = '1.1';
  3327. $this->setHeader('Accept-Encoding', $enc);
  3328. if (!isset($this->outgoing_headers['Connection'])) {
  3329. $this->setHeader('Connection', 'close');
  3330. $this->persistentConnection = false;
  3331. }
  3332. // deprecated as of PHP 5.3.0
  3333. //set_magic_quotes_runtime(0);
  3334. $this->encoding = $enc;
  3335. }
  3336. }
  3337. /**
  3338. * set proxy info here
  3339. *
  3340. * @param string $proxyhost use an empty string to remove proxy
  3341. * @param string $proxyport
  3342. * @param string $proxyusername
  3343. * @param string $proxypassword
  3344. * @param string $proxyauthtype (basic|ntlm)
  3345. * @access public
  3346. */
  3347. function setProxy($proxyhost, $proxyport, $proxyusername = '', $proxypassword = '', $proxyauthtype = 'basic') {
  3348. if ($proxyhost) {
  3349. $this->proxy = array(
  3350. 'host' => $proxyhost,
  3351. 'port' => $proxyport,
  3352. 'username' => $proxyusername,
  3353. 'password' => $proxypassword,
  3354. 'authtype' => $proxyauthtype
  3355. );
  3356. if ($proxyusername != '' && $proxypassword != '' && $proxyauthtype = 'basic') {
  3357. $this->setHeader('Proxy-Authorization', ' Basic '.base64_encode($proxyusername.':'.$proxypassword));
  3358. }
  3359. } else {
  3360. $this->debug('remove proxy');
  3361. $proxy = null;
  3362. unsetHeader('Proxy-Authorization');
  3363. }
  3364. }
  3365. /**
  3366. * Test if the given string starts with a header that is to be skipped.
  3367. * Skippable headers result from chunked transfer and proxy requests.
  3368. *
  3369. * @param string $data The string to check.
  3370. * @returns boolean Whether a skippable header was found.
  3371. * @access private
  3372. */
  3373. function isSkippableCurlHeader(&$data) {
  3374. $skipHeaders = array( 'HTTP/1.1 100',
  3375. 'HTTP/1.0 301',
  3376. 'HTTP/1.1 301',
  3377. 'HTTP/1.0 302',
  3378. 'HTTP/1.1 302',
  3379. 'HTTP/1.0 401',
  3380. 'HTTP/1.1 401',
  3381. 'HTTP/1.0 200 Connection established');
  3382. foreach ($skipHeaders as $hd) {
  3383. $prefix = substr($data, 0, strlen($hd));
  3384. if ($prefix == $hd) return true;
  3385. }
  3386. return false;
  3387. }
  3388. /**
  3389. * decode a string that is encoded w/ "chunked' transfer encoding
  3390. * as defined in RFC2068 19.4.6
  3391. *
  3392. * @param string $buffer
  3393. * @param string $lb
  3394. * @returns string
  3395. * @access public
  3396. * @deprecated
  3397. */
  3398. function decodeChunked($buffer, $lb){
  3399. // length := 0
  3400. $length = 0;
  3401. $new = '';
  3402. // read chunk-size, chunk-extension (if any) and CRLF
  3403. // get the position of the linebreak
  3404. $chunkend = strpos($buffer, $lb);
  3405. if ($chunkend == FALSE) {
  3406. $this->debug('no linebreak found in decodeChunked');
  3407. return $new;
  3408. }
  3409. $temp = substr($buffer,0,$chunkend);
  3410. $chunk_size = hexdec( trim($temp) );
  3411. $chunkstart = $chunkend + strlen($lb);
  3412. // while (chunk-size > 0) {
  3413. while ($chunk_size > 0) {
  3414. $this->debug("chunkstart: $chunkstart chunk_size: $chunk_size");
  3415. $chunkend = strpos( $buffer, $lb, $chunkstart + $chunk_size);
  3416. // Just in case we got a broken connection
  3417. if ($chunkend == FALSE) {
  3418. $chunk = substr($buffer,$chunkstart);
  3419. // append chunk-data to entity-body
  3420. $new .= $chunk;
  3421. $length += strlen($chunk);
  3422. break;
  3423. }
  3424. // read chunk-data and CRLF
  3425. $chunk = substr($buffer,$chunkstart,$chunkend-$chunkstart);
  3426. // append chunk-data to entity-body
  3427. $new .= $chunk;
  3428. // length := length + chunk-size
  3429. $length += strlen($chunk);
  3430. // read chunk-size and CRLF
  3431. $chunkstart = $chunkend + strlen($lb);
  3432. $chunkend = strpos($buffer, $lb, $chunkstart) + strlen($lb);
  3433. if ($chunkend == FALSE) {
  3434. break; //Just in case we got a broken connection
  3435. }
  3436. $temp = substr($buffer,$chunkstart,$chunkend-$chunkstart);
  3437. $chunk_size = hexdec( trim($temp) );
  3438. $chunkstart = $chunkend;
  3439. }
  3440. return $new;
  3441. }
  3442. /**
  3443. * Writes the payload, including HTTP headers, to $this->outgoing_payload.
  3444. *
  3445. * @param string $data HTTP body
  3446. * @param string $cookie_str data for HTTP Cookie header
  3447. * @return void
  3448. * @access private
  3449. */
  3450. function buildPayload($data, $cookie_str = '') {
  3451. // Note: for cURL connections, $this->outgoing_payload is ignored,
  3452. // as is the Content-Length header, but these are still created as
  3453. // debugging guides.
  3454. // add content-length header
  3455. if ($this->request_method != 'GET') {
  3456. $this->setHeader('Content-Length', strlen($data));
  3457. }
  3458. // start building outgoing payload:
  3459. if ($this->proxy) {
  3460. $uri = $this->url;
  3461. } else {
  3462. $uri = $this->uri;
  3463. }
  3464. $req = "$this->request_method $uri HTTP/$this->protocol_version";
  3465. $this->debug("HTTP request: $req");
  3466. $this->outgoing_payload = "$req\r\n";
  3467. // loop thru headers, serializing
  3468. foreach($this->outgoing_headers as $k => $v){
  3469. $hdr = $k.': '.$v;
  3470. $this->debug("HTTP header: $hdr");
  3471. $this->outgoing_payload .= "$hdr\r\n";
  3472. }
  3473. // add any cookies
  3474. if ($cookie_str != '') {
  3475. $hdr = 'Cookie: '.$cookie_str;
  3476. $this->debug("HTTP header: $hdr");
  3477. $this->outgoing_payload .= "$hdr\r\n";
  3478. }
  3479. // header/body separator
  3480. $this->outgoing_payload .= "\r\n";
  3481. // add data
  3482. $this->outgoing_payload .= $data;
  3483. }
  3484. /**
  3485. * sends the SOAP request via HTTP[S]
  3486. *
  3487. * @param string $data message data
  3488. * @param array $cookies cookies to send
  3489. * @return boolean true if OK, false if problem
  3490. * @access private
  3491. */
  3492. function sendRequest($data, $cookies = NULL) {
  3493. // build cookie string
  3494. $cookie_str = $this->getCookiesForRequest($cookies, (($this->scheme == 'ssl') || ($this->scheme == 'https')));
  3495. // build payload
  3496. $this->buildPayload($data, $cookie_str);
  3497. if ($this->io_method() == 'socket') {
  3498. // send payload
  3499. if(!fputs($this->fp, $this->outgoing_payload, strlen($this->outgoing_payload))) {
  3500. $this->setError('couldn\'t write message data to socket');
  3501. $this->debug('couldn\'t write message data to socket');
  3502. return false;
  3503. }
  3504. $this->debug('wrote data to socket, length = ' . strlen($this->outgoing_payload));
  3505. return true;
  3506. } else if ($this->io_method() == 'curl') {
  3507. // set payload
  3508. // cURL does say this should only be the verb, and in fact it
  3509. // turns out that the URI and HTTP version are appended to this, which
  3510. // some servers refuse to work with (so we no longer use this method!)
  3511. //$this->setCurlOption(CURLOPT_CUSTOMREQUEST, $this->outgoing_payload);
  3512. $curl_headers = array();
  3513. foreach($this->outgoing_headers as $k => $v){
  3514. if ($k == 'Connection' || $k == 'Content-Length' || $k == 'Host' || $k == 'Authorization' || $k == 'Proxy-Authorization') {
  3515. $this->debug("Skip cURL header $k: $v");
  3516. } else {
  3517. $curl_headers[] = "$k: $v";
  3518. }
  3519. }
  3520. if ($cookie_str != '') {
  3521. $curl_headers[] = 'Cookie: ' . $cookie_str;
  3522. }
  3523. $this->setCurlOption(CURLOPT_HTTPHEADER, $curl_headers);
  3524. $this->debug('set cURL HTTP headers');
  3525. if ($this->request_method == "POST") {
  3526. $this->setCurlOption(CURLOPT_POST, 1);
  3527. $this->setCurlOption(CURLOPT_POSTFIELDS, $data);
  3528. $this->debug('set cURL POST data');
  3529. } else {
  3530. }
  3531. // insert custom user-set cURL options
  3532. foreach ($this->ch_options as $key => $val) {
  3533. $this->setCurlOption($key, $val);
  3534. }
  3535. $this->debug('set cURL payload');
  3536. return true;
  3537. }
  3538. }
  3539. /**
  3540. * gets the SOAP response via HTTP[S]
  3541. *
  3542. * @return string the response (also sets member variables like incoming_payload)
  3543. * @access private
  3544. */
  3545. function getResponse(){
  3546. $this->incoming_payload = '';
  3547. if ($this->io_method() == 'socket') {
  3548. // loop until headers have been retrieved
  3549. $data = '';
  3550. while (!isset($lb)){
  3551. // We might EOF during header read.
  3552. if(feof($this->fp)) {
  3553. $this->incoming_payload = $data;
  3554. $this->debug('found no headers before EOF after length ' . strlen($data));
  3555. $this->debug("received before EOF:\n" . $data);
  3556. $this->setError('server failed to send headers');
  3557. return false;
  3558. }
  3559. $tmp = fgets($this->fp, 256);
  3560. $tmplen = strlen($tmp);
  3561. $this->debug("read line of $tmplen bytes: " . trim($tmp));
  3562. if ($tmplen == 0) {
  3563. $this->incoming_payload = $data;
  3564. $this->debug('socket read of headers timed out after length ' . strlen($data));
  3565. $this->debug("read before timeout: " . $data);
  3566. $this->setError('socket read of headers timed out');
  3567. return false;
  3568. }
  3569. $data .= $tmp;
  3570. $pos = strpos($data,"\r\n\r\n");
  3571. if($pos > 1){
  3572. $lb = "\r\n";
  3573. } else {
  3574. $pos = strpos($data,"\n\n");
  3575. if($pos > 1){
  3576. $lb = "\n";
  3577. }
  3578. }
  3579. // remove 100 headers
  3580. if (isset($lb) && preg_match('/^HTTP\/1.1 100/',$data)) {
  3581. unset($lb);
  3582. $data = '';
  3583. }//
  3584. }
  3585. // store header data
  3586. $this->incoming_payload .= $data;
  3587. $this->debug('found end of headers after length ' . strlen($data));
  3588. // process headers
  3589. $header_data = trim(substr($data,0,$pos));
  3590. $header_array = explode($lb,$header_data);
  3591. $this->incoming_headers = array();
  3592. $this->incoming_cookies = array();
  3593. foreach($header_array as $header_line){
  3594. $arr = explode(':',$header_line, 2);
  3595. if(count($arr) > 1){
  3596. $header_name = strtolower(trim($arr[0]));
  3597. $this->incoming_headers[$header_name] = trim($arr[1]);
  3598. if ($header_name == 'set-cookie') {
  3599. // TODO: allow multiple cookies from parseCookie
  3600. $cookie = $this->parseCookie(trim($arr[1]));
  3601. if ($cookie) {
  3602. $this->incoming_cookies[] = $cookie;
  3603. $this->debug('found cookie: ' . $cookie['name'] . ' = ' . $cookie['value']);
  3604. } else {
  3605. $this->debug('did not find cookie in ' . trim($arr[1]));
  3606. }
  3607. }
  3608. } else if (isset($header_name)) {
  3609. // append continuation line to previous header
  3610. $this->incoming_headers[$header_name] .= $lb . ' ' . $header_line;
  3611. }
  3612. }
  3613. // loop until msg has been received
  3614. if (isset($this->incoming_headers['transfer-encoding']) && strtolower($this->incoming_headers['transfer-encoding']) == 'chunked') {
  3615. $content_length = 2147483647; // ignore any content-length header
  3616. $chunked = true;
  3617. $this->debug("want to read chunked content");
  3618. } elseif (isset($this->incoming_headers['content-length'])) {
  3619. $content_length = $this->incoming_headers['content-length'];
  3620. $chunked = false;
  3621. $this->debug("want to read content of length $content_length");
  3622. } else {
  3623. $content_length = 2147483647;
  3624. $chunked = false;
  3625. $this->debug("want to read content to EOF");
  3626. }
  3627. $data = '';
  3628. do {
  3629. if ($chunked) {
  3630. $tmp = fgets($this->fp, 256);
  3631. $tmplen = strlen($tmp);
  3632. $this->debug("read chunk line of $tmplen bytes");
  3633. if ($tmplen == 0) {
  3634. $this->incoming_payload = $data;
  3635. $this->debug('socket read of chunk length timed out after length ' . strlen($data));
  3636. $this->debug("read before timeout:\n" . $data);
  3637. $this->setError('socket read of chunk length timed out');
  3638. return false;
  3639. }
  3640. $content_length = hexdec(trim($tmp));
  3641. $this->debug("chunk length $content_length");
  3642. }
  3643. $strlen = 0;
  3644. while (($strlen < $content_length) && (!feof($this->fp))) {
  3645. $readlen = min(8192, $content_length - $strlen);
  3646. $tmp = fread($this->fp, $readlen);
  3647. $tmplen = strlen($tmp);
  3648. $this->debug("read buffer of $tmplen bytes");
  3649. if (($tmplen == 0) && (!feof($this->fp))) {
  3650. $this->incoming_payload = $data;
  3651. $this->debug('socket read of body timed out after length ' . strlen($data));
  3652. $this->debug("read before timeout:\n" . $data);
  3653. $this->setError('socket read of body timed out');
  3654. return false;
  3655. }
  3656. $strlen += $tmplen;
  3657. $data .= $tmp;
  3658. }
  3659. if ($chunked && ($content_length > 0)) {
  3660. $tmp = fgets($this->fp, 256);
  3661. $tmplen = strlen($tmp);
  3662. $this->debug("read chunk terminator of $tmplen bytes");
  3663. if ($tmplen == 0) {
  3664. $this->incoming_payload = $data;
  3665. $this->debug('socket read of chunk terminator timed out after length ' . strlen($data));
  3666. $this->debug("read before timeout:\n" . $data);
  3667. $this->setError('socket read of chunk terminator timed out');
  3668. return false;
  3669. }
  3670. }
  3671. } while ($chunked && ($content_length > 0) && (!feof($this->fp)));
  3672. if (feof($this->fp)) {
  3673. $this->debug('read to EOF');
  3674. }
  3675. $this->debug('read body of length ' . strlen($data));
  3676. $this->incoming_payload .= $data;
  3677. $this->debug('received a total of '.strlen($this->incoming_payload).' bytes of data from server');
  3678. // close filepointer
  3679. if(
  3680. (isset($this->incoming_headers['connection']) && strtolower($this->incoming_headers['connection']) == 'close') ||
  3681. (! $this->persistentConnection) || feof($this->fp)){
  3682. fclose($this->fp);
  3683. $this->fp = false;
  3684. $this->debug('closed socket');
  3685. }
  3686. // connection was closed unexpectedly
  3687. if($this->incoming_payload == ''){
  3688. $this->setError('no response from server');
  3689. return false;
  3690. }
  3691. // decode transfer-encoding
  3692. // if(isset($this->incoming_headers['transfer-encoding']) && strtolower($this->incoming_headers['transfer-encoding']) == 'chunked'){
  3693. // if(!$data = $this->decodeChunked($data, $lb)){
  3694. // $this->setError('Decoding of chunked data failed');
  3695. // return false;
  3696. // }
  3697. //print "<pre>\nde-chunked:\n---------------\n$data\n\n---------------\n</pre>";
  3698. // set decoded payload
  3699. // $this->incoming_payload = $header_data.$lb.$lb.$data;
  3700. // }
  3701. } else if ($this->io_method() == 'curl') {
  3702. // send and receive
  3703. $this->debug('send and receive with cURL');
  3704. $this->incoming_payload = curl_exec($this->ch);
  3705. $data = $this->incoming_payload;
  3706. $cErr = curl_error($this->ch);
  3707. if ($cErr != '') {
  3708. $err = 'cURL ERROR: '.curl_errno($this->ch).': '.$cErr.'<br>';
  3709. // TODO: there is a PHP bug that can cause this to SEGV for CURLINFO_CONTENT_TYPE
  3710. foreach(curl_getinfo($this->ch) as $k => $v){
  3711. $err .= "$k: $v<br>";
  3712. }
  3713. $this->debug($err);
  3714. $this->setError($err);
  3715. curl_close($this->ch);
  3716. return false;
  3717. } else {
  3718. //echo '<pre>';
  3719. //var_dump(curl_getinfo($this->ch));
  3720. //echo '</pre>';
  3721. }
  3722. // close curl
  3723. $this->debug('No cURL error, closing cURL');
  3724. curl_close($this->ch);
  3725. // try removing skippable headers
  3726. $savedata = $data;
  3727. while ($this->isSkippableCurlHeader($data)) {
  3728. $this->debug("Found HTTP header to skip");
  3729. if ($pos = strpos($data,"\r\n\r\n")) {
  3730. $data = ltrim(substr($data,$pos));
  3731. } elseif($pos = strpos($data,"\n\n") ) {
  3732. $data = ltrim(substr($data,$pos));
  3733. }
  3734. }
  3735. if ($data == '') {
  3736. // have nothing left; just remove 100 header(s)
  3737. $data = $savedata;
  3738. while (preg_match('/^HTTP\/1.1 100/',$data)) {
  3739. if ($pos = strpos($data,"\r\n\r\n")) {
  3740. $data = ltrim(substr($data,$pos));
  3741. } elseif($pos = strpos($data,"\n\n") ) {
  3742. $data = ltrim(substr($data,$pos));
  3743. }
  3744. }
  3745. }
  3746. // separate content from HTTP headers
  3747. if ($pos = strpos($data,"\r\n\r\n")) {
  3748. $lb = "\r\n";
  3749. } elseif( $pos = strpos($data,"\n\n")) {
  3750. $lb = "\n";
  3751. } else {
  3752. $this->debug('no proper separation of headers and document');
  3753. $this->setError('no proper separation of headers and document');
  3754. return false;
  3755. }
  3756. $header_data = trim(substr($data,0,$pos));
  3757. $header_array = explode($lb,$header_data);
  3758. $data = ltrim(substr($data,$pos));
  3759. $this->debug('found proper separation of headers and document');
  3760. $this->debug('cleaned data, stringlen: '.strlen($data));
  3761. // clean headers
  3762. foreach ($header_array as $header_line) {
  3763. $arr = explode(':',$header_line,2);
  3764. if(count($arr) > 1){
  3765. $header_name = strtolower(trim($arr[0]));
  3766. $this->incoming_headers[$header_name] = trim($arr[1]);
  3767. if ($header_name == 'set-cookie') {
  3768. // TODO: allow multiple cookies from parseCookie
  3769. $cookie = $this->parseCookie(trim($arr[1]));
  3770. if ($cookie) {
  3771. $this->incoming_cookies[] = $cookie;
  3772. $this->debug('found cookie: ' . $cookie['name'] . ' = ' . $cookie['value']);
  3773. } else {
  3774. $this->debug('did not find cookie in ' . trim($arr[1]));
  3775. }
  3776. }
  3777. } else if (isset($header_name)) {
  3778. // append continuation line to previous header
  3779. $this->incoming_headers[$header_name] .= $lb . ' ' . $header_line;
  3780. }
  3781. }
  3782. }
  3783. $this->response_status_line = $header_array[0];
  3784. $arr = explode(' ', $this->response_status_line, 3);
  3785. $http_version = $arr[0];
  3786. $http_status = intval($arr[1]);
  3787. $http_reason = count($arr) > 2 ? $arr[2] : '';
  3788. // see if we need to resend the request with http digest authentication
  3789. if (isset($this->incoming_headers['location']) && ($http_status == 301 || $http_status == 302)) {
  3790. $this->debug("Got $http_status $http_reason with Location: " . $this->incoming_headers['location']);
  3791. $this->setURL($this->incoming_headers['location']);
  3792. $this->tryagain = true;
  3793. return false;
  3794. }
  3795. // see if we need to resend the request with http digest authentication
  3796. if (isset($this->incoming_headers['www-authenticate']) && $http_status == 401) {
  3797. $this->debug("Got 401 $http_reason with WWW-Authenticate: " . $this->incoming_headers['www-authenticate']);
  3798. if (strstr($this->incoming_headers['www-authenticate'], "Digest ")) {
  3799. $this->debug('Server wants digest authentication');
  3800. // remove "Digest " from our elements
  3801. $digestString = str_replace('Digest ', '', $this->incoming_headers['www-authenticate']);
  3802. // parse elements into array
  3803. $digestElements = explode(',', $digestString);
  3804. foreach ($digestElements as $val) {
  3805. $tempElement = explode('=', trim($val), 2);
  3806. $digestRequest[$tempElement[0]] = str_replace("\"", '', $tempElement[1]);
  3807. }
  3808. // should have (at least) qop, realm, nonce
  3809. if (isset($digestRequest['nonce'])) {
  3810. $this->setCredentials($this->username, $this->password, 'digest', $digestRequest);
  3811. $this->tryagain = true;
  3812. return false;
  3813. }
  3814. }
  3815. $this->debug('HTTP authentication failed');
  3816. $this->setError('HTTP authentication failed');
  3817. return false;
  3818. }
  3819. if (
  3820. ($http_status >= 300 && $http_status <= 307) ||
  3821. ($http_status >= 400 && $http_status <= 417) ||
  3822. ($http_status >= 501 && $http_status <= 505)
  3823. ) {
  3824. $this->setError("Unsupported HTTP response status $http_status $http_reason (soapclient->response has contents of the response)");
  3825. return false;
  3826. }
  3827. // decode content-encoding
  3828. if(isset($this->incoming_headers['content-encoding']) && $this->incoming_headers['content-encoding'] != ''){
  3829. if(strtolower($this->incoming_headers['content-encoding']) == 'deflate' || strtolower($this->incoming_headers['content-encoding']) == 'gzip'){
  3830. // if decoding works, use it. else assume data wasn't gzencoded
  3831. if(function_exists('gzinflate')){
  3832. //$timer->setMarker('starting decoding of gzip/deflated content');
  3833. // IIS 5 requires gzinflate instead of gzuncompress (similar to IE 5 and gzdeflate v. gzcompress)
  3834. // this means there are no Zlib headers, although there should be
  3835. $this->debug('The gzinflate function exists');
  3836. $datalen = strlen($data);
  3837. if ($this->incoming_headers['content-encoding'] == 'deflate') {
  3838. if ($degzdata = @gzinflate($data)) {
  3839. $data = $degzdata;
  3840. $this->debug('The payload has been inflated to ' . strlen($data) . ' bytes');
  3841. if (strlen($data) < $datalen) {
  3842. // test for the case that the payload has been compressed twice
  3843. $this->debug('The inflated payload is smaller than the gzipped one; try again');
  3844. if ($degzdata = @gzinflate($data)) {
  3845. $data = $degzdata;
  3846. $this->debug('The payload has been inflated again to ' . strlen($data) . ' bytes');
  3847. }
  3848. }
  3849. } else {
  3850. $this->debug('Error using gzinflate to inflate the payload');
  3851. $this->setError('Error using gzinflate to inflate the payload');
  3852. }
  3853. } elseif ($this->incoming_headers['content-encoding'] == 'gzip') {
  3854. if ($degzdata = @gzinflate(substr($data, 10))) { // do our best
  3855. $data = $degzdata;
  3856. $this->debug('The payload has been un-gzipped to ' . strlen($data) . ' bytes');
  3857. if (strlen($data) < $datalen) {
  3858. // test for the case that the payload has been compressed twice
  3859. $this->debug('The un-gzipped payload is smaller than the gzipped one; try again');
  3860. if ($degzdata = @gzinflate(substr($data, 10))) {
  3861. $data = $degzdata;
  3862. $this->debug('The payload has been un-gzipped again to ' . strlen($data) . ' bytes');
  3863. }
  3864. }
  3865. } else {
  3866. $this->debug('Error using gzinflate to un-gzip the payload');
  3867. $this->setError('Error using gzinflate to un-gzip the payload');
  3868. }
  3869. }
  3870. //$timer->setMarker('finished decoding of gzip/deflated content');
  3871. //print "<xmp>\nde-inflated:\n---------------\n$data\n-------------\n</xmp>";
  3872. // set decoded payload
  3873. $this->incoming_payload = $header_data.$lb.$lb.$data;
  3874. } else {
  3875. $this->debug('The server sent compressed data. Your php install must have the Zlib extension compiled in to support this.');
  3876. $this->setError('The server sent compressed data. Your php install must have the Zlib extension compiled in to support this.');
  3877. }
  3878. } else {
  3879. $this->debug('Unsupported Content-Encoding ' . $this->incoming_headers['content-encoding']);
  3880. $this->setError('Unsupported Content-Encoding ' . $this->incoming_headers['content-encoding']);
  3881. }
  3882. } else {
  3883. $this->debug('No Content-Encoding header');
  3884. }
  3885. if(strlen($data) == 0){
  3886. $this->debug('no data after headers!');
  3887. $this->setError('no data present after HTTP headers');
  3888. return false;
  3889. }
  3890. return $data;
  3891. }
  3892. /**
  3893. * sets the content-type for the SOAP message to be sent
  3894. *
  3895. * @param string $type the content type, MIME style
  3896. * @param mixed $charset character set used for encoding (or false)
  3897. * @access public
  3898. */
  3899. function setContentType($type, $charset = false) {
  3900. $this->setHeader('Content-Type', $type . ($charset ? '; charset=' . $charset : ''));
  3901. }
  3902. /**
  3903. * specifies that an HTTP persistent connection should be used
  3904. *
  3905. * @return boolean whether the request was honored by this method.
  3906. * @access public
  3907. */
  3908. function usePersistentConnection(){
  3909. if (isset($this->outgoing_headers['Accept-Encoding'])) {
  3910. return false;
  3911. }
  3912. $this->protocol_version = '1.1';
  3913. $this->persistentConnection = true;
  3914. $this->setHeader('Connection', 'Keep-Alive');
  3915. return true;
  3916. }
  3917. /**
  3918. * parse an incoming Cookie into it's parts
  3919. *
  3920. * @param string $cookie_str content of cookie
  3921. * @return array with data of that cookie
  3922. * @access private
  3923. */
  3924. /*
  3925. * TODO: allow a Set-Cookie string to be parsed into multiple cookies
  3926. */
  3927. function parseCookie($cookie_str) {
  3928. $cookie_str = str_replace('; ', ';', $cookie_str) . ';';
  3929. $data = preg_split('/;/', $cookie_str);
  3930. $value_str = $data[0];
  3931. $cookie_param = 'domain=';
  3932. $start = strpos($cookie_str, $cookie_param);
  3933. if ($start > 0) {
  3934. $domain = substr($cookie_str, $start + strlen($cookie_param));
  3935. $domain = substr($domain, 0, strpos($domain, ';'));
  3936. } else {
  3937. $domain = '';
  3938. }
  3939. $cookie_param = 'expires=';
  3940. $start = strpos($cookie_str, $cookie_param);
  3941. if ($start > 0) {
  3942. $expires = substr($cookie_str, $start + strlen($cookie_param));
  3943. $expires = substr($expires, 0, strpos($expires, ';'));
  3944. } else {
  3945. $expires = '';
  3946. }
  3947. $cookie_param = 'path=';
  3948. $start = strpos($cookie_str, $cookie_param);
  3949. if ( $start > 0 ) {
  3950. $path = substr($cookie_str, $start + strlen($cookie_param));
  3951. $path = substr($path, 0, strpos($path, ';'));
  3952. } else {
  3953. $path = '/';
  3954. }
  3955. $cookie_param = ';secure;';
  3956. if (strpos($cookie_str, $cookie_param) !== FALSE) {
  3957. $secure = true;
  3958. } else {
  3959. $secure = false;
  3960. }
  3961. $sep_pos = strpos($value_str, '=');
  3962. if ($sep_pos) {
  3963. $name = substr($value_str, 0, $sep_pos);
  3964. $value = substr($value_str, $sep_pos + 1);
  3965. $cookie= array( 'name' => $name,
  3966. 'value' => $value,
  3967. 'domain' => $domain,
  3968. 'path' => $path,
  3969. 'expires' => $expires,
  3970. 'secure' => $secure
  3971. );
  3972. return $cookie;
  3973. }
  3974. return false;
  3975. }
  3976. /**
  3977. * sort out cookies for the current request
  3978. *
  3979. * @param array $cookies array with all cookies
  3980. * @param boolean $secure is the send-content secure or not?
  3981. * @return string for Cookie-HTTP-Header
  3982. * @access private
  3983. */
  3984. function getCookiesForRequest($cookies, $secure=false) {
  3985. $cookie_str = '';
  3986. if ((! is_null($cookies)) && (is_array($cookies))) {
  3987. foreach ($cookies as $cookie) {
  3988. if (! is_array($cookie)) {
  3989. continue;
  3990. }
  3991. $this->debug("check cookie for validity: ".$cookie['name'].'='.$cookie['value']);
  3992. if ((isset($cookie['expires'])) && (! empty($cookie['expires']))) {
  3993. if (strtotime($cookie['expires']) <= time()) {
  3994. $this->debug('cookie has expired');
  3995. continue;
  3996. }
  3997. }
  3998. if ((isset($cookie['domain'])) && (! empty($cookie['domain']))) {
  3999. $domain = preg_quote($cookie['domain']);
  4000. if (! preg_match("'.*$domain$'i", $this->host)) {
  4001. $this->debug('cookie has different domain');
  4002. continue;
  4003. }
  4004. }
  4005. if ((isset($cookie['path'])) && (! empty($cookie['path']))) {
  4006. $path = preg_quote($cookie['path']);
  4007. if (! preg_match("'^$path.*'i", $this->path)) {
  4008. $this->debug('cookie is for a different path');
  4009. continue;
  4010. }
  4011. }
  4012. if ((! $secure) && (isset($cookie['secure'])) && ($cookie['secure'])) {
  4013. $this->debug('cookie is secure, transport is not');
  4014. continue;
  4015. }
  4016. $cookie_str .= $cookie['name'] . '=' . $cookie['value'] . '; ';
  4017. $this->debug('add cookie to Cookie-String: ' . $cookie['name'] . '=' . $cookie['value']);
  4018. }
  4019. }
  4020. return $cookie_str;
  4021. }
  4022. }
  4023. ?><?php
  4024. /*
  4025. Modification information for LGPL compliance
  4026. r58622 - 2010-10-22 18:18:59 -0700 (Fri, 22 Oct 2010) - engsvnbuild - Author: lam <lam@198.18.142.201>
  4027. bug 40066
  4028. r58361 - 2010-09-29 16:59:02 -0700 (Wed, 29 Sep 2010) - kjing - Author: Jenny Gonsalves <jenny@sugarcrm.com>
  4029. Merging with maint_6_0_1 (svn merge -r 58250:58342)
  4030. r57813 - 2010-08-19 10:34:44 -0700 (Thu, 19 Aug 2010) - kjing - Author: John Mertic <jmertic@sugarcrm.com>
  4031. Bug 39085 - When loading the opposite search panel via ajax on the ListViews, call the index action instead of the ListView action to avoid touching pre-MVC code by accident.
  4032. r57707 - 2010-08-10 12:26:13 -0700 (Tue, 10 Aug 2010) - kjing - Author: Stanislav Malyshev <smalyshev@gmail.com>
  4033. fix SOAP calls with no parameters
  4034. r56990 - 2010-06-16 13:05:36 -0700 (Wed, 16 Jun 2010) - kjing - snapshot "Mango" svn branch to a new one for GitHub sync
  4035. r56989 - 2010-06-16 13:01:33 -0700 (Wed, 16 Jun 2010) - kjing - defunt "Mango" svn dev branch before github cutover
  4036. r55980 - 2010-04-19 13:31:28 -0700 (Mon, 19 Apr 2010) - kjing - create Mango (6.1) based on windex
  4037. r51719 - 2009-10-22 10:18:00 -0700 (Thu, 22 Oct 2009) - mitani - Converted to Build 3 tags and updated the build system
  4038. r51634 - 2009-10-19 13:32:22 -0700 (Mon, 19 Oct 2009) - mitani - Windex is the branch for Sugar Sales 1.0 development
  4039. r51508 - 2009-10-14 07:40:23 -0700 (Wed, 14 Oct 2009) - jmertic - More fallout fixes from the PHP 5.3 ereg to preg changes.
  4040. r51455 - 2009-10-13 07:56:48 -0700 (Tue, 13 Oct 2009) - jmertic - Bug 33202 - Enable install of SugarCRM on PHP 5.3.0, asserting that the minimum supported version is PHP 5.2.x.
  4041. r51443 - 2009-10-12 13:34:36 -0700 (Mon, 12 Oct 2009) - jmertic - Bug 33332 - Made application PHP 5.3 compliant with E_DEPRECATED warnings on by:
  4042. - Changing all ereg function to either preg or simple string based ones
  4043. - No more references to magic quotes.
  4044. - Change all the session_unregister() functions to just unset() the correct session variable instead.
  4045. r50375 - 2009-08-24 18:07:43 -0700 (Mon, 24 Aug 2009) - dwong - branch kobe2 from tokyo r50372
  4046. r45763 - 2009-04-01 12:16:18 -0700 (Wed, 01 Apr 2009) - majed - Removed half of the require_once and include_onces in the product that were redundant or could be handled easily by the auto loader
  4047. r45680 - 2009-03-30 14:34:35 -0700 (Mon, 30 Mar 2009) - Samir Gandhi - modifeid serializeSchema to generate WS-I compliant WSDL
  4048. r42807 - 2008-12-29 11:16:59 -0800 (Mon, 29 Dec 2008) - dwong - Branch from trunk/sugarcrm r42806 to branches/tokyo/sugarcrm
  4049. r42645 - 2008-12-18 13:41:08 -0800 (Thu, 18 Dec 2008) - awu - merging maint_5_2_0 rev41336:HEAD to trunk
  4050. r41647 - 2008-11-11 17:44:30 -0800 (Tue, 11 Nov 2008) - majed - Fixes a few bugs
  4051. r41596 - 2008-11-10 19:20:04 -0800 (Mon, 10 Nov 2008) - Samir Gandhi - modified to set $method in the code
  4052. r41558 - 2008-11-10 14:35:34 -0800 (Mon, 10 Nov 2008) - majed - changes nusoap to allow for registering classes
  4053. r39619 - 2008-09-09 13:41:34 -0700 (Tue, 09 Sep 2008) - jmertic - Bug 24827 - Remove all instances where we return a new object and assign it by reference, since this is deprecated in PHP 5 and emits E_DEPRECATED errors in PHP 5.3.
  4054. Touched:
  4055. - data/SugarBean.php
  4056. - include/domit/php_http_client_generic.php
  4057. - include/domit/php_http_connector.php
  4058. - include/domit/testing_domit.php
  4059. - include/domit/xml_domit_getelementsbypath.php
  4060. - include/domit/xml_domit_lite_parser.php
  4061. - include/domit/xml_domit_nodemaps.php
  4062. - include/domit/xml_domit_parser.php
  4063. - include/domit/xml_domit_shared.php
  4064. - include/generic/SugarWidgets/SugarWidgetField.php
  4065. - include/generic/SugarWidgets/SugarWidgetReportField.php
  4066. - include/ListView/ProcessView.php
  4067. - include/nusoap/class.soapclient.php
  4068. - include/nusoap/nusoap.php
  4069. - include/nusoap/nusoapmime.php
  4070. - include/Pear/HTML_Safe/Safe.php
  4071. - include/Pear/XML_HTMLSax3/HTMLSax3.php
  4072. - modules/Administration/RebuildWorkFlow.php
  4073. - modules/Expressions/RelateSelector.php
  4074. - modules/Reports/templates/templates_reports.php
  4075. - modules/WorkFlow/Delete.php
  4076. - modules/WorkFlow/Save.php
  4077. - modules/WorkFlow/SaveSequence.php
  4078. - modules/WorkFlow/WorkFlow.php
  4079. - modules/WorkFlowActionShells/CreateStep1.php
  4080. - modules/WorkFlowActionShells/CreateStep2.php
  4081. - modules/WorkFlowActionShells/Save.php
  4082. - modules/WorkFlowActionShells/WorkFlowActionShell.php
  4083. - modules/WorkFlowAlerts/Save.php
  4084. - modules/WorkFlowAlerts/WorkFlowAlert.php
  4085. - modules/WorkFlowAlertShells/DetailView.php
  4086. - modules/WorkFlowAlertShells/WorkFlowAlertShell.php
  4087. - modules/WorkFlowTriggerShells/CreateStep1.php
  4088. - modules/WorkFlowTriggerShells/CreateStepFilter.php
  4089. - modules/WorkFlowTriggerShells/SaveFilter.php
  4090. - modules/WorkFlowTriggerShells/WorkFlowTriggerShell.php
  4091. - soap/SoapHelperFunctions.php
  4092. - test/modules/DynamicFields/DynamicFields_Bug24095_test.php
  4093. - test/simpletest/browser.php
  4094. - test/simpletest/default_reporter.php
  4095. - test/simpletest/detached.php
  4096. - test/simpletest/eclipse.php
  4097. - test/simpletest/expectation.php
  4098. - test/simpletest/extensions/pear_test_case.php
  4099. - test/simpletest/form.php
  4100. - test/simpletest/http.php
  4101. - test/simpletest/mock_objects.php
  4102. - test/simpletest/page.php
  4103. - test/simpletest/parser.php
  4104. - test/simpletest/remote.php
  4105. - test/simpletest/shell_tester.php
  4106. - test/simpletest/simple_test.php
  4107. - test/simpletest/simpletest.php
  4108. - test/simpletest/test/acceptance_test.php
  4109. - test/simpletest/test/adapter_test.php
  4110. - test/simpletest/test/authentication_test.php
  4111. - test/simpletest/test/browser_test.php
  4112. - test/simpletest/test/collector_test.php
  4113. - test/simpletest/test/compatibility_test.php
  4114. - test/simpletest/test/detached_test.php
  4115. - test/simpletest/test/eclipse_test.php
  4116. - test/simpletest/test/encoding_test.php
  4117. - test/simpletest/test/errors_test.php
  4118. - test/simpletest/test/expectation_test.php
  4119. - test/simpletest/test/form_test.php
  4120. - test/simpletest/test/frames_test.php
  4121. - test/simpletest/test/http_test.php
  4122. - test/simpletest/test/live_test.php
  4123. - test/simpletest/test/mock_objects_test.php
  4124. - test/simpletest/test/page_test.php
  4125. - test/simpletest/test/parse_error_test.php
  4126. - test/simpletest/test/parser_test.php
  4127. - test/simpletest/test/remote_test.php
  4128. - test/simpletest/test/shell_test.php
  4129. - test/simpletest/test/shell_tester_test.php
  4130. - test/simpletest/test/simpletest_test.php
  4131. - test/simpletest/test/site/page_request.php
  4132. - test/simpletest/test/tag_test.php
  4133. - test/simpletest/test/unit_tester_test.php
  4134. - test/simpletest/test/user_agent_test.php
  4135. - test/simpletest/test/visual_test.php
  4136. - test/simpletest/test/xml_test.php
  4137. - test/simpletest/test_case.php
  4138. - test/simpletest/ui/array_reporter/test.php
  4139. - test/simpletest/ui/recorder/test.php
  4140. - test/simpletest/unit_tester.php
  4141. - test/simpletest/url.php
  4142. - test/simpletest/user_agent.php
  4143. - test/simpletest/web_tester.php
  4144. - test/spikephpcoverage/src/PEAR.php
  4145. - test/spikephpcoverage/src/util/Utility.php
  4146. - test/spikephpcoverage/src/XML/Parser.php
  4147. - test/spikephpcoverage/src/XML/Parser/Simple.php
  4148. - test/test_utilities/SugarTest_SimpleBrowser.php
  4149. r38362 - 2008-07-28 14:06:59 -0700 (Mon, 28 Jul 2008) - roger - bug: 23897. Using print_r when using the debug statement in nusoap will print out the statements to the screen if the call is coming from the UI.
  4150. r38300 - 2008-07-25 13:33:43 -0700 (Fri, 25 Jul 2008) - Samir Gandhi - put the debug in parseresponse function
  4151. r38293 - 2008-07-25 12:32:34 -0700 (Fri, 25 Jul 2008) - Samir Gandhi - to put all the debug statements return value in the call function
  4152. r36824 - 2008-06-18 09:26:11 -0700 (Wed, 18 Jun 2008) - roger - bug: 21832
  4153. r26422 - 2007-09-05 17:29:12 -0700 (Wed, 05 Sep 2007) - majed - migrate from beta 1 to trunk
  4154. r15787 - 2006-08-10 10:14:41 -0700 (Thu, 10 Aug 2006) - roger - RRS: bug 7961
  4155. r14701 - 2006-07-17 13:37:26 -0700 (Mon, 17 Jul 2006) - roger - RRS: bug 5801
  4156. r13782 - 2006-06-06 10:58:55 -0700 (Tue, 06 Jun 2006) - majed - changes entry point code
  4157. r11466 - 2006-02-01 15:49:47 -0800 (Wed, 01 Feb 2006) - jacob - Adding extra !empty check to get around a PHP warning.
  4158. r11115 - 2006-01-17 14:54:45 -0800 (Tue, 17 Jan 2006) - majed - add entry point validation
  4159. r10585 - 2005-12-13 14:42:26 -0800 (Tue, 13 Dec 2005) - majed - adds new license mechanisim
  4160. r10170 - 2005-12-05 18:37:46 -0800 (Mon, 05 Dec 2005) - majed - fixes various issues
  4161. r8999 - 2005-11-04 05:26:49 -0800 (Fri, 04 Nov 2005) - roger - When nusoap was upgraded we had an issue with the user's default language not being populated during a soap request. I determined the reason this was happening and have checked in the corresponding change to nusoap.
  4162. r8991 - 2005-11-03 19:07:25 -0800 (Thu, 03 Nov 2005) - majed - fixes nusoap issue
  4163. r8846 - 2005-10-31 11:01:12 -0800 (Mon, 31 Oct 2005) - majed - new version of nusoap
  4164. r7905 - 2005-09-21 19:12:57 -0700 (Wed, 21 Sep 2005) - majed - restores old nusoap pre & with a few fixes
  4165. r7861 - 2005-09-20 15:40:25 -0700 (Tue, 20 Sep 2005) - majed - & fix for 3.5.1
  4166. r7452 - 2005-08-17 11:32:34 -0700 (Wed, 17 Aug 2005) - majed - changes soap to nusoap
  4167. r5820 - 2005-06-21 14:22:24 -0700 (Tue, 21 Jun 2005) - majed - fixes issues with nusoap and with custom fields
  4168. r5462 - 2005-05-25 13:50:11 -0700 (Wed, 25 May 2005) - majed - upgraded nusoap to .6.9
  4169. r5104 - 2005-05-04 15:33:41 -0700 (Wed, 04 May 2005) - majed - gets rid of HTTP_GET_VARS and what not which has been deprecated
  4170. r573 - 2004-09-04 13:03:32 -0700 (Sat, 04 Sep 2004) - sugarclint - undoing copyrights added in inadvertantly. --clint
  4171. r546 - 2004-09-03 11:49:38 -0700 (Fri, 03 Sep 2004) - sugarmsi - removed echo count
  4172. r354 - 2004-08-02 23:00:37 -0700 (Mon, 02 Aug 2004) - sugarjacob - Adding Soap
  4173. */
  4174. /**
  4175. *
  4176. * nusoap_server allows the user to create a SOAP server
  4177. * that is capable of receiving messages and returning responses
  4178. *
  4179. * @author Dietrich Ayala <dietrich@ganx4.com>
  4180. * @author Scott Nichol <snichol@users.sourceforge.net>
  4181. * @access public
  4182. */
  4183. class nusoap_server extends nusoap_base {
  4184. /**
  4185. * HTTP headers of request
  4186. * @var array
  4187. * @access private
  4188. */
  4189. var $headers = array();
  4190. /**
  4191. * HTTP request
  4192. * @var string
  4193. * @access private
  4194. */
  4195. var $request = '';
  4196. /**
  4197. * SOAP headers from request (incomplete namespace resolution; special characters not escaped) (text)
  4198. * @var string
  4199. * @access public
  4200. */
  4201. var $requestHeaders = '';
  4202. /**
  4203. * SOAP Headers from request (parsed)
  4204. * @var mixed
  4205. * @access public
  4206. */
  4207. var $requestHeader = NULL;
  4208. /**
  4209. * SOAP body request portion (incomplete namespace resolution; special characters not escaped) (text)
  4210. * @var string
  4211. * @access public
  4212. */
  4213. var $document = '';
  4214. /**
  4215. * SOAP payload for request (text)
  4216. * @var string
  4217. * @access public
  4218. */
  4219. var $requestSOAP = '';
  4220. /**
  4221. * requested method namespace URI
  4222. * @var string
  4223. * @access private
  4224. */
  4225. var $methodURI = '';
  4226. /**
  4227. * name of method requested
  4228. * @var string
  4229. * @access private
  4230. */
  4231. var $methodname = '';
  4232. /**
  4233. * method parameters from request
  4234. * @var array
  4235. * @access private
  4236. */
  4237. var $methodparams = array();
  4238. /**
  4239. * SOAP Action from request
  4240. * @var string
  4241. * @access private
  4242. */
  4243. var $SOAPAction = '';
  4244. /**
  4245. * character set encoding of incoming (request) messages
  4246. * @var string
  4247. * @access public
  4248. */
  4249. var $xml_encoding = '';
  4250. /**
  4251. * toggles whether the parser decodes element content w/ utf8_decode()
  4252. * @var boolean
  4253. * @access public
  4254. */
  4255. var $decode_utf8 = false;
  4256. /**
  4257. * HTTP headers of response
  4258. * @var array
  4259. * @access public
  4260. */
  4261. var $outgoing_headers = array();
  4262. /**
  4263. * HTTP response
  4264. * @var string
  4265. * @access private
  4266. */
  4267. var $response = '';
  4268. /**
  4269. * SOAP headers for response (text or array of soapval or associative array)
  4270. * @var mixed
  4271. * @access public
  4272. */
  4273. var $responseHeaders = '';
  4274. /**
  4275. * SOAP payload for response (text)
  4276. * @var string
  4277. * @access private
  4278. */
  4279. var $responseSOAP = '';
  4280. /**
  4281. * method return value to place in response
  4282. * @var mixed
  4283. * @access private
  4284. */
  4285. var $methodreturn = false;
  4286. /**
  4287. * whether $methodreturn is a string of literal XML
  4288. * @var boolean
  4289. * @access public
  4290. */
  4291. var $methodreturnisliteralxml = false;
  4292. /**
  4293. * SOAP fault for response (or false)
  4294. * @var mixed
  4295. * @access private
  4296. */
  4297. var $fault = false;
  4298. /**
  4299. * text indication of result (for debugging)
  4300. * @var string
  4301. * @access private
  4302. */
  4303. var $result = 'successful';
  4304. /**
  4305. * assoc array of operations => opData; operations are added by the register()
  4306. * method or by parsing an external WSDL definition
  4307. * @var array
  4308. * @access private
  4309. */
  4310. var $operations = array();
  4311. /**
  4312. * wsdl instance (if one)
  4313. * @var mixed
  4314. * @access private
  4315. */
  4316. var $wsdl = false;
  4317. /**
  4318. * URL for WSDL (if one)
  4319. * @var mixed
  4320. * @access private
  4321. */
  4322. var $externalWSDLURL = false;
  4323. /**
  4324. * whether to append debug to response as XML comment
  4325. * @var boolean
  4326. * @access public
  4327. */
  4328. var $debug_flag = false;
  4329. /**
  4330. * constructor
  4331. * the optional parameter is a path to a WSDL file that you'd like to bind the server instance to.
  4332. *
  4333. * @param mixed $wsdl file path or URL (string), or wsdl instance (object)
  4334. * @access public
  4335. */
  4336. function nusoap_server($wsdl=false){
  4337. parent::nusoap_base();
  4338. // turn on debugging?
  4339. global $debug;
  4340. global $HTTP_SERVER_VARS;
  4341. if (isset($_SERVER)) {
  4342. $this->debug("_SERVER is defined:");
  4343. $this->appendDebug($this->varDump($_SERVER));
  4344. } elseif (isset($HTTP_SERVER_VARS)) {
  4345. $this->debug("HTTP_SERVER_VARS is defined:");
  4346. $this->appendDebug($this->varDump($HTTP_SERVER_VARS));
  4347. } else {
  4348. $this->debug("Neither _SERVER nor HTTP_SERVER_VARS is defined.");
  4349. }
  4350. if (isset($debug)) {
  4351. $this->debug("In nusoap_server, set debug_flag=$debug based on global flag");
  4352. $this->debug_flag = $debug;
  4353. } elseif (isset($_SERVER['QUERY_STRING'])) {
  4354. $qs = explode('&', $_SERVER['QUERY_STRING']);
  4355. foreach ($qs as $v) {
  4356. if (substr($v, 0, 6) == 'debug=') {
  4357. $this->debug("In nusoap_server, set debug_flag=" . substr($v, 6) . " based on query string #1");
  4358. $this->debug_flag = substr($v, 6);
  4359. }
  4360. }
  4361. } elseif (isset($HTTP_SERVER_VARS['QUERY_STRING'])) {
  4362. $qs = explode('&', $HTTP_SERVER_VARS['QUERY_STRING']);
  4363. foreach ($qs as $v) {
  4364. if (substr($v, 0, 6) == 'debug=') {
  4365. $this->debug("In nusoap_server, set debug_flag=" . substr($v, 6) . " based on query string #2");
  4366. $this->debug_flag = substr($v, 6);
  4367. }
  4368. }
  4369. }
  4370. // wsdl
  4371. if($wsdl){
  4372. $this->debug("In nusoap_server, WSDL is specified");
  4373. if (is_object($wsdl) && (get_class($wsdl) == 'wsdl')) {
  4374. $this->wsdl = $wsdl;
  4375. $this->externalWSDLURL = $this->wsdl->wsdl;
  4376. $this->debug('Use existing wsdl instance from ' . $this->externalWSDLURL);
  4377. } else {
  4378. $this->debug('Create wsdl from ' . $wsdl);
  4379. $this->wsdl = new wsdl($wsdl);
  4380. $this->externalWSDLURL = $wsdl;
  4381. }
  4382. $this->appendDebug($this->wsdl->getDebug());
  4383. $this->wsdl->clearDebug();
  4384. if($err = $this->wsdl->getError()){
  4385. die('WSDL ERROR: '.$err);
  4386. }
  4387. }
  4388. }
  4389. /**
  4390. * processes request and returns response
  4391. *
  4392. * @param string $data usually is the value of $HTTP_RAW_POST_DATA
  4393. * @access public
  4394. */
  4395. function service($data){
  4396. global $HTTP_SERVER_VARS;
  4397. if (isset($_SERVER['REQUEST_METHOD'])) {
  4398. $rm = $_SERVER['REQUEST_METHOD'];
  4399. } elseif (isset($HTTP_SERVER_VARS['REQUEST_METHOD'])) {
  4400. $rm = $HTTP_SERVER_VARS['REQUEST_METHOD'];
  4401. } else {
  4402. $rm = '';
  4403. }
  4404. if (isset($_SERVER['QUERY_STRING'])) {
  4405. $qs = $_SERVER['QUERY_STRING'];
  4406. } elseif (isset($HTTP_SERVER_VARS['QUERY_STRING'])) {
  4407. $qs = $HTTP_SERVER_VARS['QUERY_STRING'];
  4408. } else {
  4409. $qs = '';
  4410. }
  4411. $this->debug("In service, request method=$rm query string=$qs strlen(\$data)=" . strlen($data));
  4412. if ($rm == 'POST') {
  4413. $this->debug("In service, invoke the request");
  4414. $this->parse_request($data);
  4415. if (! $this->fault) {
  4416. $this->invoke_method();
  4417. }
  4418. if (! $this->fault) {
  4419. $this->serialize_return();
  4420. }
  4421. $this->send_response();
  4422. } elseif (preg_match('/wsdl/', $qs) ){
  4423. $this->debug("In service, this is a request for WSDL");
  4424. if ($this->externalWSDLURL){
  4425. if (strpos($this->externalWSDLURL, "http://") !== false) { // assume URL
  4426. $this->debug("In service, re-direct for WSDL");
  4427. header('Location: '.$this->externalWSDLURL);
  4428. } else { // assume file
  4429. $this->debug("In service, use file passthru for WSDL");
  4430. header("Content-Type: text/xml\r\n");
  4431. $pos = strpos($this->externalWSDLURL, "file://");
  4432. if ($pos === false) {
  4433. $filename = $this->externalWSDLURL;
  4434. } else {
  4435. $filename = substr($this->externalWSDLURL, $pos + 7);
  4436. }
  4437. $fp = fopen($this->externalWSDLURL, 'r');
  4438. fpassthru($fp);
  4439. }
  4440. } elseif ($this->wsdl) {
  4441. $this->debug("In service, serialize WSDL");
  4442. header("Content-Type: text/xml; charset=ISO-8859-1\r\n");
  4443. print $this->wsdl->serialize($this->debug_flag);
  4444. if ($this->debug_flag) {
  4445. $this->debug('wsdl:');
  4446. $this->appendDebug($this->varDump($this->wsdl));
  4447. print $this->getDebugAsXMLComment();
  4448. }
  4449. } else {
  4450. $this->debug("In service, there is no WSDL");
  4451. header("Content-Type: text/html; charset=ISO-8859-1\r\n");
  4452. print "This service does not provide WSDL";
  4453. }
  4454. } elseif ($this->wsdl) {
  4455. $this->debug("In service, return Web description");
  4456. print $this->wsdl->webDescription();
  4457. } else {
  4458. $this->debug("In service, no Web description");
  4459. header("Content-Type: text/html; charset=ISO-8859-1\r\n");
  4460. print "This service does not provide a Web description";
  4461. }
  4462. }
  4463. /**
  4464. * parses HTTP request headers.
  4465. *
  4466. * The following fields are set by this function (when successful)
  4467. *
  4468. * headers
  4469. * request
  4470. * xml_encoding
  4471. * SOAPAction
  4472. *
  4473. * @access private
  4474. */
  4475. function parse_http_headers() {
  4476. global $HTTP_SERVER_VARS;
  4477. $this->request = '';
  4478. $this->SOAPAction = '';
  4479. if(function_exists('getallheaders')){
  4480. $this->debug("In parse_http_headers, use getallheaders");
  4481. $headers = getallheaders();
  4482. foreach($headers as $k=>$v){
  4483. $k = strtolower($k);
  4484. $this->headers[$k] = $v;
  4485. $this->request .= "$k: $v\r\n";
  4486. $this->debug("$k: $v");
  4487. }
  4488. // get SOAPAction header
  4489. if(isset($this->headers['soapaction'])){
  4490. $this->SOAPAction = str_replace('"','',$this->headers['soapaction']);
  4491. }
  4492. // get the character encoding of the incoming request
  4493. if(isset($this->headers['content-type']) && strpos($this->headers['content-type'],'=')){
  4494. $enc = str_replace('"','',substr(strstr($this->headers["content-type"],'='),1));
  4495. if(preg_match('/^(ISO-8859-1|US-ASCII|UTF-8)$/i',$enc)){
  4496. $this->xml_encoding = strtoupper($enc);
  4497. } else {
  4498. $this->xml_encoding = 'US-ASCII';
  4499. }
  4500. } else {
  4501. // should be US-ASCII for HTTP 1.0 or ISO-8859-1 for HTTP 1.1
  4502. $this->xml_encoding = 'ISO-8859-1';
  4503. }
  4504. } elseif(isset($_SERVER) && is_array($_SERVER)){
  4505. $this->debug("In parse_http_headers, use _SERVER");
  4506. foreach ($_SERVER as $k => $v) {
  4507. if (substr($k, 0, 5) == 'HTTP_') {
  4508. $k = str_replace(' ', '-', strtolower(str_replace('_', ' ', substr($k, 5))));
  4509. } else {
  4510. $k = str_replace(' ', '-', strtolower(str_replace('_', ' ', $k)));
  4511. }
  4512. if ($k == 'soapaction') {
  4513. // get SOAPAction header
  4514. $k = 'SOAPAction';
  4515. $v = str_replace('"', '', $v);
  4516. $v = str_replace('\\', '', $v);
  4517. $this->SOAPAction = $v;
  4518. } else if ($k == 'content-type') {
  4519. // get the character encoding of the incoming request
  4520. if (strpos($v, '=')) {
  4521. $enc = substr(strstr($v, '='), 1);
  4522. $enc = str_replace('"', '', $enc);
  4523. $enc = str_replace('\\', '', $enc);
  4524. if (preg_match('/^(ISO-8859-1|US-ASCII|UTF-8)$/i',$enc)) {
  4525. $this->xml_encoding = strtoupper($enc);
  4526. } else {
  4527. $this->xml_encoding = 'US-ASCII';
  4528. }
  4529. } else {
  4530. // should be US-ASCII for HTTP 1.0 or ISO-8859-1 for HTTP 1.1
  4531. $this->xml_encoding = 'ISO-8859-1';
  4532. }
  4533. }
  4534. $this->headers[$k] = $v;
  4535. $this->request .= "$k: $v\r\n";
  4536. $this->debug("$k: $v");
  4537. }
  4538. } elseif (is_array($HTTP_SERVER_VARS)) {
  4539. $this->debug("In parse_http_headers, use HTTP_SERVER_VARS");
  4540. foreach ($HTTP_SERVER_VARS as $k => $v) {
  4541. if (substr($k, 0, 5) == 'HTTP_') {
  4542. $k = str_replace(' ', '-', strtolower(str_replace('_', ' ', substr($k, 5)))); $k = strtolower(substr($k, 5));
  4543. } else {
  4544. $k = str_replace(' ', '-', strtolower(str_replace('_', ' ', $k))); $k = strtolower($k);
  4545. }
  4546. if ($k == 'soapaction') {
  4547. // get SOAPAction header
  4548. $k = 'SOAPAction';
  4549. $v = str_replace('"', '', $v);
  4550. $v = str_replace('\\', '', $v);
  4551. $this->SOAPAction = $v;
  4552. } else if ($k == 'content-type') {
  4553. // get the character encoding of the incoming request
  4554. if (strpos($v, '=')) {
  4555. $enc = substr(strstr($v, '='), 1);
  4556. $enc = str_replace('"', '', $enc);
  4557. $enc = str_replace('\\', '', $enc);
  4558. if (preg_match('/^(ISO-8859-1|US-ASCII|UTF-8)$/i',$enc)) {
  4559. $this->xml_encoding = strtoupper($enc);
  4560. } else {
  4561. $this->xml_encoding = 'US-ASCII';
  4562. }
  4563. } else {
  4564. // should be US-ASCII for HTTP 1.0 or ISO-8859-1 for HTTP 1.1
  4565. $this->xml_encoding = 'ISO-8859-1';
  4566. }
  4567. }
  4568. $this->headers[$k] = $v;
  4569. $this->request .= "$k: $v\r\n";
  4570. $this->debug("$k: $v");
  4571. }
  4572. } else {
  4573. $this->debug("In parse_http_headers, HTTP headers not accessible");
  4574. $this->setError("HTTP headers not accessible");
  4575. }
  4576. }
  4577. /**
  4578. * parses a request
  4579. *
  4580. * The following fields are set by this function (when successful)
  4581. *
  4582. * headers
  4583. * request
  4584. * xml_encoding
  4585. * SOAPAction
  4586. * request
  4587. * requestSOAP
  4588. * methodURI
  4589. * methodname
  4590. * methodparams
  4591. * requestHeaders
  4592. * document
  4593. *
  4594. * This sets the fault field on error
  4595. *
  4596. * @param string $data XML string
  4597. * @access private
  4598. */
  4599. function parse_request($data='') {
  4600. $this->debug('entering parse_request()');
  4601. $this->parse_http_headers();
  4602. $this->debug('got character encoding: '.$this->xml_encoding);
  4603. // uncompress if necessary
  4604. if (isset($this->headers['content-encoding']) && $this->headers['content-encoding'] != '') {
  4605. $this->debug('got content encoding: ' . $this->headers['content-encoding']);
  4606. if ($this->headers['content-encoding'] == 'deflate' || $this->headers['content-encoding'] == 'gzip') {
  4607. // if decoding works, use it. else assume data wasn't gzencoded
  4608. if (function_exists('gzuncompress')) {
  4609. if ($this->headers['content-encoding'] == 'deflate' && $degzdata = @gzuncompress($data)) {
  4610. $data = $degzdata;
  4611. } elseif ($this->headers['content-encoding'] == 'gzip' && $degzdata = gzinflate(substr($data, 10))) {
  4612. $data = $degzdata;
  4613. } else {
  4614. $this->fault('SOAP-ENV:Client', 'Errors occurred when trying to decode the data');
  4615. return;
  4616. }
  4617. } else {
  4618. $this->fault('SOAP-ENV:Client', 'This Server does not support compressed data');
  4619. return;
  4620. }
  4621. }
  4622. }
  4623. $this->request .= "\r\n".$data;
  4624. $data = $this->parseRequest($this->headers, $data);
  4625. $this->requestSOAP = $data;
  4626. $this->debug('leaving parse_request');
  4627. }
  4628. function register_class($classname){
  4629. $this->registeredClass = $classname;
  4630. }
  4631. /**
  4632. * invokes a PHP function for the requested SOAP method
  4633. *
  4634. * The following fields are set by this function (when successful)
  4635. *
  4636. * methodreturn
  4637. *
  4638. * Note that the PHP function that is called may also set the following
  4639. * fields to affect the response sent to the client
  4640. *
  4641. * responseHeaders
  4642. * outgoing_headers
  4643. *
  4644. * This sets the fault field on error
  4645. *
  4646. * @access private
  4647. */
  4648. function invoke_method() {
  4649. $this->debug('in invoke_method, methodname=' . $this->methodname . ' methodURI=' . $this->methodURI . ' SOAPAction=' . $this->SOAPAction);
  4650. //
  4651. // if you are debugging in this area of the code, your service uses a class to implement methods,
  4652. // you use SOAP RPC, and the client is .NET, please be aware of the following...
  4653. // when the .NET wsdl.exe utility generates a proxy, it will remove the '.' or '..' from the
  4654. // method name. that is fine for naming the .NET methods. it is not fine for properly constructing
  4655. // the XML request and reading the XML response. you need to add the RequestElementName and
  4656. // ResponseElementName to the System.Web.Services.Protocols.SoapRpcMethodAttribute that wsdl.exe
  4657. // generates for the method. these parameters are used to specify the correct XML element names
  4658. // for .NET to use, i.e. the names with the '.' in them.
  4659. //
  4660. $orig_methodname = $this->methodname;
  4661. if ($this->wsdl) {
  4662. if ($this->opData = $this->wsdl->getOperationData($this->methodname)) {
  4663. $this->debug('in invoke_method, found WSDL operation=' . $this->methodname);
  4664. $this->appendDebug('opData=' . $this->varDump($this->opData));
  4665. } elseif ($this->opData = $this->wsdl->getOperationDataForSoapAction($this->SOAPAction)) {
  4666. // Note: hopefully this case will only be used for doc/lit, since rpc services should have wrapper element
  4667. $this->debug('in invoke_method, found WSDL soapAction=' . $this->SOAPAction . ' for operation=' . $this->opData['name']);
  4668. $this->appendDebug('opData=' . $this->varDump($this->opData));
  4669. $this->methodname = $this->opData['name'];
  4670. } else {
  4671. $this->debug('in invoke_method, no WSDL for operation=' . $this->methodname);
  4672. $this->fault('SOAP-ENV:Client', "Operation '" . $this->methodname . "' is not defined in the WSDL for this service");
  4673. return;
  4674. }
  4675. } else {
  4676. $this->debug('in invoke_method, no WSDL to validate method');
  4677. }
  4678. // if a . is present in $this->methodname, we see if there is a class in scope,
  4679. // which could be referred to. We will also distinguish between two deliminators,
  4680. // to allow methods to be called a the class or an instance
  4681. if (strpos($this->methodname, '..') > 0) {
  4682. $delim = '..';
  4683. } else if (strpos($this->methodname, '.') > 0) {
  4684. $delim = '.';
  4685. } else {
  4686. $delim = '';
  4687. }
  4688. $this->debug("in invoke_method, delim=$delim");
  4689. $class = '';
  4690. $method = '';
  4691. if (strlen($delim) > 0 && substr_count($this->methodname, $delim) == 1) {
  4692. $try_class = substr($this->methodname, 0, strpos($this->methodname, $delim));
  4693. if (class_exists($try_class)) {
  4694. // get the class and method name
  4695. $class = $try_class;
  4696. $method = substr($this->methodname, strpos($this->methodname, $delim) + strlen($delim));
  4697. $this->debug("in invoke_method, class=$class method=$method delim=$delim");
  4698. } else {
  4699. $this->debug("in invoke_method, class=$try_class not found");
  4700. }
  4701. } else {
  4702. $try_class = '';
  4703. $this->debug("in invoke_method, no class to try");
  4704. }
  4705. if(empty($delim) && isset($this->registeredClass)){
  4706. $class = $this->registeredClass;
  4707. $delim = '..';
  4708. $method = $this->methodname;
  4709. }
  4710. // does method exist?
  4711. if ($class == '') {
  4712. if (!function_exists($this->methodname)) {
  4713. $this->debug("in invoke_method, function '$this->methodname' not found!");
  4714. $this->result = 'fault: method not found';
  4715. $this->fault('SOAP-ENV:Client',"method '$this->methodname'('$orig_methodname') not defined in service('$try_class' '$delim')");
  4716. return;
  4717. }
  4718. } else {
  4719. $method_to_compare = (substr(phpversion(), 0, 2) == '4.') ? strtolower($method) : $method;
  4720. if (!in_array($method_to_compare, get_class_methods($class))) {
  4721. $this->debug("in invoke_method, method '$this->methodname' not found in class '$class'!");
  4722. $this->result = 'fault: method not found';
  4723. $this->fault('SOAP-ENV:Client',"method '$this->methodname'/'$method_to_compare'('$orig_methodname') not defined in service/'$class'('$try_class' '$delim')");
  4724. return;
  4725. }
  4726. }
  4727. // evaluate message, getting back parameters
  4728. // verify that request parameters match the method's signature
  4729. if(! $this->verify_method($this->methodname,$this->methodparams)){
  4730. // debug
  4731. $this->debug('ERROR: request not verified against method signature');
  4732. $this->result = 'fault: request failed validation against method signature';
  4733. // return fault
  4734. $this->fault('SOAP-ENV:Client',"Operation '$this->methodname' not defined in service.");
  4735. return;
  4736. }
  4737. // if there are parameters to pass
  4738. $this->debug('in invoke_method, params:');
  4739. $this->appendDebug($this->varDump($this->methodparams));
  4740. $this->debug("in invoke_method, calling '$this->methodname'");
  4741. if (!function_exists('call_user_func_array')) {
  4742. if ($class == '') {
  4743. $this->debug('in invoke_method, calling function using eval()');
  4744. $funcCall = "\$this->methodreturn = $this->methodname(";
  4745. } else {
  4746. if ($delim == '..') {
  4747. $this->debug('in invoke_method, calling class method using eval()');
  4748. $funcCall = "\$this->methodreturn = ".$class."::".$method."(";
  4749. } else {
  4750. $this->debug('in invoke_method, calling instance method using eval()');
  4751. // generate unique instance name
  4752. $instname = "\$inst_".time();
  4753. $funcCall = $instname." = new ".$class."(); ";
  4754. $funcCall .= "\$this->methodreturn = ".$instname."->".$method."(";
  4755. }
  4756. }
  4757. if ($this->methodparams) {
  4758. foreach ($this->methodparams as $param) {
  4759. if (is_array($param) || is_object($param)) {
  4760. $this->fault('SOAP-ENV:Client', 'NuSOAP does not handle complexType parameters correctly when using eval; call_user_func_array must be available');
  4761. return;
  4762. }
  4763. $funcCall .= "\"$param\",";
  4764. }
  4765. $funcCall = substr($funcCall, 0, -1);
  4766. }
  4767. $funcCall .= ');';
  4768. $this->debug('in invoke_method, function call: '.$funcCall);
  4769. @eval($funcCall);
  4770. } else {
  4771. if ($class == '') {
  4772. $this->debug('in invoke_method, calling function using call_user_func_array()');
  4773. $call_arg = "$this->methodname"; // straight assignment changes $this->methodname to lower case after call_user_func_array()
  4774. } elseif ($delim == '..') {
  4775. $this->debug('in invoke_method, calling class method using call_user_func_array()');
  4776. $call_arg = array ($class, $method);
  4777. } else {
  4778. $this->debug('in invoke_method, calling instance method using call_user_func_array()');
  4779. $instance = new $class ();
  4780. $call_arg = array(&$instance, $method);
  4781. }
  4782. if (is_array($this->methodparams)) {
  4783. $this->methodreturn = call_user_func_array($call_arg, array_values($this->methodparams));
  4784. } else {
  4785. $this->methodreturn = call_user_func_array($call_arg, array());
  4786. }
  4787. }
  4788. $this->debug('in invoke_method, methodreturn:');
  4789. $this->appendDebug($this->varDump($this->methodreturn));
  4790. $this->debug("in invoke_method, called method $this->methodname, received data of type ".gettype($this->methodreturn));
  4791. }
  4792. /**
  4793. * serializes the return value from a PHP function into a full SOAP Envelope
  4794. *
  4795. * The following fields are set by this function (when successful)
  4796. *
  4797. * responseSOAP
  4798. *
  4799. * This sets the fault field on error
  4800. *
  4801. * @access private
  4802. */
  4803. function serialize_return() {
  4804. $this->debug('Entering serialize_return methodname: ' . $this->methodname . ' methodURI: ' . $this->methodURI);
  4805. // if fault
  4806. if (isset($this->methodreturn) && is_object($this->methodreturn) && ((get_class($this->methodreturn) == 'soap_fault') || (get_class($this->methodreturn) == 'nusoap_fault'))) {
  4807. $this->debug('got a fault object from method');
  4808. $this->fault = $this->methodreturn;
  4809. return;
  4810. } elseif ($this->methodreturnisliteralxml) {
  4811. $return_val = $this->methodreturn;
  4812. // returned value(s)
  4813. } else {
  4814. $this->debug('got a(n) '.gettype($this->methodreturn).' from method');
  4815. $this->debug('serializing return value');
  4816. if($this->wsdl){
  4817. if (sizeof($this->opData['output']['parts']) > 1) {
  4818. $this->debug('more than one output part, so use the method return unchanged');
  4819. $opParams = $this->methodreturn;
  4820. } elseif (sizeof($this->opData['output']['parts']) == 1) {
  4821. $this->debug('exactly one output part, so wrap the method return in a simple array');
  4822. // TODO: verify that it is not already wrapped!
  4823. //foreach ($this->opData['output']['parts'] as $name => $type) {
  4824. // $this->debug('wrap in element named ' . $name);
  4825. //}
  4826. $opParams = array($this->methodreturn);
  4827. }
  4828. $return_val = $this->wsdl->serializeRPCParameters($this->methodname,'output',$opParams);
  4829. $this->appendDebug($this->wsdl->getDebug());
  4830. $this->wsdl->clearDebug();
  4831. if($errstr = $this->wsdl->getError()){
  4832. $this->debug('got wsdl error: '.$errstr);
  4833. $this->fault('SOAP-ENV:Server', 'unable to serialize result');
  4834. return;
  4835. }
  4836. } else {
  4837. if (isset($this->methodreturn)) {
  4838. $return_val = $this->serialize_val($this->methodreturn, 'return');
  4839. } else {
  4840. $return_val = '';
  4841. $this->debug('in absence of WSDL, assume void return for backward compatibility');
  4842. }
  4843. }
  4844. }
  4845. $this->debug('return value:');
  4846. $this->appendDebug($this->varDump($return_val));
  4847. $this->debug('serializing response');
  4848. if ($this->wsdl) {
  4849. $this->debug('have WSDL for serialization: style is ' . $this->opData['style']);
  4850. if ($this->opData['style'] == 'rpc') {
  4851. $this->debug('style is rpc for serialization: use is ' . $this->opData['output']['use']);
  4852. if ($this->opData['output']['use'] == 'literal') {
  4853. // http://www.ws-i.org/Profiles/BasicProfile-1.1-2004-08-24.html R2735 says rpc/literal accessor elements should not be in a namespace
  4854. if ($this->methodURI) {
  4855. $payload = '<ns1:'.$this->methodname.'Response xmlns:ns1="'.$this->methodURI.'">'.$return_val.'</ns1:'.$this->methodname."Response>";
  4856. } else {
  4857. $payload = '<'.$this->methodname.'Response>'.$return_val.'</'.$this->methodname.'Response>';
  4858. }
  4859. } else {
  4860. if ($this->methodURI) {
  4861. $payload = '<ns1:'.$this->methodname.'Response xmlns:ns1="'.$this->methodURI.'">'.$return_val.'</ns1:'.$this->methodname."Response>";
  4862. } else {
  4863. $payload = '<'.$this->methodname.'Response>'.$return_val.'</'.$this->methodname.'Response>';
  4864. }
  4865. }
  4866. } else {
  4867. $this->debug('style is not rpc for serialization: assume document');
  4868. $payload = $return_val;
  4869. }
  4870. } else {
  4871. $this->debug('do not have WSDL for serialization: assume rpc/encoded');
  4872. $payload = '<ns1:'.$this->methodname.'Response xmlns:ns1="'.$this->methodURI.'">'.$return_val.'</ns1:'.$this->methodname."Response>";
  4873. }
  4874. $this->result = 'successful';
  4875. if($this->wsdl){
  4876. //if($this->debug_flag){
  4877. $this->appendDebug($this->wsdl->getDebug());
  4878. // }
  4879. if (isset($this->opData['output']['encodingStyle'])) {
  4880. $encodingStyle = $this->opData['output']['encodingStyle'];
  4881. } else {
  4882. $encodingStyle = '';
  4883. }
  4884. // Added: In case we use a WSDL, return a serialized env. WITH the usedNamespaces.
  4885. $this->responseSOAP = $this->serializeEnvelope($payload,$this->responseHeaders,$this->wsdl->usedNamespaces,$this->opData['style'],$this->opData['output']['use'],$encodingStyle);
  4886. } else {
  4887. $this->responseSOAP = $this->serializeEnvelope($payload,$this->responseHeaders);
  4888. }
  4889. $this->debug("Leaving serialize_return");
  4890. }
  4891. /**
  4892. * sends an HTTP response
  4893. *
  4894. * The following fields are set by this function (when successful)
  4895. *
  4896. * outgoing_headers
  4897. * response
  4898. *
  4899. * @access private
  4900. */
  4901. function send_response() {
  4902. $this->debug('Enter send_response');
  4903. if ($this->fault) {
  4904. $payload = $this->fault->serialize();
  4905. $this->outgoing_headers[] = "HTTP/1.0 500 Internal Server Error";
  4906. $this->outgoing_headers[] = "Status: 500 Internal Server Error";
  4907. } else {
  4908. $payload = $this->responseSOAP;
  4909. // Some combinations of PHP+Web server allow the Status
  4910. // to come through as a header. Since OK is the default
  4911. // just do nothing.
  4912. // $this->outgoing_headers[] = "HTTP/1.0 200 OK";
  4913. // $this->outgoing_headers[] = "Status: 200 OK";
  4914. }
  4915. // add debug data if in debug mode
  4916. if(isset($this->debug_flag) && $this->debug_flag){
  4917. $payload .= $this->getDebugAsXMLComment();
  4918. }
  4919. $this->outgoing_headers[] = "Server: $this->title Server v$this->version";
  4920. preg_match('/\$Revisio' . 'n: ([^ ]+)/', $this->revision, $rev);
  4921. $this->outgoing_headers[] = "X-SOAP-Server: $this->title/$this->version (".$rev[1].")";
  4922. // Let the Web server decide about this
  4923. //$this->outgoing_headers[] = "Connection: Close\r\n";
  4924. $payload = $this->getHTTPBody($payload);
  4925. $type = $this->getHTTPContentType();
  4926. $charset = $this->getHTTPContentTypeCharset();
  4927. $this->outgoing_headers[] = "Content-Type: $type" . ($charset ? '; charset=' . $charset : '');
  4928. //begin code to compress payload - by John
  4929. // NOTE: there is no way to know whether the Web server will also compress
  4930. // this data.
  4931. if (strlen($payload) > 1024 && isset($this->headers) && isset($this->headers['accept-encoding'])) {
  4932. if (strstr($this->headers['accept-encoding'], 'gzip')) {
  4933. if (function_exists('gzencode')) {
  4934. if (isset($this->debug_flag) && $this->debug_flag) {
  4935. $payload .= "<!-- Content being gzipped -->";
  4936. }
  4937. $this->outgoing_headers[] = "Content-Encoding: gzip";
  4938. $payload = gzencode($payload);
  4939. } else {
  4940. if (isset($this->debug_flag) && $this->debug_flag) {
  4941. $payload .= "<!-- Content will not be gzipped: no gzencode -->";
  4942. }
  4943. }
  4944. } elseif (strstr($this->headers['accept-encoding'], 'deflate')) {
  4945. // Note: MSIE requires gzdeflate output (no Zlib header and checksum),
  4946. // instead of gzcompress output,
  4947. // which conflicts with HTTP 1.1 spec (http://www.w3.org/Protocols/rfc2616/rfc2616-sec3.html#sec3.5)
  4948. if (function_exists('gzdeflate')) {
  4949. if (isset($this->debug_flag) && $this->debug_flag) {
  4950. $payload .= "<!-- Content being deflated -->";
  4951. }
  4952. $this->outgoing_headers[] = "Content-Encoding: deflate";
  4953. $payload = gzdeflate($payload);
  4954. } else {
  4955. if (isset($this->debug_flag) && $this->debug_flag) {
  4956. $payload .= "<!-- Content will not be deflated: no gzcompress -->";
  4957. }
  4958. }
  4959. }
  4960. }
  4961. //end code
  4962. ob_end_clean();
  4963. ob_start();
  4964. $this->outgoing_headers[] = "Content-Length: ".strlen($payload);
  4965. reset($this->outgoing_headers);
  4966. foreach($this->outgoing_headers as $hdr){
  4967. header($hdr, false);
  4968. }
  4969. print $payload;
  4970. ob_flush();
  4971. $this->response = join("\r\n",$this->outgoing_headers)."\r\n\r\n".$payload;
  4972. }
  4973. /**
  4974. * takes the value that was created by parsing the request
  4975. * and compares to the method's signature, if available.
  4976. *
  4977. * @param string $operation The operation to be invoked
  4978. * @param array $request The array of parameter values
  4979. * @return boolean Whether the operation was found
  4980. * @access private
  4981. */
  4982. function verify_method($operation,$request){
  4983. if(isset($this->wsdl) && is_object($this->wsdl)){
  4984. if($this->wsdl->getOperationData($operation)){
  4985. return true;
  4986. }
  4987. } elseif(isset($this->operations[$operation])){
  4988. return true;
  4989. }
  4990. return false;
  4991. }
  4992. /**
  4993. * processes SOAP message received from client
  4994. *
  4995. * @param array $headers The HTTP headers
  4996. * @param string $data unprocessed request data from client
  4997. * @return mixed value of the message, decoded into a PHP type
  4998. * @access private
  4999. */
  5000. function parseRequest($headers, $data) {
  5001. $this->debug('Entering parseRequest() for data of length ' . strlen($data) . ' headers:');
  5002. $this->appendDebug($this->varDump($headers));
  5003. if (!isset($headers['content-type'])) {
  5004. $this->setError('Request not of type text/xml (no content-type header)');
  5005. return false;
  5006. }
  5007. if (!strstr($headers['content-type'], 'text/xml')) {
  5008. $this->setError('Request not of type text/xml');
  5009. return false;
  5010. }
  5011. if (strpos($headers['content-type'], '=')) {
  5012. $enc = str_replace('"', '', substr(strstr($headers["content-type"], '='), 1));
  5013. $this->debug('Got response encoding: ' . $enc);
  5014. if(preg_match('/^(ISO-8859-1|US-ASCII|UTF-8)$/i',$enc)){
  5015. $this->xml_encoding = strtoupper($enc);
  5016. } else {
  5017. $this->xml_encoding = 'US-ASCII';
  5018. }
  5019. } else {
  5020. // should be US-ASCII for HTTP 1.0 or ISO-8859-1 for HTTP 1.1
  5021. $this->xml_encoding = 'ISO-8859-1';
  5022. }
  5023. $this->debug('Use encoding: ' . $this->xml_encoding . ' when creating nusoap_parser');
  5024. // parse response, get soap parser obj
  5025. $parser = new nusoap_parser($data,$this->xml_encoding,'',$this->decode_utf8);
  5026. // parser debug
  5027. $this->debug("parser debug: \n".$parser->getDebug());
  5028. // if fault occurred during message parsing
  5029. if($err = $parser->getError()){
  5030. $this->result = 'fault: error in msg parsing: '.$err;
  5031. $this->fault('SOAP-ENV:Client',"error in msg parsing:\n".$err);
  5032. // else successfully parsed request into soapval object
  5033. } else {
  5034. // get/set methodname
  5035. $this->methodURI = $parser->root_struct_namespace;
  5036. $this->methodname = $parser->root_struct_name;
  5037. $this->debug('methodname: '.$this->methodname.' methodURI: '.$this->methodURI);
  5038. $this->debug('calling parser->get_soapbody()');
  5039. $this->methodparams = $parser->get_soapbody();
  5040. // get SOAP headers
  5041. $this->requestHeaders = $parser->getHeaders();
  5042. // get SOAP Header
  5043. $this->requestHeader = $parser->get_soapheader();
  5044. // add document for doclit support
  5045. $this->document = $parser->document;
  5046. }
  5047. }
  5048. /**
  5049. * gets the HTTP body for the current response.
  5050. *
  5051. * @param string $soapmsg The SOAP payload
  5052. * @return string The HTTP body, which includes the SOAP payload
  5053. * @access private
  5054. */
  5055. function getHTTPBody($soapmsg) {
  5056. return $soapmsg;
  5057. }
  5058. /**
  5059. * gets the HTTP content type for the current response.
  5060. *
  5061. * Note: getHTTPBody must be called before this.
  5062. *
  5063. * @return string the HTTP content type for the current response.
  5064. * @access private
  5065. */
  5066. function getHTTPContentType() {
  5067. return 'text/xml';
  5068. }
  5069. /**
  5070. * gets the HTTP content type charset for the current response.
  5071. * returns false for non-text content types.
  5072. *
  5073. * Note: getHTTPBody must be called before this.
  5074. *
  5075. * @return string the HTTP content type charset for the current response.
  5076. * @access private
  5077. */
  5078. function getHTTPContentTypeCharset() {
  5079. return $this->soap_defencoding;
  5080. }
  5081. /**
  5082. * add a method to the dispatch map (this has been replaced by the register method)
  5083. *
  5084. * @param string $methodname
  5085. * @param string $in array of input values
  5086. * @param string $out array of output values
  5087. * @access public
  5088. * @deprecated
  5089. */
  5090. function add_to_map($methodname,$in,$out){
  5091. $this->operations[$methodname] = array('name' => $methodname,'in' => $in,'out' => $out);
  5092. }
  5093. /**
  5094. * register a service function with the server
  5095. *
  5096. * @param string $name the name of the PHP function, class.method or class..method
  5097. * @param array $in assoc array of input values: key = param name, value = param type
  5098. * @param array $out assoc array of output values: key = param name, value = param type
  5099. * @param mixed $namespace the element namespace for the method or false
  5100. * @param mixed $soapaction the soapaction for the method or false
  5101. * @param mixed $style optional (rpc|document) or false Note: when 'document' is specified, parameter and return wrappers are created for you automatically
  5102. * @param mixed $use optional (encoded|literal) or false
  5103. * @param string $documentation optional Description to include in WSDL
  5104. * @param string $encodingStyle optional (usually 'http://schemas.xmlsoap.org/soap/encoding/' for encoded)
  5105. * @access public
  5106. */
  5107. function register($name,$in=array(),$out=array(),$namespace=false,$soapaction=false,$style=false,$use=false,$documentation='',$encodingStyle=''){
  5108. global $HTTP_SERVER_VARS;
  5109. if($this->externalWSDLURL){
  5110. die('You cannot bind to an external WSDL file, and register methods outside of it! Please choose either WSDL or no WSDL.');
  5111. }
  5112. if (! $name) {
  5113. die('You must specify a name when you register an operation');
  5114. }
  5115. if (!is_array($in)) {
  5116. die('You must provide an array for operation inputs');
  5117. }
  5118. if (!is_array($out)) {
  5119. die('You must provide an array for operation outputs');
  5120. }
  5121. if(false == $namespace) {
  5122. }
  5123. if(false == $soapaction) {
  5124. if (isset($_SERVER)) {
  5125. $SERVER_NAME = $_SERVER['SERVER_NAME'];
  5126. $SCRIPT_NAME = isset($_SERVER['PHP_SELF']) ? $_SERVER['PHP_SELF'] : $_SERVER['SCRIPT_NAME'];
  5127. $HTTPS = isset($_SERVER['HTTPS']) ? $_SERVER['HTTPS'] : (isset($HTTP_SERVER_VARS['HTTPS']) ? $HTTP_SERVER_VARS['HTTPS'] : 'off');
  5128. } elseif (isset($HTTP_SERVER_VARS)) {
  5129. $SERVER_NAME = $HTTP_SERVER_VARS['SERVER_NAME'];
  5130. $SCRIPT_NAME = isset($HTTP_SERVER_VARS['PHP_SELF']) ? $HTTP_SERVER_VARS['PHP_SELF'] : $HTTP_SERVER_VARS['SCRIPT_NAME'];
  5131. $HTTPS = isset($HTTP_SERVER_VARS['HTTPS']) ? $HTTP_SERVER_VARS['HTTPS'] : 'off';
  5132. } else {
  5133. $this->setError("Neither _SERVER nor HTTP_SERVER_VARS is available");
  5134. }
  5135. if ($HTTPS == '1' || $HTTPS == 'on') {
  5136. $SCHEME = 'https';
  5137. } else {
  5138. $SCHEME = 'http';
  5139. }
  5140. $soapaction = "$SCHEME://$SERVER_NAME$SCRIPT_NAME/$name";
  5141. }
  5142. if(false == $style) {
  5143. $style = "rpc";
  5144. }
  5145. if(false == $use) {
  5146. $use = "encoded";
  5147. }
  5148. if ($use == 'encoded' && $encodingStyle == '') {
  5149. $encodingStyle = 'http://schemas.xmlsoap.org/soap/encoding/';
  5150. }
  5151. $this->operations[$name] = array(
  5152. 'name' => $name,
  5153. 'in' => $in,
  5154. 'out' => $out,
  5155. 'namespace' => $namespace,
  5156. 'soapaction' => $soapaction,
  5157. 'style' => $style);
  5158. if($this->wsdl){
  5159. $this->wsdl->addOperation($name,$in,$out,$namespace,$soapaction,$style,$use,$documentation,$encodingStyle);
  5160. }
  5161. return true;
  5162. }
  5163. /**
  5164. * Specify a fault to be returned to the client.
  5165. * This also acts as a flag to the server that a fault has occured.
  5166. *
  5167. * @param string $faultcode
  5168. * @param string $faultstring
  5169. * @param string $faultactor
  5170. * @param string $faultdetail
  5171. * @access public
  5172. */
  5173. function fault($faultcode,$faultstring,$faultactor='',$faultdetail=''){
  5174. if ($faultdetail == '' && $this->debug_flag) {
  5175. $faultdetail = $this->getDebug();
  5176. }
  5177. $this->fault = new nusoap_fault($faultcode,$faultactor,$faultstring,$faultdetail);
  5178. $this->fault->soap_defencoding = $this->soap_defencoding;
  5179. }
  5180. /**
  5181. * Sets up wsdl object.
  5182. * Acts as a flag to enable internal WSDL generation
  5183. *
  5184. * @param string $serviceName, name of the service
  5185. * @param mixed $namespace optional 'tns' service namespace or false
  5186. * @param mixed $endpoint optional URL of service endpoint or false
  5187. * @param string $style optional (rpc|document) WSDL style (also specified by operation)
  5188. * @param string $transport optional SOAP transport
  5189. * @param mixed $schemaTargetNamespace optional 'types' targetNamespace for service schema or false
  5190. */
  5191. function configureWSDL($serviceName,$namespace = false,$endpoint = false,$style='rpc', $transport = 'http://schemas.xmlsoap.org/soap/http', $schemaTargetNamespace = false)
  5192. {
  5193. global $HTTP_SERVER_VARS;
  5194. if (isset($_SERVER)) {
  5195. $SERVER_NAME = $_SERVER['SERVER_NAME'];
  5196. $SERVER_PORT = $_SERVER['SERVER_PORT'];
  5197. $SCRIPT_NAME = isset($_SERVER['PHP_SELF']) ? $_SERVER['PHP_SELF'] : $_SERVER['SCRIPT_NAME'];
  5198. $HTTPS = isset($_SERVER['HTTPS']) ? $_SERVER['HTTPS'] : (isset($HTTP_SERVER_VARS['HTTPS']) ? $HTTP_SERVER_VARS['HTTPS'] : 'off');
  5199. } elseif (isset($HTTP_SERVER_VARS)) {
  5200. $SERVER_NAME = $HTTP_SERVER_VARS['SERVER_NAME'];
  5201. $SERVER_PORT = $HTTP_SERVER_VARS['SERVER_PORT'];
  5202. $SCRIPT_NAME = isset($HTTP_SERVER_VARS['PHP_SELF']) ? $HTTP_SERVER_VARS['PHP_SELF'] : $HTTP_SERVER_VARS['SCRIPT_NAME'];
  5203. $HTTPS = isset($HTTP_SERVER_VARS['HTTPS']) ? $HTTP_SERVER_VARS['HTTPS'] : 'off';
  5204. } else {
  5205. $this->setError("Neither _SERVER nor HTTP_SERVER_VARS is available");
  5206. }
  5207. // If server name has port number attached then strip it (else port number gets duplicated in WSDL output) (occurred using lighttpd and FastCGI)
  5208. $colon = strpos($SERVER_NAME,":");
  5209. if ($colon) {
  5210. $SERVER_NAME = substr($SERVER_NAME, 0, $colon);
  5211. }
  5212. if ($SERVER_PORT == 80) {
  5213. $SERVER_PORT = '';
  5214. } else {
  5215. $SERVER_PORT = ':' . $SERVER_PORT;
  5216. }
  5217. if(false == $namespace) {
  5218. $namespace = "http://$SERVER_NAME/soap/$serviceName";
  5219. }
  5220. if(false == $endpoint) {
  5221. if ($HTTPS == '1' || $HTTPS == 'on') {
  5222. $SCHEME = 'https';
  5223. } else {
  5224. $SCHEME = 'http';
  5225. }
  5226. $endpoint = "$SCHEME://$SERVER_NAME$SERVER_PORT$SCRIPT_NAME";
  5227. }
  5228. if(false == $schemaTargetNamespace) {
  5229. $schemaTargetNamespace = $namespace;
  5230. }
  5231. $this->wsdl = new wsdl;
  5232. $this->wsdl->serviceName = $serviceName;
  5233. $this->wsdl->endpoint = $endpoint;
  5234. $this->wsdl->namespaces['tns'] = $namespace;
  5235. $this->wsdl->namespaces['soap'] = 'http://schemas.xmlsoap.org/wsdl/soap/';
  5236. $this->wsdl->namespaces['wsdl'] = 'http://schemas.xmlsoap.org/wsdl/';
  5237. if ($schemaTargetNamespace != $namespace) {
  5238. $this->wsdl->namespaces['types'] = $schemaTargetNamespace;
  5239. }
  5240. $this->wsdl->schemas[$schemaTargetNamespace][0] = new nusoap_xmlschema('', '', $this->wsdl->namespaces);
  5241. if ($style == 'document') {
  5242. $this->wsdl->schemas[$schemaTargetNamespace][0]->schemaInfo['elementFormDefault'] = 'qualified';
  5243. }
  5244. $this->wsdl->schemas[$schemaTargetNamespace][0]->schemaTargetNamespace = $schemaTargetNamespace;
  5245. $this->wsdl->schemas[$schemaTargetNamespace][0]->imports['http://schemas.xmlsoap.org/soap/encoding/'][0] = array('location' => '', 'loaded' => true);
  5246. $this->wsdl->schemas[$schemaTargetNamespace][0]->imports['http://schemas.xmlsoap.org/wsdl/'][0] = array('location' => '', 'loaded' => true);
  5247. $this->wsdl->bindings[$serviceName.'Binding'] = array(
  5248. 'name'=>$serviceName.'Binding',
  5249. 'style'=>$style,
  5250. 'transport'=>$transport,
  5251. 'portType'=>$serviceName.'PortType');
  5252. $this->wsdl->ports[$serviceName.'Port'] = array(
  5253. 'binding'=>$serviceName.'Binding',
  5254. 'location'=>$endpoint,
  5255. 'bindingType'=>'http://schemas.xmlsoap.org/wsdl/soap/');
  5256. }
  5257. }
  5258. /**
  5259. * Backward compatibility
  5260. */
  5261. class soap_server extends nusoap_server {
  5262. }
  5263. ?><?php
  5264. /*
  5265. Modification information for LGPL compliance
  5266. r58622 - 2010-10-22 18:18:59 -0700 (Fri, 22 Oct 2010) - engsvnbuild - Author: lam <lam@198.18.142.201>
  5267. bug 40066
  5268. r58361 - 2010-09-29 16:59:02 -0700 (Wed, 29 Sep 2010) - kjing - Author: Jenny Gonsalves <jenny@sugarcrm.com>
  5269. Merging with maint_6_0_1 (svn merge -r 58250:58342)
  5270. r57813 - 2010-08-19 10:34:44 -0700 (Thu, 19 Aug 2010) - kjing - Author: John Mertic <jmertic@sugarcrm.com>
  5271. Bug 39085 - When loading the opposite search panel via ajax on the ListViews, call the index action instead of the ListView action to avoid touching pre-MVC code by accident.
  5272. r57707 - 2010-08-10 12:26:13 -0700 (Tue, 10 Aug 2010) - kjing - Author: Stanislav Malyshev <smalyshev@gmail.com>
  5273. fix SOAP calls with no parameters
  5274. r56990 - 2010-06-16 13:05:36 -0700 (Wed, 16 Jun 2010) - kjing - snapshot "Mango" svn branch to a new one for GitHub sync
  5275. r56989 - 2010-06-16 13:01:33 -0700 (Wed, 16 Jun 2010) - kjing - defunt "Mango" svn dev branch before github cutover
  5276. r55980 - 2010-04-19 13:31:28 -0700 (Mon, 19 Apr 2010) - kjing - create Mango (6.1) based on windex
  5277. r51719 - 2009-10-22 10:18:00 -0700 (Thu, 22 Oct 2009) - mitani - Converted to Build 3 tags and updated the build system
  5278. r51634 - 2009-10-19 13:32:22 -0700 (Mon, 19 Oct 2009) - mitani - Windex is the branch for Sugar Sales 1.0 development
  5279. r51508 - 2009-10-14 07:40:23 -0700 (Wed, 14 Oct 2009) - jmertic - More fallout fixes from the PHP 5.3 ereg to preg changes.
  5280. r51455 - 2009-10-13 07:56:48 -0700 (Tue, 13 Oct 2009) - jmertic - Bug 33202 - Enable install of SugarCRM on PHP 5.3.0, asserting that the minimum supported version is PHP 5.2.x.
  5281. r51443 - 2009-10-12 13:34:36 -0700 (Mon, 12 Oct 2009) - jmertic - Bug 33332 - Made application PHP 5.3 compliant with E_DEPRECATED warnings on by:
  5282. - Changing all ereg function to either preg or simple string based ones
  5283. - No more references to magic quotes.
  5284. - Change all the session_unregister() functions to just unset() the correct session variable instead.
  5285. r50375 - 2009-08-24 18:07:43 -0700 (Mon, 24 Aug 2009) - dwong - branch kobe2 from tokyo r50372
  5286. r45763 - 2009-04-01 12:16:18 -0700 (Wed, 01 Apr 2009) - majed - Removed half of the require_once and include_onces in the product that were redundant or could be handled easily by the auto loader
  5287. r45680 - 2009-03-30 14:34:35 -0700 (Mon, 30 Mar 2009) - Samir Gandhi - modifeid serializeSchema to generate WS-I compliant WSDL
  5288. r42807 - 2008-12-29 11:16:59 -0800 (Mon, 29 Dec 2008) - dwong - Branch from trunk/sugarcrm r42806 to branches/tokyo/sugarcrm
  5289. r42645 - 2008-12-18 13:41:08 -0800 (Thu, 18 Dec 2008) - awu - merging maint_5_2_0 rev41336:HEAD to trunk
  5290. r41647 - 2008-11-11 17:44:30 -0800 (Tue, 11 Nov 2008) - majed - Fixes a few bugs
  5291. r41596 - 2008-11-10 19:20:04 -0800 (Mon, 10 Nov 2008) - Samir Gandhi - modified to set $method in the code
  5292. r41558 - 2008-11-10 14:35:34 -0800 (Mon, 10 Nov 2008) - majed - changes nusoap to allow for registering classes
  5293. r39619 - 2008-09-09 13:41:34 -0700 (Tue, 09 Sep 2008) - jmertic - Bug 24827 - Remove all instances where we return a new object and assign it by reference, since this is deprecated in PHP 5 and emits E_DEPRECATED errors in PHP 5.3.
  5294. Touched:
  5295. - data/SugarBean.php
  5296. - include/domit/php_http_client_generic.php
  5297. - include/domit/php_http_connector.php
  5298. - include/domit/testing_domit.php
  5299. - include/domit/xml_domit_getelementsbypath.php
  5300. - include/domit/xml_domit_lite_parser.php
  5301. - include/domit/xml_domit_nodemaps.php
  5302. - include/domit/xml_domit_parser.php
  5303. - include/domit/xml_domit_shared.php
  5304. - include/generic/SugarWidgets/SugarWidgetField.php
  5305. - include/generic/SugarWidgets/SugarWidgetReportField.php
  5306. - include/ListView/ProcessView.php
  5307. - include/nusoap/class.soapclient.php
  5308. - include/nusoap/nusoap.php
  5309. - include/nusoap/nusoapmime.php
  5310. - include/Pear/HTML_Safe/Safe.php
  5311. - include/Pear/XML_HTMLSax3/HTMLSax3.php
  5312. - modules/Administration/RebuildWorkFlow.php
  5313. - modules/Expressions/RelateSelector.php
  5314. - modules/Reports/templates/templates_reports.php
  5315. - modules/WorkFlow/Delete.php
  5316. - modules/WorkFlow/Save.php
  5317. - modules/WorkFlow/SaveSequence.php
  5318. - modules/WorkFlow/WorkFlow.php
  5319. - modules/WorkFlowActionShells/CreateStep1.php
  5320. - modules/WorkFlowActionShells/CreateStep2.php
  5321. - modules/WorkFlowActionShells/Save.php
  5322. - modules/WorkFlowActionShells/WorkFlowActionShell.php
  5323. - modules/WorkFlowAlerts/Save.php
  5324. - modules/WorkFlowAlerts/WorkFlowAlert.php
  5325. - modules/WorkFlowAlertShells/DetailView.php
  5326. - modules/WorkFlowAlertShells/WorkFlowAlertShell.php
  5327. - modules/WorkFlowTriggerShells/CreateStep1.php
  5328. - modules/WorkFlowTriggerShells/CreateStepFilter.php
  5329. - modules/WorkFlowTriggerShells/SaveFilter.php
  5330. - modules/WorkFlowTriggerShells/WorkFlowTriggerShell.php
  5331. - soap/SoapHelperFunctions.php
  5332. - test/modules/DynamicFields/DynamicFields_Bug24095_test.php
  5333. - test/simpletest/browser.php
  5334. - test/simpletest/default_reporter.php
  5335. - test/simpletest/detached.php
  5336. - test/simpletest/eclipse.php
  5337. - test/simpletest/expectation.php
  5338. - test/simpletest/extensions/pear_test_case.php
  5339. - test/simpletest/form.php
  5340. - test/simpletest/http.php
  5341. - test/simpletest/mock_objects.php
  5342. - test/simpletest/page.php
  5343. - test/simpletest/parser.php
  5344. - test/simpletest/remote.php
  5345. - test/simpletest/shell_tester.php
  5346. - test/simpletest/simple_test.php
  5347. - test/simpletest/simpletest.php
  5348. - test/simpletest/test/acceptance_test.php
  5349. - test/simpletest/test/adapter_test.php
  5350. - test/simpletest/test/authentication_test.php
  5351. - test/simpletest/test/browser_test.php
  5352. - test/simpletest/test/collector_test.php
  5353. - test/simpletest/test/compatibility_test.php
  5354. - test/simpletest/test/detached_test.php
  5355. - test/simpletest/test/eclipse_test.php
  5356. - test/simpletest/test/encoding_test.php
  5357. - test/simpletest/test/errors_test.php
  5358. - test/simpletest/test/expectation_test.php
  5359. - test/simpletest/test/form_test.php
  5360. - test/simpletest/test/frames_test.php
  5361. - test/simpletest/test/http_test.php
  5362. - test/simpletest/test/live_test.php
  5363. - test/simpletest/test/mock_objects_test.php
  5364. - test/simpletest/test/page_test.php
  5365. - test/simpletest/test/parse_error_test.php
  5366. - test/simpletest/test/parser_test.php
  5367. - test/simpletest/test/remote_test.php
  5368. - test/simpletest/test/shell_test.php
  5369. - test/simpletest/test/shell_tester_test.php
  5370. - test/simpletest/test/simpletest_test.php
  5371. - test/simpletest/test/site/page_request.php
  5372. - test/simpletest/test/tag_test.php
  5373. - test/simpletest/test/unit_tester_test.php
  5374. - test/simpletest/test/user_agent_test.php
  5375. - test/simpletest/test/visual_test.php
  5376. - test/simpletest/test/xml_test.php
  5377. - test/simpletest/test_case.php
  5378. - test/simpletest/ui/array_reporter/test.php
  5379. - test/simpletest/ui/recorder/test.php
  5380. - test/simpletest/unit_tester.php
  5381. - test/simpletest/url.php
  5382. - test/simpletest/user_agent.php
  5383. - test/simpletest/web_tester.php
  5384. - test/spikephpcoverage/src/PEAR.php
  5385. - test/spikephpcoverage/src/util/Utility.php
  5386. - test/spikephpcoverage/src/XML/Parser.php
  5387. - test/spikephpcoverage/src/XML/Parser/Simple.php
  5388. - test/test_utilities/SugarTest_SimpleBrowser.php
  5389. r38362 - 2008-07-28 14:06:59 -0700 (Mon, 28 Jul 2008) - roger - bug: 23897. Using print_r when using the debug statement in nusoap will print out the statements to the screen if the call is coming from the UI.
  5390. r38300 - 2008-07-25 13:33:43 -0700 (Fri, 25 Jul 2008) - Samir Gandhi - put the debug in parseresponse function
  5391. r38293 - 2008-07-25 12:32:34 -0700 (Fri, 25 Jul 2008) - Samir Gandhi - to put all the debug statements return value in the call function
  5392. r36824 - 2008-06-18 09:26:11 -0700 (Wed, 18 Jun 2008) - roger - bug: 21832
  5393. r26422 - 2007-09-05 17:29:12 -0700 (Wed, 05 Sep 2007) - majed - migrate from beta 1 to trunk
  5394. r15787 - 2006-08-10 10:14:41 -0700 (Thu, 10 Aug 2006) - roger - RRS: bug 7961
  5395. r14701 - 2006-07-17 13:37:26 -0700 (Mon, 17 Jul 2006) - roger - RRS: bug 5801
  5396. r13782 - 2006-06-06 10:58:55 -0700 (Tue, 06 Jun 2006) - majed - changes entry point code
  5397. r11466 - 2006-02-01 15:49:47 -0800 (Wed, 01 Feb 2006) - jacob - Adding extra !empty check to get around a PHP warning.
  5398. r11115 - 2006-01-17 14:54:45 -0800 (Tue, 17 Jan 2006) - majed - add entry point validation
  5399. r10585 - 2005-12-13 14:42:26 -0800 (Tue, 13 Dec 2005) - majed - adds new license mechanisim
  5400. r10170 - 2005-12-05 18:37:46 -0800 (Mon, 05 Dec 2005) - majed - fixes various issues
  5401. r8999 - 2005-11-04 05:26:49 -0800 (Fri, 04 Nov 2005) - roger - When nusoap was upgraded we had an issue with the user's default language not being populated during a soap request. I determined the reason this was happening and have checked in the corresponding change to nusoap.
  5402. r8991 - 2005-11-03 19:07:25 -0800 (Thu, 03 Nov 2005) - majed - fixes nusoap issue
  5403. r8846 - 2005-10-31 11:01:12 -0800 (Mon, 31 Oct 2005) - majed - new version of nusoap
  5404. r7905 - 2005-09-21 19:12:57 -0700 (Wed, 21 Sep 2005) - majed - restores old nusoap pre & with a few fixes
  5405. r7861 - 2005-09-20 15:40:25 -0700 (Tue, 20 Sep 2005) - majed - & fix for 3.5.1
  5406. r7452 - 2005-08-17 11:32:34 -0700 (Wed, 17 Aug 2005) - majed - changes soap to nusoap
  5407. r5820 - 2005-06-21 14:22:24 -0700 (Tue, 21 Jun 2005) - majed - fixes issues with nusoap and with custom fields
  5408. r5462 - 2005-05-25 13:50:11 -0700 (Wed, 25 May 2005) - majed - upgraded nusoap to .6.9
  5409. r5104 - 2005-05-04 15:33:41 -0700 (Wed, 04 May 2005) - majed - gets rid of HTTP_GET_VARS and what not which has been deprecated
  5410. r573 - 2004-09-04 13:03:32 -0700 (Sat, 04 Sep 2004) - sugarclint - undoing copyrights added in inadvertantly. --clint
  5411. r546 - 2004-09-03 11:49:38 -0700 (Fri, 03 Sep 2004) - sugarmsi - removed echo count
  5412. r354 - 2004-08-02 23:00:37 -0700 (Mon, 02 Aug 2004) - sugarjacob - Adding Soap
  5413. */
  5414. /**
  5415. * parses a WSDL file, allows access to it's data, other utility methods.
  5416. * also builds WSDL structures programmatically.
  5417. *
  5418. * @author Dietrich Ayala <dietrich@ganx4.com>
  5419. * @author Scott Nichol <snichol@users.sourceforge.net>
  5420. * @access public
  5421. */
  5422. class wsdl extends nusoap_base {
  5423. // URL or filename of the root of this WSDL
  5424. var $wsdl;
  5425. // define internal arrays of bindings, ports, operations, messages, etc.
  5426. var $schemas = array();
  5427. var $currentSchema;
  5428. var $message = array();
  5429. var $complexTypes = array();
  5430. var $messages = array();
  5431. var $currentMessage;
  5432. var $currentOperation;
  5433. var $portTypes = array();
  5434. var $currentPortType;
  5435. var $bindings = array();
  5436. var $currentBinding;
  5437. var $ports = array();
  5438. var $currentPort;
  5439. var $opData = array();
  5440. var $status = '';
  5441. var $documentation = false;
  5442. var $endpoint = '';
  5443. // array of wsdl docs to import
  5444. var $import = array();
  5445. // parser vars
  5446. var $parser;
  5447. var $position = 0;
  5448. var $depth = 0;
  5449. var $depth_array = array();
  5450. // for getting wsdl
  5451. var $proxyhost = '';
  5452. var $proxyport = '';
  5453. var $proxyusername = '';
  5454. var $proxypassword = '';
  5455. var $timeout = 0;
  5456. var $response_timeout = 30;
  5457. var $curl_options = array(); // User-specified cURL options
  5458. var $use_curl = false; // whether to always try to use cURL
  5459. // for HTTP authentication
  5460. var $username = ''; // Username for HTTP authentication
  5461. var $password = ''; // Password for HTTP authentication
  5462. var $authtype = ''; // Type of HTTP authentication
  5463. var $certRequest = array(); // Certificate for HTTP SSL authentication
  5464. /**
  5465. * constructor
  5466. *
  5467. * @param string $wsdl WSDL document URL
  5468. * @param string $proxyhost
  5469. * @param string $proxyport
  5470. * @param string $proxyusername
  5471. * @param string $proxypassword
  5472. * @param integer $timeout set the connection timeout
  5473. * @param integer $response_timeout set the response timeout
  5474. * @param array $curl_options user-specified cURL options
  5475. * @param boolean $use_curl try to use cURL
  5476. * @access public
  5477. */
  5478. function wsdl($wsdl = '',$proxyhost=false,$proxyport=false,$proxyusername=false,$proxypassword=false,$timeout=0,$response_timeout=30,$curl_options=null,$use_curl=false){
  5479. parent::nusoap_base();
  5480. $this->debug("ctor wsdl=$wsdl timeout=$timeout response_timeout=$response_timeout");
  5481. $this->proxyhost = $proxyhost;
  5482. $this->proxyport = $proxyport;
  5483. $this->proxyusername = $proxyusername;
  5484. $this->proxypassword = $proxypassword;
  5485. $this->timeout = $timeout;
  5486. $this->response_timeout = $response_timeout;
  5487. if (is_array($curl_options))
  5488. $this->curl_options = $curl_options;
  5489. $this->use_curl = $use_curl;
  5490. $this->fetchWSDL($wsdl);
  5491. }
  5492. /**
  5493. * fetches the WSDL document and parses it
  5494. *
  5495. * @access public
  5496. */
  5497. function fetchWSDL($wsdl) {
  5498. $this->debug("parse and process WSDL path=$wsdl");
  5499. $this->wsdl = $wsdl;
  5500. // parse wsdl file
  5501. if ($this->wsdl != "") {
  5502. $this->parseWSDL($this->wsdl);
  5503. }
  5504. // imports
  5505. // TODO: handle imports more properly, grabbing them in-line and nesting them
  5506. $imported_urls = array();
  5507. $imported = 1;
  5508. while ($imported > 0) {
  5509. $imported = 0;
  5510. // Schema imports
  5511. foreach ($this->schemas as $ns => $list) {
  5512. foreach ($list as $xs) {
  5513. $wsdlparts = parse_url($this->wsdl); // this is bogusly simple!
  5514. foreach ($xs->imports as $ns2 => $list2) {
  5515. for ($ii = 0; $ii < count($list2); $ii++) {
  5516. if (! $list2[$ii]['loaded']) {
  5517. $this->schemas[$ns]->imports[$ns2][$ii]['loaded'] = true;
  5518. $url = $list2[$ii]['location'];
  5519. if ($url != '') {
  5520. $urlparts = parse_url($url);
  5521. if (!isset($urlparts['host'])) {
  5522. $url = $wsdlparts['scheme'] . '://' . $wsdlparts['host'] . (isset($wsdlparts['port']) ? ':' .$wsdlparts['port'] : '') .
  5523. substr($wsdlparts['path'],0,strrpos($wsdlparts['path'],'/') + 1) .$urlparts['path'];
  5524. }
  5525. if (! in_array($url, $imported_urls)) {
  5526. $this->parseWSDL($url);
  5527. $imported++;
  5528. $imported_urls[] = $url;
  5529. }
  5530. } else {
  5531. $this->debug("Unexpected scenario: empty URL for unloaded import");
  5532. }
  5533. }
  5534. }
  5535. }
  5536. }
  5537. }
  5538. // WSDL imports
  5539. $wsdlparts = parse_url($this->wsdl); // this is bogusly simple!
  5540. foreach ($this->import as $ns => $list) {
  5541. for ($ii = 0; $ii < count($list); $ii++) {
  5542. if (! $list[$ii]['loaded']) {
  5543. $this->import[$ns][$ii]['loaded'] = true;
  5544. $url = $list[$ii]['location'];
  5545. if ($url != '') {
  5546. $urlparts = parse_url($url);
  5547. if (!isset($urlparts['host'])) {
  5548. $url = $wsdlparts['scheme'] . '://' . $wsdlparts['host'] . (isset($wsdlparts['port']) ? ':' . $wsdlparts['port'] : '') .
  5549. substr($wsdlparts['path'],0,strrpos($wsdlparts['path'],'/') + 1) .$urlparts['path'];
  5550. }
  5551. if (! in_array($url, $imported_urls)) {
  5552. $this->parseWSDL($url);
  5553. $imported++;
  5554. $imported_urls[] = $url;
  5555. }
  5556. } else {
  5557. $this->debug("Unexpected scenario: empty URL for unloaded import");
  5558. }
  5559. }
  5560. }
  5561. }
  5562. }
  5563. // add new data to operation data
  5564. foreach($this->bindings as $binding => $bindingData) {
  5565. if (isset($bindingData['operations']) && is_array($bindingData['operations'])) {
  5566. foreach($bindingData['operations'] as $operation => $data) {
  5567. $this->debug('post-parse data gathering for ' . $operation);
  5568. $this->bindings[$binding]['operations'][$operation]['input'] =
  5569. isset($this->bindings[$binding]['operations'][$operation]['input']) ?
  5570. array_merge($this->bindings[$binding]['operations'][$operation]['input'], $this->portTypes[ $bindingData['portType'] ][$operation]['input']) :
  5571. $this->portTypes[ $bindingData['portType'] ][$operation]['input'];
  5572. $this->bindings[$binding]['operations'][$operation]['output'] =
  5573. isset($this->bindings[$binding]['operations'][$operation]['output']) ?
  5574. array_merge($this->bindings[$binding]['operations'][$operation]['output'], $this->portTypes[ $bindingData['portType'] ][$operation]['output']) :
  5575. $this->portTypes[ $bindingData['portType'] ][$operation]['output'];
  5576. if(isset($this->messages[ $this->bindings[$binding]['operations'][$operation]['input']['message'] ])){
  5577. $this->bindings[$binding]['operations'][$operation]['input']['parts'] = $this->messages[ $this->bindings[$binding]['operations'][$operation]['input']['message'] ];
  5578. }
  5579. if(isset($this->messages[ $this->bindings[$binding]['operations'][$operation]['output']['message'] ])){
  5580. $this->bindings[$binding]['operations'][$operation]['output']['parts'] = $this->messages[ $this->bindings[$binding]['operations'][$operation]['output']['message'] ];
  5581. }
  5582. // Set operation style if necessary, but do not override one already provided
  5583. if (isset($bindingData['style']) && !isset($this->bindings[$binding]['operations'][$operation]['style'])) {
  5584. $this->bindings[$binding]['operations'][$operation]['style'] = $bindingData['style'];
  5585. }
  5586. $this->bindings[$binding]['operations'][$operation]['transport'] = isset($bindingData['transport']) ? $bindingData['transport'] : '';
  5587. $this->bindings[$binding]['operations'][$operation]['documentation'] = isset($this->portTypes[ $bindingData['portType'] ][$operation]['documentation']) ? $this->portTypes[ $bindingData['portType'] ][$operation]['documentation'] : '';
  5588. $this->bindings[$binding]['operations'][$operation]['endpoint'] = isset($bindingData['endpoint']) ? $bindingData['endpoint'] : '';
  5589. }
  5590. }
  5591. }
  5592. }
  5593. /**
  5594. * parses the wsdl document
  5595. *
  5596. * @param string $wsdl path or URL
  5597. * @access private
  5598. */
  5599. function parseWSDL($wsdl = '') {
  5600. $this->debug("parse WSDL at path=$wsdl");
  5601. if ($wsdl == '') {
  5602. $this->debug('no wsdl passed to parseWSDL()!!');
  5603. $this->setError('no wsdl passed to parseWSDL()!!');
  5604. return false;
  5605. }
  5606. // parse $wsdl for url format
  5607. $wsdl_props = parse_url($wsdl);
  5608. if (isset($wsdl_props['scheme']) && ($wsdl_props['scheme'] == 'http' || $wsdl_props['scheme'] == 'https')) {
  5609. $this->debug('getting WSDL http(s) URL ' . $wsdl);
  5610. // get wsdl
  5611. $tr = new soap_transport_http($wsdl, $this->curl_options, $this->use_curl);
  5612. $tr->request_method = 'GET';
  5613. $tr->useSOAPAction = false;
  5614. if($this->proxyhost && $this->proxyport){
  5615. $tr->setProxy($this->proxyhost,$this->proxyport,$this->proxyusername,$this->proxypassword);
  5616. }
  5617. if ($this->authtype != '') {
  5618. $tr->setCredentials($this->username, $this->password, $this->authtype, array(), $this->certRequest);
  5619. }
  5620. $tr->setEncoding('gzip, deflate');
  5621. $wsdl_string = $tr->send('', $this->timeout, $this->response_timeout);
  5622. //$this->debug("WSDL request\n" . $tr->outgoing_payload);
  5623. //$this->debug("WSDL response\n" . $tr->incoming_payload);
  5624. $this->appendDebug($tr->getDebug());
  5625. // catch errors
  5626. if($err = $tr->getError() ){
  5627. $errstr = 'Getting ' . $wsdl . ' - HTTP ERROR: '.$err;
  5628. $this->debug($errstr);
  5629. $this->setError($errstr);
  5630. unset($tr);
  5631. return false;
  5632. }
  5633. unset($tr);
  5634. $this->debug("got WSDL URL");
  5635. } else {
  5636. // $wsdl is not http(s), so treat it as a file URL or plain file path
  5637. if (isset($wsdl_props['scheme']) && ($wsdl_props['scheme'] == 'file') && isset($wsdl_props['path'])) {
  5638. $path = isset($wsdl_props['host']) ? ($wsdl_props['host'] . ':' . $wsdl_props['path']) : $wsdl_props['path'];
  5639. } else {
  5640. $path = $wsdl;
  5641. }
  5642. $this->debug('getting WSDL file ' . $path);
  5643. if ($fp = @fopen($path, 'r')) {
  5644. $wsdl_string = '';
  5645. while ($data = fread($fp, 32768)) {
  5646. $wsdl_string .= $data;
  5647. }
  5648. fclose($fp);
  5649. } else {
  5650. $errstr = "Bad path to WSDL file $path";
  5651. $this->debug($errstr);
  5652. $this->setError($errstr);
  5653. return false;
  5654. }
  5655. }
  5656. $this->debug('Parse WSDL');
  5657. // end new code added
  5658. // Create an XML parser.
  5659. $this->parser = xml_parser_create();
  5660. // Set the options for parsing the XML data.
  5661. // xml_parser_set_option($parser, XML_OPTION_SKIP_WHITE, 1);
  5662. xml_parser_set_option($this->parser, XML_OPTION_CASE_FOLDING, 0);
  5663. // Set the object for the parser.
  5664. xml_set_object($this->parser, $this);
  5665. // Set the element handlers for the parser.
  5666. xml_set_element_handler($this->parser, 'start_element', 'end_element');
  5667. xml_set_character_data_handler($this->parser, 'character_data');
  5668. // Parse the XML file.
  5669. if (!xml_parse($this->parser, $wsdl_string, true)) {
  5670. // Display an error message.
  5671. $errstr = sprintf(
  5672. 'XML error parsing WSDL from %s on line %d: %s',
  5673. $wsdl,
  5674. xml_get_current_line_number($this->parser),
  5675. xml_error_string(xml_get_error_code($this->parser))
  5676. );
  5677. $this->debug($errstr);
  5678. $this->debug("XML payload:\n" . $wsdl_string);
  5679. $this->setError($errstr);
  5680. return false;
  5681. }
  5682. // free the parser
  5683. xml_parser_free($this->parser);
  5684. $this->debug('Parsing WSDL done');
  5685. // catch wsdl parse errors
  5686. if($this->getError()){
  5687. return false;
  5688. }
  5689. return true;
  5690. }
  5691. /**
  5692. * start-element handler
  5693. *
  5694. * @param string $parser XML parser object
  5695. * @param string $name element name
  5696. * @param string $attrs associative array of attributes
  5697. * @access private
  5698. */
  5699. function start_element($parser, $name, $attrs)
  5700. {
  5701. if ($this->status == 'schema') {
  5702. $this->currentSchema->schemaStartElement($parser, $name, $attrs);
  5703. $this->appendDebug($this->currentSchema->getDebug());
  5704. $this->currentSchema->clearDebug();
  5705. } elseif (preg_match('/schema$/', $name)) {
  5706. $this->debug('Parsing WSDL schema');
  5707. // $this->debug("startElement for $name ($attrs[name]). status = $this->status (".$this->getLocalPart($name).")");
  5708. $this->status = 'schema';
  5709. $this->currentSchema = new nusoap_xmlschema('', '', $this->namespaces);
  5710. $this->currentSchema->schemaStartElement($parser, $name, $attrs);
  5711. $this->appendDebug($this->currentSchema->getDebug());
  5712. $this->currentSchema->clearDebug();
  5713. } else {
  5714. // position in the total number of elements, starting from 0
  5715. $pos = $this->position++;
  5716. $depth = $this->depth++;
  5717. // set self as current value for this depth
  5718. $this->depth_array[$depth] = $pos;
  5719. $this->message[$pos] = array('cdata' => '');
  5720. // process attributes
  5721. if (count($attrs) > 0) {
  5722. // register namespace declarations
  5723. foreach($attrs as $k => $v) {
  5724. if (preg_match('/^xmlns/',$k)) {
  5725. if ($ns_prefix = substr(strrchr($k, ':'), 1)) {
  5726. $this->namespaces[$ns_prefix] = $v;
  5727. } else {
  5728. $this->namespaces['ns' . (count($this->namespaces) + 1)] = $v;
  5729. }
  5730. if ($v == 'http://www.w3.org/2001/XMLSchema' || $v == 'http://www.w3.org/1999/XMLSchema' || $v == 'http://www.w3.org/2000/10/XMLSchema') {
  5731. $this->XMLSchemaVersion = $v;
  5732. $this->namespaces['xsi'] = $v . '-instance';
  5733. }
  5734. }
  5735. }
  5736. // expand each attribute prefix to its namespace
  5737. foreach($attrs as $k => $v) {
  5738. $k = strpos($k, ':') ? $this->expandQname($k) : $k;
  5739. if ($k != 'location' && $k != 'soapAction' && $k != 'namespace') {
  5740. $v = strpos($v, ':') ? $this->expandQname($v) : $v;
  5741. }
  5742. $eAttrs[$k] = $v;
  5743. }
  5744. $attrs = $eAttrs;
  5745. } else {
  5746. $attrs = array();
  5747. }
  5748. // get element prefix, namespace and name
  5749. if (preg_match('/:/', $name)) {
  5750. // get ns prefix
  5751. $prefix = substr($name, 0, strpos($name, ':'));
  5752. // get ns
  5753. $namespace = isset($this->namespaces[$prefix]) ? $this->namespaces[$prefix] : '';
  5754. // get unqualified name
  5755. $name = substr(strstr($name, ':'), 1);
  5756. }
  5757. // process attributes, expanding any prefixes to namespaces
  5758. // find status, register data
  5759. switch ($this->status) {
  5760. case 'message':
  5761. if ($name == 'part') {
  5762. if (isset($attrs['type'])) {
  5763. $this->debug("msg " . $this->currentMessage . ": found part (with type) $attrs[name]: " . implode(',', $attrs));
  5764. $this->messages[$this->currentMessage][$attrs['name']] = $attrs['type'];
  5765. }
  5766. if (isset($attrs['element'])) {
  5767. $this->debug("msg " . $this->currentMessage . ": found part (with element) $attrs[name]: " . implode(',', $attrs));
  5768. $this->messages[$this->currentMessage][$attrs['name']] = $attrs['element'] . '^';
  5769. }
  5770. }
  5771. break;
  5772. case 'portType':
  5773. switch ($name) {
  5774. case 'operation':
  5775. $this->currentPortOperation = $attrs['name'];
  5776. $this->debug("portType $this->currentPortType operation: $this->currentPortOperation");
  5777. if (isset($attrs['parameterOrder'])) {
  5778. $this->portTypes[$this->currentPortType][$attrs['name']]['parameterOrder'] = $attrs['parameterOrder'];
  5779. }
  5780. break;
  5781. case 'documentation':
  5782. $this->documentation = true;
  5783. break;
  5784. // merge input/output data
  5785. default:
  5786. $m = isset($attrs['message']) ? $this->getLocalPart($attrs['message']) : '';
  5787. $this->portTypes[$this->currentPortType][$this->currentPortOperation][$name]['message'] = $m;
  5788. break;
  5789. }
  5790. break;
  5791. case 'binding':
  5792. switch ($name) {
  5793. case 'binding':
  5794. // get ns prefix
  5795. if (isset($attrs['style'])) {
  5796. $this->bindings[$this->currentBinding]['prefix'] = $prefix;
  5797. }
  5798. $this->bindings[$this->currentBinding] = array_merge($this->bindings[$this->currentBinding], $attrs);
  5799. break;
  5800. case 'header':
  5801. $this->bindings[$this->currentBinding]['operations'][$this->currentOperation][$this->opStatus]['headers'][] = $attrs;
  5802. break;
  5803. case 'operation':
  5804. if (isset($attrs['soapAction'])) {
  5805. $this->bindings[$this->currentBinding]['operations'][$this->currentOperation]['soapAction'] = $attrs['soapAction'];
  5806. }
  5807. if (isset($attrs['style'])) {
  5808. $this->bindings[$this->currentBinding]['operations'][$this->currentOperation]['style'] = $attrs['style'];
  5809. }
  5810. if (isset($attrs['name'])) {
  5811. $this->currentOperation = $attrs['name'];
  5812. $this->debug("current binding operation: $this->currentOperation");
  5813. $this->bindings[$this->currentBinding]['operations'][$this->currentOperation]['name'] = $attrs['name'];
  5814. $this->bindings[$this->currentBinding]['operations'][$this->currentOperation]['binding'] = $this->currentBinding;
  5815. $this->bindings[$this->currentBinding]['operations'][$this->currentOperation]['endpoint'] = isset($this->bindings[$this->currentBinding]['endpoint']) ? $this->bindings[$this->currentBinding]['endpoint'] : '';
  5816. }
  5817. break;
  5818. case 'input':
  5819. $this->opStatus = 'input';
  5820. break;
  5821. case 'output':
  5822. $this->opStatus = 'output';
  5823. break;
  5824. case 'body':
  5825. if (isset($this->bindings[$this->currentBinding]['operations'][$this->currentOperation][$this->opStatus])) {
  5826. $this->bindings[$this->currentBinding]['operations'][$this->currentOperation][$this->opStatus] = array_merge($this->bindings[$this->currentBinding]['operations'][$this->currentOperation][$this->opStatus], $attrs);
  5827. } else {
  5828. $this->bindings[$this->currentBinding]['operations'][$this->currentOperation][$this->opStatus] = $attrs;
  5829. }
  5830. break;
  5831. }
  5832. break;
  5833. case 'service':
  5834. switch ($name) {
  5835. case 'port':
  5836. $this->currentPort = $attrs['name'];
  5837. $this->debug('current port: ' . $this->currentPort);
  5838. $this->ports[$this->currentPort]['binding'] = $this->getLocalPart($attrs['binding']);
  5839. break;
  5840. case 'address':
  5841. $this->ports[$this->currentPort]['location'] = $attrs['location'];
  5842. $this->ports[$this->currentPort]['bindingType'] = $namespace;
  5843. $this->bindings[ $this->ports[$this->currentPort]['binding'] ]['bindingType'] = $namespace;
  5844. $this->bindings[ $this->ports[$this->currentPort]['binding'] ]['endpoint'] = $attrs['location'];
  5845. break;
  5846. }
  5847. break;
  5848. }
  5849. // set status
  5850. switch ($name) {
  5851. case 'import':
  5852. if (isset($attrs['location'])) {
  5853. $this->import[$attrs['namespace']][] = array('location' => $attrs['location'], 'loaded' => false);
  5854. $this->debug('parsing import ' . $attrs['namespace']. ' - ' . $attrs['location'] . ' (' . count($this->import[$attrs['namespace']]).')');
  5855. } else {
  5856. $this->import[$attrs['namespace']][] = array('location' => '', 'loaded' => true);
  5857. if (! $this->getPrefixFromNamespace($attrs['namespace'])) {
  5858. $this->namespaces['ns'.(count($this->namespaces)+1)] = $attrs['namespace'];
  5859. }
  5860. $this->debug('parsing import ' . $attrs['namespace']. ' - [no location] (' . count($this->import[$attrs['namespace']]).')');
  5861. }
  5862. break;
  5863. //wait for schema
  5864. //case 'types':
  5865. // $this->status = 'schema';
  5866. // break;
  5867. case 'message':
  5868. $this->status = 'message';
  5869. $this->messages[$attrs['name']] = array();
  5870. $this->currentMessage = $attrs['name'];
  5871. break;
  5872. case 'portType':
  5873. $this->status = 'portType';
  5874. $this->portTypes[$attrs['name']] = array();
  5875. $this->currentPortType = $attrs['name'];
  5876. break;
  5877. case "binding":
  5878. if (isset($attrs['name'])) {
  5879. // get binding name
  5880. if (strpos($attrs['name'], ':')) {
  5881. $this->currentBinding = $this->getLocalPart($attrs['name']);
  5882. } else {
  5883. $this->currentBinding = $attrs['name'];
  5884. }
  5885. $this->status = 'binding';
  5886. $this->bindings[$this->currentBinding]['portType'] = $this->getLocalPart($attrs['type']);
  5887. $this->debug("current binding: $this->currentBinding of portType: " . $attrs['type']);
  5888. }
  5889. break;
  5890. case 'service':
  5891. $this->serviceName = $attrs['name'];
  5892. $this->status = 'service';
  5893. $this->debug('current service: ' . $this->serviceName);
  5894. break;
  5895. case 'definitions':
  5896. foreach ($attrs as $name => $value) {
  5897. $this->wsdl_info[$name] = $value;
  5898. }
  5899. break;
  5900. }
  5901. }
  5902. }
  5903. /**
  5904. * end-element handler
  5905. *
  5906. * @param string $parser XML parser object
  5907. * @param string $name element name
  5908. * @access private
  5909. */
  5910. function end_element($parser, $name){
  5911. // unset schema status
  5912. if (/*preg_match('/types$/', $name) ||*/ preg_match('/schema$/', $name)) {
  5913. $this->status = "";
  5914. $this->appendDebug($this->currentSchema->getDebug());
  5915. $this->currentSchema->clearDebug();
  5916. $this->schemas[$this->currentSchema->schemaTargetNamespace][] = $this->currentSchema;
  5917. $this->debug('Parsing WSDL schema done');
  5918. }
  5919. if ($this->status == 'schema') {
  5920. $this->currentSchema->schemaEndElement($parser, $name);
  5921. } else {
  5922. // bring depth down a notch
  5923. $this->depth--;
  5924. }
  5925. // end documentation
  5926. if ($this->documentation) {
  5927. //TODO: track the node to which documentation should be assigned; it can be a part, message, etc.
  5928. //$this->portTypes[$this->currentPortType][$this->currentPortOperation]['documentation'] = $this->documentation;
  5929. $this->documentation = false;
  5930. }
  5931. }
  5932. /**
  5933. * element content handler
  5934. *
  5935. * @param string $parser XML parser object
  5936. * @param string $data element content
  5937. * @access private
  5938. */
  5939. function character_data($parser, $data)
  5940. {
  5941. $pos = isset($this->depth_array[$this->depth]) ? $this->depth_array[$this->depth] : 0;
  5942. if (isset($this->message[$pos]['cdata'])) {
  5943. $this->message[$pos]['cdata'] .= $data;
  5944. }
  5945. if ($this->documentation) {
  5946. $this->documentation .= $data;
  5947. }
  5948. }
  5949. /**
  5950. * if authenticating, set user credentials here
  5951. *
  5952. * @param string $username
  5953. * @param string $password
  5954. * @param string $authtype (basic|digest|certificate|ntlm)
  5955. * @param array $certRequest (keys must be cainfofile (optional), sslcertfile, sslkeyfile, passphrase, certpassword (optional), verifypeer (optional), verifyhost (optional): see corresponding options in cURL docs)
  5956. * @access public
  5957. */
  5958. function setCredentials($username, $password, $authtype = 'basic', $certRequest = array()) {
  5959. $this->debug("setCredentials username=$username authtype=$authtype certRequest=");
  5960. $this->appendDebug($this->varDump($certRequest));
  5961. $this->username = $username;
  5962. $this->password = $password;
  5963. $this->authtype = $authtype;
  5964. $this->certRequest = $certRequest;
  5965. }
  5966. function getBindingData($binding)
  5967. {
  5968. if (is_array($this->bindings[$binding])) {
  5969. return $this->bindings[$binding];
  5970. }
  5971. }
  5972. /**
  5973. * returns an assoc array of operation names => operation data
  5974. *
  5975. * @param string $portName WSDL port name
  5976. * @param string $bindingType eg: soap, smtp, dime (only soap and soap12 are currently supported)
  5977. * @return array
  5978. * @access public
  5979. */
  5980. function getOperations($portName = '', $bindingType = 'soap') {
  5981. $ops = array();
  5982. if ($bindingType == 'soap') {
  5983. $bindingType = 'http://schemas.xmlsoap.org/wsdl/soap/';
  5984. } elseif ($bindingType == 'soap12') {
  5985. $bindingType = 'http://schemas.xmlsoap.org/wsdl/soap12/';
  5986. } else {
  5987. $this->debug("getOperations bindingType $bindingType may not be supported");
  5988. }
  5989. $this->debug("getOperations for port '$portName' bindingType $bindingType");
  5990. // loop thru ports
  5991. foreach($this->ports as $port => $portData) {
  5992. $this->debug("getOperations checking port $port bindingType " . $portData['bindingType']);
  5993. if ($portName == '' || $port == $portName) {
  5994. // binding type of port matches parameter
  5995. if ($portData['bindingType'] == $bindingType) {
  5996. $this->debug("getOperations found port $port bindingType $bindingType");
  5997. //$this->debug("port data: " . $this->varDump($portData));
  5998. //$this->debug("bindings: " . $this->varDump($this->bindings[ $portData['binding'] ]));
  5999. // merge bindings
  6000. if (isset($this->bindings[ $portData['binding'] ]['operations'])) {
  6001. $ops = array_merge ($ops, $this->bindings[ $portData['binding'] ]['operations']);
  6002. }
  6003. }
  6004. }
  6005. }
  6006. if (count($ops) == 0) {
  6007. $this->debug("getOperations found no operations for port '$portName' bindingType $bindingType");
  6008. }
  6009. return $ops;
  6010. }
  6011. /**
  6012. * returns an associative array of data necessary for calling an operation
  6013. *
  6014. * @param string $operation name of operation
  6015. * @param string $bindingType type of binding eg: soap, soap12
  6016. * @return array
  6017. * @access public
  6018. */
  6019. function getOperationData($operation, $bindingType = 'soap')
  6020. {
  6021. if ($bindingType == 'soap') {
  6022. $bindingType = 'http://schemas.xmlsoap.org/wsdl/soap/';
  6023. } elseif ($bindingType == 'soap12') {
  6024. $bindingType = 'http://schemas.xmlsoap.org/wsdl/soap12/';
  6025. }
  6026. // loop thru ports
  6027. foreach($this->ports as $port => $portData) {
  6028. // binding type of port matches parameter
  6029. if ($portData['bindingType'] == $bindingType) {
  6030. // get binding
  6031. //foreach($this->bindings[ $portData['binding'] ]['operations'] as $bOperation => $opData) {
  6032. foreach(array_keys($this->bindings[ $portData['binding'] ]['operations']) as $bOperation) {
  6033. // note that we could/should also check the namespace here
  6034. if ($operation == $bOperation) {
  6035. $opData = $this->bindings[ $portData['binding'] ]['operations'][$operation];
  6036. return $opData;
  6037. }
  6038. }
  6039. }
  6040. }
  6041. }
  6042. /**
  6043. * returns an associative array of data necessary for calling an operation
  6044. *
  6045. * @param string $soapAction soapAction for operation
  6046. * @param string $bindingType type of binding eg: soap, soap12
  6047. * @return array
  6048. * @access public
  6049. */
  6050. function getOperationDataForSoapAction($soapAction, $bindingType = 'soap') {
  6051. if ($bindingType == 'soap') {
  6052. $bindingType = 'http://schemas.xmlsoap.org/wsdl/soap/';
  6053. } elseif ($bindingType == 'soap12') {
  6054. $bindingType = 'http://schemas.xmlsoap.org/wsdl/soap12/';
  6055. }
  6056. // loop thru ports
  6057. foreach($this->ports as $port => $portData) {
  6058. // binding type of port matches parameter
  6059. if ($portData['bindingType'] == $bindingType) {
  6060. // loop through operations for the binding
  6061. foreach ($this->bindings[ $portData['binding'] ]['operations'] as $bOperation => $opData) {
  6062. if ($opData['soapAction'] == $soapAction) {
  6063. return $opData;
  6064. }
  6065. }
  6066. }
  6067. }
  6068. }
  6069. /**
  6070. * returns an array of information about a given type
  6071. * returns false if no type exists by the given name
  6072. *
  6073. * typeDef = array(
  6074. * 'elements' => array(), // refs to elements array
  6075. * 'restrictionBase' => '',
  6076. * 'phpType' => '',
  6077. * 'order' => '(sequence|all)',
  6078. * 'attrs' => array() // refs to attributes array
  6079. * )
  6080. *
  6081. * @param string $type the type
  6082. * @param string $ns namespace (not prefix) of the type
  6083. * @return mixed
  6084. * @access public
  6085. * @see nusoap_xmlschema
  6086. */
  6087. function getTypeDef($type, $ns) {
  6088. $this->debug("in getTypeDef: type=$type, ns=$ns");
  6089. if ((! $ns) && isset($this->namespaces['tns'])) {
  6090. $ns = $this->namespaces['tns'];
  6091. $this->debug("in getTypeDef: type namespace forced to $ns");
  6092. }
  6093. if (!isset($this->schemas[$ns])) {
  6094. foreach ($this->schemas as $ns0 => $schema0) {
  6095. if (strcasecmp($ns, $ns0) == 0) {
  6096. $this->debug("in getTypeDef: replacing schema namespace $ns with $ns0");
  6097. $ns = $ns0;
  6098. break;
  6099. }
  6100. }
  6101. }
  6102. if (isset($this->schemas[$ns])) {
  6103. $this->debug("in getTypeDef: have schema for namespace $ns");
  6104. for ($i = 0; $i < count($this->schemas[$ns]); $i++) {
  6105. $xs = &$this->schemas[$ns][$i];
  6106. $t = $xs->getTypeDef($type);
  6107. $this->appendDebug($xs->getDebug());
  6108. $xs->clearDebug();
  6109. if ($t) {
  6110. $this->debug("in getTypeDef: found type $type");
  6111. if (!isset($t['phpType'])) {
  6112. // get info for type to tack onto the element
  6113. $uqType = substr($t['type'], strrpos($t['type'], ':') + 1);
  6114. $ns = substr($t['type'], 0, strrpos($t['type'], ':'));
  6115. $etype = $this->getTypeDef($uqType, $ns);
  6116. if ($etype) {
  6117. $this->debug("found type for [element] $type:");
  6118. $this->debug($this->varDump($etype));
  6119. if (isset($etype['phpType'])) {
  6120. $t['phpType'] = $etype['phpType'];
  6121. }
  6122. if (isset($etype['elements'])) {
  6123. $t['elements'] = $etype['elements'];
  6124. }
  6125. if (isset($etype['attrs'])) {
  6126. $t['attrs'] = $etype['attrs'];
  6127. }
  6128. } else {
  6129. $this->debug("did not find type for [element] $type");
  6130. }
  6131. }
  6132. return $t;
  6133. }
  6134. }
  6135. $this->debug("in getTypeDef: did not find type $type");
  6136. } else {
  6137. $this->debug("in getTypeDef: do not have schema for namespace $ns");
  6138. }
  6139. return false;
  6140. }
  6141. /**
  6142. * prints html description of services
  6143. *
  6144. * @access private
  6145. */
  6146. function webDescription(){
  6147. global $HTTP_SERVER_VARS;
  6148. if (isset($_SERVER)) {
  6149. $PHP_SELF = $_SERVER['PHP_SELF'];
  6150. } elseif (isset($HTTP_SERVER_VARS)) {
  6151. $PHP_SELF = $HTTP_SERVER_VARS['PHP_SELF'];
  6152. } else {
  6153. $this->setError("Neither _SERVER nor HTTP_SERVER_VARS is available");
  6154. }
  6155. $b = '
  6156. <html><head><title>NuSOAP: '.$this->serviceName.'</title>
  6157. <style type="text/css">
  6158. body { font-family: arial; color: #000000; background-color: #ffffff; margin: 0px 0px 0px 0px; }
  6159. p { font-family: arial; color: #000000; margin-top: 0px; margin-bottom: 12px; }
  6160. pre { background-color: silver; padding: 5px; font-family: Courier New; font-size: x-small; color: #000000;}
  6161. ul { margin-top: 10px; margin-left: 20px; }
  6162. li { list-style-type: none; margin-top: 10px; color: #000000; }
  6163. .content{
  6164. margin-left: 0px; padding-bottom: 2em; }
  6165. .nav {
  6166. padding-top: 10px; padding-bottom: 10px; padding-left: 15px; font-size: .70em;
  6167. margin-top: 10px; margin-left: 0px; color: #000000;
  6168. background-color: #ccccff; width: 20%; margin-left: 20px; margin-top: 20px; }
  6169. .title {
  6170. font-family: arial; font-size: 26px; color: #ffffff;
  6171. background-color: #999999; width: 100%;
  6172. margin-left: 0px; margin-right: 0px;
  6173. padding-top: 10px; padding-bottom: 10px;}
  6174. .hidden {
  6175. position: absolute; visibility: hidden; z-index: 200; left: 250px; top: 100px;
  6176. font-family: arial; overflow: hidden; width: 600;
  6177. padding: 20px; font-size: 10px; background-color: #999999;
  6178. layer-background-color:#FFFFFF; }
  6179. a,a:active { color: charcoal; font-weight: bold; }
  6180. a:visited { color: #666666; font-weight: bold; }
  6181. a:hover { color: cc3300; font-weight: bold; }
  6182. </style>
  6183. <script language="JavaScript" type="text/javascript">
  6184. <!--
  6185. // POP-UP CAPTIONS...
  6186. function lib_bwcheck(){ //Browsercheck (needed)
  6187. this.ver=navigator.appVersion
  6188. this.agent=navigator.userAgent
  6189. this.dom=document.getElementById?1:0
  6190. this.opera5=this.agent.indexOf("Opera 5")>-1
  6191. this.ie5=(this.ver.indexOf("MSIE 5")>-1 && this.dom && !this.opera5)?1:0;
  6192. this.ie6=(this.ver.indexOf("MSIE 6")>-1 && this.dom && !this.opera5)?1:0;
  6193. this.ie4=(document.all && !this.dom && !this.opera5)?1:0;
  6194. this.ie=this.ie4||this.ie5||this.ie6
  6195. this.mac=this.agent.indexOf("Mac")>-1
  6196. this.ns6=(this.dom && parseInt(this.ver) >= 5) ?1:0;
  6197. this.ns4=(document.layers && !this.dom)?1:0;
  6198. this.bw=(this.ie6 || this.ie5 || this.ie4 || this.ns4 || this.ns6 || this.opera5)
  6199. return this
  6200. }
  6201. var bw = new lib_bwcheck()
  6202. //Makes crossbrowser object.
  6203. function makeObj(obj){
  6204. this.evnt=bw.dom? document.getElementById(obj):bw.ie4?document.all[obj]:bw.ns4?document.layers[obj]:0;
  6205. if(!this.evnt) return false
  6206. this.css=bw.dom||bw.ie4?this.evnt.style:bw.ns4?this.evnt:0;
  6207. this.wref=bw.dom||bw.ie4?this.evnt:bw.ns4?this.css.document:0;
  6208. this.writeIt=b_writeIt;
  6209. return this
  6210. }
  6211. // A unit of measure that will be added when setting the position of a layer.
  6212. //var px = bw.ns4||window.opera?"":"px";
  6213. function b_writeIt(text){
  6214. if (bw.ns4){this.wref.write(text);this.wref.close()}
  6215. else this.wref.innerHTML = text
  6216. }
  6217. //Shows the messages
  6218. var oDesc;
  6219. function popup(divid){
  6220. if(oDesc = new makeObj(divid)){
  6221. oDesc.css.visibility = "visible"
  6222. }
  6223. }
  6224. function popout(){ // Hides message
  6225. if(oDesc) oDesc.css.visibility = "hidden"
  6226. }
  6227. //-->
  6228. </script>
  6229. </head>
  6230. <body>
  6231. <div class=content>
  6232. <br><br>
  6233. <div class=title>'.$this->serviceName.'</div>
  6234. <div class=nav>
  6235. <p>View the <a href="'.$PHP_SELF.'?wsdl">WSDL</a> for the service.
  6236. Click on an operation name to view it&apos;s details.</p>
  6237. <ul>';
  6238. foreach($this->getOperations() as $op => $data){
  6239. $b .= "<li><a href='#' onclick=\"popout();popup('$op')\">$op</a></li>";
  6240. // create hidden div
  6241. $b .= "<div id='$op' class='hidden'>
  6242. <a href='#' onclick='popout()'><font color='#ffffff'>Close</font></a><br><br>";
  6243. foreach($data as $donnie => $marie){ // loop through opdata
  6244. if($donnie == 'input' || $donnie == 'output'){ // show input/output data
  6245. $b .= "<font color='white'>".ucfirst($donnie).':</font><br>';
  6246. foreach($marie as $captain => $tenille){ // loop through data
  6247. if($captain == 'parts'){ // loop thru parts
  6248. $b .= "&nbsp;&nbsp;$captain:<br>";
  6249. //if(is_array($tenille)){
  6250. foreach($tenille as $joanie => $chachi){
  6251. $b .= "&nbsp;&nbsp;&nbsp;&nbsp;$joanie: $chachi<br>";
  6252. }
  6253. //}
  6254. } else {
  6255. $b .= "&nbsp;&nbsp;$captain: $tenille<br>";
  6256. }
  6257. }
  6258. } else {
  6259. $b .= "<font color='white'>".ucfirst($donnie).":</font> $marie<br>";
  6260. }
  6261. }
  6262. $b .= '</div>';
  6263. }
  6264. $b .= '
  6265. <ul>
  6266. </div>
  6267. </div></body></html>';
  6268. return $b;
  6269. }
  6270. /**
  6271. * serialize the parsed wsdl
  6272. *
  6273. * @param mixed $debug whether to put debug=1 in endpoint URL
  6274. * @return string serialization of WSDL
  6275. * @access public
  6276. */
  6277. function serialize($debug = 0)
  6278. {
  6279. $xml = '<?xml version="1.0" encoding="ISO-8859-1"?>';
  6280. $xml .= "\n<definitions";
  6281. foreach($this->namespaces as $k => $v) {
  6282. $xml .= " xmlns:$k=\"$v\"";
  6283. }
  6284. // 10.9.02 - add poulter fix for wsdl and tns declarations
  6285. if (isset($this->namespaces['wsdl'])) {
  6286. $xml .= " xmlns=\"" . $this->namespaces['wsdl'] . "\"";
  6287. }
  6288. if (isset($this->namespaces['tns'])) {
  6289. $xml .= " targetNamespace=\"" . $this->namespaces['tns'] . "\"";
  6290. }
  6291. $xml .= '>';
  6292. // imports
  6293. if (sizeof($this->import) > 0) {
  6294. foreach($this->import as $ns => $list) {
  6295. foreach ($list as $ii) {
  6296. if ($ii['location'] != '') {
  6297. $xml .= '<import location="' . $ii['location'] . '" namespace="' . $ns . '" />';
  6298. } else {
  6299. $xml .= '<import namespace="' . $ns . '" />';
  6300. }
  6301. }
  6302. }
  6303. }
  6304. // types
  6305. if (count($this->schemas)>=1) {
  6306. $xml .= "\n<types>\n";
  6307. foreach ($this->schemas as $ns => $list) {
  6308. foreach ($list as $xs) {
  6309. $xml .= $xs->serializeSchema();
  6310. }
  6311. }
  6312. $xml .= '</types>';
  6313. }
  6314. // messages
  6315. if (count($this->messages) >= 1) {
  6316. foreach($this->messages as $msgName => $msgParts) {
  6317. $xml .= "\n<message name=\"" . $msgName . '">';
  6318. if(is_array($msgParts)){
  6319. foreach($msgParts as $partName => $partType) {
  6320. // print 'serializing '.$partType.', sv: '.$this->XMLSchemaVersion.'<br>';
  6321. if (strpos($partType, ':')) {
  6322. $typePrefix = $this->getPrefixFromNamespace($this->getPrefix($partType));
  6323. } elseif (isset($this->typemap[$this->namespaces['xsd']][$partType])) {
  6324. // print 'checking typemap: '.$this->XMLSchemaVersion.'<br>';
  6325. $typePrefix = 'xsd';
  6326. } else {
  6327. foreach($this->typemap as $ns => $types) {
  6328. if (isset($types[$partType])) {
  6329. $typePrefix = $this->getPrefixFromNamespace($ns);
  6330. }
  6331. }
  6332. if (!isset($typePrefix)) {
  6333. die("$partType has no namespace!");
  6334. }
  6335. }
  6336. $ns = $this->getNamespaceFromPrefix($typePrefix);
  6337. $localPart = $this->getLocalPart($partType);
  6338. $typeDef = $this->getTypeDef($localPart, $ns);
  6339. if ($typeDef['typeClass'] == 'element') {
  6340. $elementortype = 'element';
  6341. if (substr($localPart, -1) == '^') {
  6342. $localPart = substr($localPart, 0, -1);
  6343. }
  6344. } else {
  6345. $elementortype = 'type';
  6346. }
  6347. $xml .= "\n" . ' <part name="' . $partName . '" ' . $elementortype . '="' . $typePrefix . ':' . $localPart . '" />';
  6348. }
  6349. }
  6350. $xml .= '</message>';
  6351. }
  6352. }
  6353. // bindings & porttypes
  6354. if (count($this->bindings) >= 1) {
  6355. $binding_xml = '';
  6356. $portType_xml = '';
  6357. foreach($this->bindings as $bindingName => $attrs) {
  6358. $binding_xml .= "\n<binding name=\"" . $bindingName . '" type="tns:' . $attrs['portType'] . '">';
  6359. $binding_xml .= "\n" . ' <soap:binding style="' . $attrs['style'] . '" transport="' . $attrs['transport'] . '"/>';
  6360. $portType_xml .= "\n<portType name=\"" . $attrs['portType'] . '">';
  6361. foreach($attrs['operations'] as $opName => $opParts) {
  6362. $binding_xml .= "\n" . ' <operation name="' . $opName . '">';
  6363. $binding_xml .= "\n" . ' <soap:operation soapAction="' . $opParts['soapAction'] . '" style="'. $opParts['style'] . '"/>';
  6364. if (isset($opParts['input']['encodingStyle']) && $opParts['input']['encodingStyle'] != '') {
  6365. $enc_style = ' encodingStyle="' . $opParts['input']['encodingStyle'] . '"';
  6366. } else {
  6367. $enc_style = '';
  6368. }
  6369. $binding_xml .= "\n" . ' <input><soap:body use="' . $opParts['input']['use'] . '" namespace="' . $opParts['input']['namespace'] . '"' . $enc_style . '/></input>';
  6370. if (isset($opParts['output']['encodingStyle']) && $opParts['output']['encodingStyle'] != '') {
  6371. $enc_style = ' encodingStyle="' . $opParts['output']['encodingStyle'] . '"';
  6372. } else {
  6373. $enc_style = '';
  6374. }
  6375. $binding_xml .= "\n" . ' <output><soap:body use="' . $opParts['output']['use'] . '" namespace="' . $opParts['output']['namespace'] . '"' . $enc_style . '/></output>';
  6376. $binding_xml .= "\n" . ' </operation>';
  6377. $portType_xml .= "\n" . ' <operation name="' . $opParts['name'] . '"';
  6378. if (isset($opParts['parameterOrder'])) {
  6379. $portType_xml .= ' parameterOrder="' . $opParts['parameterOrder'] . '"';
  6380. }
  6381. $portType_xml .= '>';
  6382. if(isset($opParts['documentation']) && $opParts['documentation'] != '') {
  6383. $portType_xml .= "\n" . ' <documentation>' . htmlspecialchars($opParts['documentation']) . '</documentation>';
  6384. }
  6385. $portType_xml .= "\n" . ' <input message="tns:' . $opParts['input']['message'] . '"/>';
  6386. $portType_xml .= "\n" . ' <output message="tns:' . $opParts['output']['message'] . '"/>';
  6387. $portType_xml .= "\n" . ' </operation>';
  6388. }
  6389. $portType_xml .= "\n" . '</portType>';
  6390. $binding_xml .= "\n" . '</binding>';
  6391. }
  6392. $xml .= $portType_xml . $binding_xml;
  6393. }
  6394. // services
  6395. $xml .= "\n<service name=\"" . $this->serviceName . '">';
  6396. if (count($this->ports) >= 1) {
  6397. foreach($this->ports as $pName => $attrs) {
  6398. $xml .= "\n" . ' <port name="' . $pName . '" binding="tns:' . $attrs['binding'] . '">';
  6399. $xml .= "\n" . ' <soap:address location="' . $attrs['location'] . ($debug ? '?debug=1' : '') . '"/>';
  6400. $xml .= "\n" . ' </port>';
  6401. }
  6402. }
  6403. $xml .= "\n" . '</service>';
  6404. return $xml . "\n</definitions>";
  6405. }
  6406. /**
  6407. * determine whether a set of parameters are unwrapped
  6408. * when they are expect to be wrapped, Microsoft-style.
  6409. *
  6410. * @param string $type the type (element name) of the wrapper
  6411. * @param array $parameters the parameter values for the SOAP call
  6412. * @return boolean whether they parameters are unwrapped (and should be wrapped)
  6413. * @access private
  6414. */
  6415. function parametersMatchWrapped($type, &$parameters) {
  6416. $this->debug("in parametersMatchWrapped type=$type, parameters=");
  6417. $this->appendDebug($this->varDump($parameters));
  6418. // split type into namespace:unqualified-type
  6419. if (strpos($type, ':')) {
  6420. $uqType = substr($type, strrpos($type, ':') + 1);
  6421. $ns = substr($type, 0, strrpos($type, ':'));
  6422. $this->debug("in parametersMatchWrapped: got a prefixed type: $uqType, $ns");
  6423. if ($this->getNamespaceFromPrefix($ns)) {
  6424. $ns = $this->getNamespaceFromPrefix($ns);
  6425. $this->debug("in parametersMatchWrapped: expanded prefixed type: $uqType, $ns");
  6426. }
  6427. } else {
  6428. // TODO: should the type be compared to types in XSD, and the namespace
  6429. // set to XSD if the type matches?
  6430. $this->debug("in parametersMatchWrapped: No namespace for type $type");
  6431. $ns = '';
  6432. $uqType = $type;
  6433. }
  6434. // get the type information
  6435. if (!$typeDef = $this->getTypeDef($uqType, $ns)) {
  6436. $this->debug("in parametersMatchWrapped: $type ($uqType) is not a supported type.");
  6437. return false;
  6438. }
  6439. $this->debug("in parametersMatchWrapped: found typeDef=");
  6440. $this->appendDebug($this->varDump($typeDef));
  6441. if (substr($uqType, -1) == '^') {
  6442. $uqType = substr($uqType, 0, -1);
  6443. }
  6444. $phpType = $typeDef['phpType'];
  6445. $arrayType = (isset($typeDef['arrayType']) ? $typeDef['arrayType'] : '');
  6446. $this->debug("in parametersMatchWrapped: uqType: $uqType, ns: $ns, phptype: $phpType, arrayType: $arrayType");
  6447. // we expect a complexType or element of complexType
  6448. if ($phpType != 'struct') {
  6449. $this->debug("in parametersMatchWrapped: not a struct");
  6450. return false;
  6451. }
  6452. // see whether the parameter names match the elements
  6453. if (isset($typeDef['elements']) && is_array($typeDef['elements'])) {
  6454. $elements = 0;
  6455. $matches = 0;
  6456. foreach ($typeDef['elements'] as $name => $attrs) {
  6457. if (isset($parameters[$name])) {
  6458. $this->debug("in parametersMatchWrapped: have parameter named $name");
  6459. $matches++;
  6460. } else {
  6461. $this->debug("in parametersMatchWrapped: do not have parameter named $name");
  6462. }
  6463. $elements++;
  6464. }
  6465. $this->debug("in parametersMatchWrapped: $matches parameter names match $elements wrapped parameter names");
  6466. if ($matches == 0) {
  6467. return false;
  6468. }
  6469. return true;
  6470. }
  6471. // since there are no elements for the type, if the user passed no
  6472. // parameters, the parameters match wrapped.
  6473. $this->debug("in parametersMatchWrapped: no elements type $ns:$uqType");
  6474. return count($parameters) == 0;
  6475. }
  6476. /**
  6477. * serialize PHP values according to a WSDL message definition
  6478. * contrary to the method name, this is not limited to RPC
  6479. *
  6480. * TODO
  6481. * - multi-ref serialization
  6482. * - validate PHP values against type definitions, return errors if invalid
  6483. *
  6484. * @param string $operation operation name
  6485. * @param string $direction (input|output)
  6486. * @param mixed $parameters parameter value(s)
  6487. * @param string $bindingType (soap|soap12)
  6488. * @return mixed parameters serialized as XML or false on error (e.g. operation not found)
  6489. * @access public
  6490. */
  6491. function serializeRPCParameters($operation, $direction, $parameters, $bindingType = 'soap') {
  6492. $this->debug("in serializeRPCParameters: operation=$operation, direction=$direction, XMLSchemaVersion=$this->XMLSchemaVersion, bindingType=$bindingType");
  6493. $this->appendDebug('parameters=' . $this->varDump($parameters));
  6494. if ($direction != 'input' && $direction != 'output') {
  6495. $this->debug('The value of the \$direction argument needs to be either "input" or "output"');
  6496. $this->setError('The value of the \$direction argument needs to be either "input" or "output"');
  6497. return false;
  6498. }
  6499. if (!$opData = $this->getOperationData($operation, $bindingType)) {
  6500. $this->debug('Unable to retrieve WSDL data for operation: ' . $operation . ' bindingType: ' . $bindingType);
  6501. $this->setError('Unable to retrieve WSDL data for operation: ' . $operation . ' bindingType: ' . $bindingType);
  6502. return false;
  6503. }
  6504. $this->debug('in serializeRPCParameters: opData:');
  6505. $this->appendDebug($this->varDump($opData));
  6506. // Get encoding style for output and set to current
  6507. $encodingStyle = 'http://schemas.xmlsoap.org/soap/encoding/';
  6508. if(($direction == 'input') && isset($opData['output']['encodingStyle']) && ($opData['output']['encodingStyle'] != $encodingStyle)) {
  6509. $encodingStyle = $opData['output']['encodingStyle'];
  6510. $enc_style = $encodingStyle;
  6511. }
  6512. // set input params
  6513. $xml = '';
  6514. if (isset($opData[$direction]['parts']) && sizeof($opData[$direction]['parts']) > 0) {
  6515. $parts = &$opData[$direction]['parts'];
  6516. $part_count = sizeof($parts);
  6517. $style = $opData['style'];
  6518. $use = $opData[$direction]['use'];
  6519. $this->debug("have $part_count part(s) to serialize using $style/$use");
  6520. if (is_array($parameters)) {
  6521. $parametersArrayType = $this->isArraySimpleOrStruct($parameters);
  6522. $parameter_count = count($parameters);
  6523. $this->debug("have $parameter_count parameter(s) provided as $parametersArrayType to serialize");
  6524. // check for Microsoft-style wrapped parameters
  6525. if ($style == 'document' && $use == 'literal' && $part_count == 1 && isset($parts['parameters'])) {
  6526. $this->debug('check whether the caller has wrapped the parameters');
  6527. if ($direction == 'output' && $parametersArrayType == 'arraySimple' && $parameter_count == 1) {
  6528. // TODO: consider checking here for double-wrapping, when
  6529. // service function wraps, then NuSOAP wraps again
  6530. $this->debug("change simple array to associative with 'parameters' element");
  6531. $parameters['parameters'] = $parameters[0];
  6532. unset($parameters[0]);
  6533. }
  6534. if (($parametersArrayType == 'arrayStruct' || $parameter_count == 0) && !isset($parameters['parameters'])) {
  6535. $this->debug('check whether caller\'s parameters match the wrapped ones');
  6536. if ($this->parametersMatchWrapped($parts['parameters'], $parameters)) {
  6537. $this->debug('wrap the parameters for the caller');
  6538. $parameters = array('parameters' => $parameters);
  6539. $parameter_count = 1;
  6540. }
  6541. }
  6542. }
  6543. foreach ($parts as $name => $type) {
  6544. $this->debug("serializing part $name of type $type");
  6545. // Track encoding style
  6546. if (isset($opData[$direction]['encodingStyle']) && $encodingStyle != $opData[$direction]['encodingStyle']) {
  6547. $encodingStyle = $opData[$direction]['encodingStyle'];
  6548. $enc_style = $encodingStyle;
  6549. } else {
  6550. $enc_style = false;
  6551. }
  6552. // NOTE: add error handling here
  6553. // if serializeType returns false, then catch global error and fault
  6554. if ($parametersArrayType == 'arraySimple') {
  6555. $p = array_shift($parameters);
  6556. $this->debug('calling serializeType w/indexed param');
  6557. $xml .= $this->serializeType($name, $type, $p, $use, $enc_style);
  6558. } elseif (isset($parameters[$name])) {
  6559. $this->debug('calling serializeType w/named param');
  6560. $xml .= $this->serializeType($name, $type, $parameters[$name], $use, $enc_style);
  6561. } else {
  6562. // TODO: only send nillable
  6563. $this->debug('calling serializeType w/null param');
  6564. $xml .= $this->serializeType($name, $type, null, $use, $enc_style);
  6565. }
  6566. }
  6567. } else {
  6568. $this->debug('no parameters passed.');
  6569. }
  6570. }
  6571. $this->debug("serializeRPCParameters returning: $xml");
  6572. return $xml;
  6573. }
  6574. /**
  6575. * serialize a PHP value according to a WSDL message definition
  6576. *
  6577. * TODO
  6578. * - multi-ref serialization
  6579. * - validate PHP values against type definitions, return errors if invalid
  6580. *
  6581. * @param string $operation operation name
  6582. * @param string $direction (input|output)
  6583. * @param mixed $parameters parameter value(s)
  6584. * @return mixed parameters serialized as XML or false on error (e.g. operation not found)
  6585. * @access public
  6586. * @deprecated
  6587. */
  6588. function serializeParameters($operation, $direction, $parameters)
  6589. {
  6590. $this->debug("in serializeParameters: operation=$operation, direction=$direction, XMLSchemaVersion=$this->XMLSchemaVersion");
  6591. $this->appendDebug('parameters=' . $this->varDump($parameters));
  6592. if ($direction != 'input' && $direction != 'output') {
  6593. $this->debug('The value of the \$direction argument needs to be either "input" or "output"');
  6594. $this->setError('The value of the \$direction argument needs to be either "input" or "output"');
  6595. return false;
  6596. }
  6597. if (!$opData = $this->getOperationData($operation)) {
  6598. $this->debug('Unable to retrieve WSDL data for operation: ' . $operation);
  6599. $this->setError('Unable to retrieve WSDL data for operation: ' . $operation);
  6600. return false;
  6601. }
  6602. $this->debug('opData:');
  6603. $this->appendDebug($this->varDump($opData));
  6604. // Get encoding style for output and set to current
  6605. $encodingStyle = 'http://schemas.xmlsoap.org/soap/encoding/';
  6606. if(($direction == 'input') && isset($opData['output']['encodingStyle']) && ($opData['output']['encodingStyle'] != $encodingStyle)) {
  6607. $encodingStyle = $opData['output']['encodingStyle'];
  6608. $enc_style = $encodingStyle;
  6609. }
  6610. // set input params
  6611. $xml = '';
  6612. if (isset($opData[$direction]['parts']) && sizeof($opData[$direction]['parts']) > 0) {
  6613. $use = $opData[$direction]['use'];
  6614. $this->debug("use=$use");
  6615. $this->debug('got ' . count($opData[$direction]['parts']) . ' part(s)');
  6616. if (is_array($parameters)) {
  6617. $parametersArrayType = $this->isArraySimpleOrStruct($parameters);
  6618. $this->debug('have ' . $parametersArrayType . ' parameters');
  6619. foreach($opData[$direction]['parts'] as $name => $type) {
  6620. $this->debug('serializing part "'.$name.'" of type "'.$type.'"');
  6621. // Track encoding style
  6622. if(isset($opData[$direction]['encodingStyle']) && $encodingStyle != $opData[$direction]['encodingStyle']) {
  6623. $encodingStyle = $opData[$direction]['encodingStyle'];
  6624. $enc_style = $encodingStyle;
  6625. } else {
  6626. $enc_style = false;
  6627. }
  6628. // NOTE: add error handling here
  6629. // if serializeType returns false, then catch global error and fault
  6630. if ($parametersArrayType == 'arraySimple') {
  6631. $p = array_shift($parameters);
  6632. $this->debug('calling serializeType w/indexed param');
  6633. $xml .= $this->serializeType($name, $type, $p, $use, $enc_style);
  6634. } elseif (isset($parameters[$name])) {
  6635. $this->debug('calling serializeType w/named param');
  6636. $xml .= $this->serializeType($name, $type, $parameters[$name], $use, $enc_style);
  6637. } else {
  6638. // TODO: only send nillable
  6639. $this->debug('calling serializeType w/null param');
  6640. $xml .= $this->serializeType($name, $type, null, $use, $enc_style);
  6641. }
  6642. }
  6643. } else {
  6644. $this->debug('no parameters passed.');
  6645. }
  6646. }
  6647. $this->debug("serializeParameters returning: $xml");
  6648. return $xml;
  6649. }
  6650. /**
  6651. * serializes a PHP value according a given type definition
  6652. *
  6653. * @param string $name name of value (part or element)
  6654. * @param string $type XML schema type of value (type or element)
  6655. * @param mixed $value a native PHP value (parameter value)
  6656. * @param string $use use for part (encoded|literal)
  6657. * @param string $encodingStyle SOAP encoding style for the value (if different than the enclosing style)
  6658. * @param boolean $unqualified a kludge for what should be XML namespace form handling
  6659. * @return string value serialized as an XML string
  6660. * @access private
  6661. */
  6662. function serializeType($name, $type, $value, $use='encoded', $encodingStyle=false, $unqualified=false)
  6663. {
  6664. $this->debug("in serializeType: name=$name, type=$type, use=$use, encodingStyle=$encodingStyle, unqualified=" . ($unqualified ? "unqualified" : "qualified"));
  6665. $this->appendDebug("value=" . $this->varDump($value));
  6666. if($use == 'encoded' && $encodingStyle) {
  6667. $encodingStyle = ' SOAP-ENV:encodingStyle="' . $encodingStyle . '"';
  6668. }
  6669. // if a soapval has been supplied, let its type override the WSDL
  6670. if (is_object($value) && get_class($value) == 'soapval') {
  6671. if ($value->type_ns) {
  6672. $type = $value->type_ns . ':' . $value->type;
  6673. $forceType = true;
  6674. $this->debug("in serializeType: soapval overrides type to $type");
  6675. } elseif ($value->type) {
  6676. $type = $value->type;
  6677. $forceType = true;
  6678. $this->debug("in serializeType: soapval overrides type to $type");
  6679. } else {
  6680. $forceType = false;
  6681. $this->debug("in serializeType: soapval does not override type");
  6682. }
  6683. $attrs = $value->attributes;
  6684. $value = $value->value;
  6685. $this->debug("in serializeType: soapval overrides value to $value");
  6686. if ($attrs) {
  6687. if (!is_array($value)) {
  6688. $value['!'] = $value;
  6689. }
  6690. foreach ($attrs as $n => $v) {
  6691. $value['!' . $n] = $v;
  6692. }
  6693. $this->debug("in serializeType: soapval provides attributes");
  6694. }
  6695. } else {
  6696. $forceType = false;
  6697. }
  6698. $xml = '';
  6699. if (strpos($type, ':')) {
  6700. $uqType = substr($type, strrpos($type, ':') + 1);
  6701. $ns = substr($type, 0, strrpos($type, ':'));
  6702. $this->debug("in serializeType: got a prefixed type: $uqType, $ns");
  6703. if ($this->getNamespaceFromPrefix($ns)) {
  6704. $ns = $this->getNamespaceFromPrefix($ns);
  6705. $this->debug("in serializeType: expanded prefixed type: $uqType, $ns");
  6706. }
  6707. if($ns == $this->XMLSchemaVersion || $ns == 'http://schemas.xmlsoap.org/soap/encoding/'){
  6708. $this->debug('in serializeType: type namespace indicates XML Schema or SOAP Encoding type');
  6709. if ($unqualified && $use == 'literal') {
  6710. $elementNS = " xmlns=\"\"";
  6711. } else {
  6712. $elementNS = '';
  6713. }
  6714. if (is_null($value)) {
  6715. if ($use == 'literal') {
  6716. // TODO: depends on minOccurs
  6717. $xml = "<$name$elementNS/>";
  6718. } else {
  6719. // TODO: depends on nillable, which should be checked before calling this method
  6720. $xml = "<$name$elementNS xsi:nil=\"true\" xsi:type=\"" . $this->getPrefixFromNamespace($ns) . ":$uqType\"/>";
  6721. }
  6722. $this->debug("in serializeType: returning: $xml");
  6723. return $xml;
  6724. }
  6725. if ($uqType == 'Array') {
  6726. // JBoss/Axis does this sometimes
  6727. return $this->serialize_val($value, $name, false, false, false, false, $use);
  6728. }
  6729. if ($uqType == 'boolean') {
  6730. if ((is_string($value) && $value == 'false') || (! $value)) {
  6731. $value = 'false';
  6732. } else {
  6733. $value = 'true';
  6734. }
  6735. }
  6736. if ($uqType == 'string' && gettype($value) == 'string') {
  6737. $value = $this->expandEntities($value);
  6738. }
  6739. if (($uqType == 'long' || $uqType == 'unsignedLong') && gettype($value) == 'double') {
  6740. $value = sprintf("%.0lf", $value);
  6741. }
  6742. // it's a scalar
  6743. // TODO: what about null/nil values?
  6744. // check type isn't a custom type extending xmlschema namespace
  6745. if (!$this->getTypeDef($uqType, $ns)) {
  6746. if ($use == 'literal') {
  6747. if ($forceType) {
  6748. $xml = "<$name$elementNS xsi:type=\"" . $this->getPrefixFromNamespace($ns) . ":$uqType\">$value</$name>";
  6749. } else {
  6750. $xml = "<$name$elementNS>$value</$name>";
  6751. }
  6752. } else {
  6753. $xml = "<$name$elementNS xsi:type=\"" . $this->getPrefixFromNamespace($ns) . ":$uqType\"$encodingStyle>$value</$name>";
  6754. }
  6755. $this->debug("in serializeType: returning: $xml");
  6756. return $xml;
  6757. }
  6758. $this->debug('custom type extends XML Schema or SOAP Encoding namespace (yuck)');
  6759. } else if ($ns == 'http://xml.apache.org/xml-soap') {
  6760. $this->debug('in serializeType: appears to be Apache SOAP type');
  6761. if ($uqType == 'Map') {
  6762. $tt_prefix = $this->getPrefixFromNamespace('http://xml.apache.org/xml-soap');
  6763. if (! $tt_prefix) {
  6764. $this->debug('in serializeType: Add namespace for Apache SOAP type');
  6765. $tt_prefix = 'ns' . rand(1000, 9999);
  6766. $this->namespaces[$tt_prefix] = 'http://xml.apache.org/xml-soap';
  6767. // force this to be added to usedNamespaces
  6768. $tt_prefix = $this->getPrefixFromNamespace('http://xml.apache.org/xml-soap');
  6769. }
  6770. $contents = '';
  6771. foreach($value as $k => $v) {
  6772. $this->debug("serializing map element: key $k, value $v");
  6773. $contents .= '<item>';
  6774. $contents .= $this->serialize_val($k,'key',false,false,false,false,$use);
  6775. $contents .= $this->serialize_val($v,'value',false,false,false,false,$use);
  6776. $contents .= '</item>';
  6777. }
  6778. if ($use == 'literal') {
  6779. if ($forceType) {
  6780. $xml = "<$name xsi:type=\"" . $tt_prefix . ":$uqType\">$contents</$name>";
  6781. } else {
  6782. $xml = "<$name>$contents</$name>";
  6783. }
  6784. } else {
  6785. $xml = "<$name xsi:type=\"" . $tt_prefix . ":$uqType\"$encodingStyle>$contents</$name>";
  6786. }
  6787. $this->debug("in serializeType: returning: $xml");
  6788. return $xml;
  6789. }
  6790. $this->debug('in serializeType: Apache SOAP type, but only support Map');
  6791. }
  6792. } else {
  6793. // TODO: should the type be compared to types in XSD, and the namespace
  6794. // set to XSD if the type matches?
  6795. $this->debug("in serializeType: No namespace for type $type");
  6796. $ns = '';
  6797. $uqType = $type;
  6798. }
  6799. if(!$typeDef = $this->getTypeDef($uqType, $ns)){
  6800. $this->setError("$type ($uqType) is not a supported type.");
  6801. $this->debug("in serializeType: $type ($uqType) is not a supported type.");
  6802. return false;
  6803. } else {
  6804. $this->debug("in serializeType: found typeDef");
  6805. $this->appendDebug('typeDef=' . $this->varDump($typeDef));
  6806. if (substr($uqType, -1) == '^') {
  6807. $uqType = substr($uqType, 0, -1);
  6808. }
  6809. }
  6810. if (!isset($typeDef['phpType'])) {
  6811. $this->setError("$type ($uqType) has no phpType.");
  6812. $this->debug("in serializeType: $type ($uqType) has no phpType.");
  6813. return false;
  6814. }
  6815. $phpType = $typeDef['phpType'];
  6816. $this->debug("in serializeType: uqType: $uqType, ns: $ns, phptype: $phpType, arrayType: " . (isset($typeDef['arrayType']) ? $typeDef['arrayType'] : '') );
  6817. // if php type == struct, map value to the <all> element names
  6818. if ($phpType == 'struct') {
  6819. if (isset($typeDef['typeClass']) && $typeDef['typeClass'] == 'element') {
  6820. $elementName = $uqType;
  6821. if (isset($typeDef['form']) && ($typeDef['form'] == 'qualified')) {
  6822. $elementNS = " xmlns=\"$ns\"";
  6823. } else {
  6824. $elementNS = " xmlns=\"\"";
  6825. }
  6826. } else {
  6827. $elementName = $name;
  6828. if ($unqualified) {
  6829. $elementNS = " xmlns=\"\"";
  6830. } else {
  6831. $elementNS = '';
  6832. }
  6833. }
  6834. if (is_null($value)) {
  6835. if ($use == 'literal') {
  6836. // TODO: depends on minOccurs and nillable
  6837. $xml = "<$elementName$elementNS/>";
  6838. } else {
  6839. $xml = "<$elementName$elementNS xsi:nil=\"true\" xsi:type=\"" . $this->getPrefixFromNamespace($ns) . ":$uqType\"/>";
  6840. }
  6841. $this->debug("in serializeType: returning: $xml");
  6842. return $xml;
  6843. }
  6844. if (is_object($value)) {
  6845. $value = get_object_vars($value);
  6846. }
  6847. if (is_array($value)) {
  6848. $elementAttrs = $this->serializeComplexTypeAttributes($typeDef, $value, $ns, $uqType);
  6849. if ($use == 'literal') {
  6850. if ($forceType) {
  6851. $xml = "<$elementName$elementNS$elementAttrs xsi:type=\"" . $this->getPrefixFromNamespace($ns) . ":$uqType\">";
  6852. } else {
  6853. $xml = "<$elementName$elementNS$elementAttrs>";
  6854. }
  6855. } else {
  6856. $xml = "<$elementName$elementNS$elementAttrs xsi:type=\"" . $this->getPrefixFromNamespace($ns) . ":$uqType\"$encodingStyle>";
  6857. }
  6858. if (isset($typeDef['simpleContent']) && $typeDef['simpleContent'] == 'true') {
  6859. if (isset($value['!'])) {
  6860. $xml .= $value['!'];
  6861. $this->debug("in serializeType: serialized simpleContent for type $type");
  6862. } else {
  6863. $this->debug("in serializeType: no simpleContent to serialize for type $type");
  6864. }
  6865. } else {
  6866. // complexContent
  6867. $xml .= $this->serializeComplexTypeElements($typeDef, $value, $ns, $uqType, $use, $encodingStyle);
  6868. }
  6869. $xml .= "</$elementName>";
  6870. } else {
  6871. $this->debug("in serializeType: phpType is struct, but value is not an array");
  6872. $this->setError("phpType is struct, but value is not an array: see debug output for details");
  6873. $xml = '';
  6874. }
  6875. } elseif ($phpType == 'array') {
  6876. if (isset($typeDef['form']) && ($typeDef['form'] == 'qualified')) {
  6877. $elementNS = " xmlns=\"$ns\"";
  6878. } else {
  6879. if ($unqualified) {
  6880. $elementNS = " xmlns=\"\"";
  6881. } else {
  6882. $elementNS = '';
  6883. }
  6884. }
  6885. if (is_null($value)) {
  6886. if ($use == 'literal') {
  6887. // TODO: depends on minOccurs
  6888. $xml = "<$name$elementNS/>";
  6889. } else {
  6890. $xml = "<$name$elementNS xsi:nil=\"true\" xsi:type=\"" .
  6891. $this->getPrefixFromNamespace('http://schemas.xmlsoap.org/soap/encoding/') .
  6892. ":Array\" " .
  6893. $this->getPrefixFromNamespace('http://schemas.xmlsoap.org/soap/encoding/') .
  6894. ':arrayType="' .
  6895. $this->getPrefixFromNamespace($this->getPrefix($typeDef['arrayType'])) .
  6896. ':' .
  6897. $this->getLocalPart($typeDef['arrayType'])."[0]\"/>";
  6898. }
  6899. $this->debug("in serializeType: returning: $xml");
  6900. return $xml;
  6901. }
  6902. if (isset($typeDef['multidimensional'])) {
  6903. $nv = array();
  6904. foreach($value as $v) {
  6905. $cols = ',' . sizeof($v);
  6906. $nv = array_merge($nv, $v);
  6907. }
  6908. $value = $nv;
  6909. } else {
  6910. $cols = '';
  6911. }
  6912. if (is_array($value) && sizeof($value) >= 1) {
  6913. $rows = sizeof($value);
  6914. $contents = '';
  6915. foreach($value as $k => $v) {
  6916. $this->debug("serializing array element: $k, $v of type: $typeDef[arrayType]");
  6917. //if (strpos($typeDef['arrayType'], ':') ) {
  6918. if (!in_array($typeDef['arrayType'],$this->typemap['http://www.w3.org/2001/XMLSchema'])) {
  6919. $contents .= $this->serializeType('item', $typeDef['arrayType'], $v, $use);
  6920. } else {
  6921. $contents .= $this->serialize_val($v, 'item', $typeDef['arrayType'], null, $this->XMLSchemaVersion, false, $use);
  6922. }
  6923. }
  6924. } else {
  6925. $rows = 0;
  6926. $contents = null;
  6927. }
  6928. // TODO: for now, an empty value will be serialized as a zero element
  6929. // array. Revisit this when coding the handling of null/nil values.
  6930. if ($use == 'literal') {
  6931. $xml = "<$name$elementNS>"
  6932. .$contents
  6933. ."</$name>";
  6934. } else {
  6935. $xml = "<$name$elementNS xsi:type=\"".$this->getPrefixFromNamespace('http://schemas.xmlsoap.org/soap/encoding/').':Array" '.
  6936. $this->getPrefixFromNamespace('http://schemas.xmlsoap.org/soap/encoding/')
  6937. .':arrayType="'
  6938. .$this->getPrefixFromNamespace($this->getPrefix($typeDef['arrayType']))
  6939. .":".$this->getLocalPart($typeDef['arrayType'])."[$rows$cols]\">"
  6940. .$contents
  6941. ."</$name>";
  6942. }
  6943. } elseif ($phpType == 'scalar') {
  6944. if (isset($typeDef['form']) && ($typeDef['form'] == 'qualified')) {
  6945. $elementNS = " xmlns=\"$ns\"";
  6946. } else {
  6947. if ($unqualified) {
  6948. $elementNS = " xmlns=\"\"";
  6949. } else {
  6950. $elementNS = '';
  6951. }
  6952. }
  6953. if ($use == 'literal') {
  6954. if ($forceType) {
  6955. $xml = "<$name$elementNS xsi:type=\"" . $this->getPrefixFromNamespace($ns) . ":$uqType\">$value</$name>";
  6956. } else {
  6957. $xml = "<$name$elementNS>$value</$name>";
  6958. }
  6959. } else {
  6960. $xml = "<$name$elementNS xsi:type=\"" . $this->getPrefixFromNamespace($ns) . ":$uqType\"$encodingStyle>$value</$name>";
  6961. }
  6962. }
  6963. $this->debug("in serializeType: returning: $xml");
  6964. return $xml;
  6965. }
  6966. /**
  6967. * serializes the attributes for a complexType
  6968. *
  6969. * @param array $typeDef our internal representation of an XML schema type (or element)
  6970. * @param mixed $value a native PHP value (parameter value)
  6971. * @param string $ns the namespace of the type
  6972. * @param string $uqType the local part of the type
  6973. * @return string value serialized as an XML string
  6974. * @access private
  6975. */
  6976. function serializeComplexTypeAttributes($typeDef, $value, $ns, $uqType) {
  6977. $this->debug("serializeComplexTypeAttributes for XML Schema type $ns:$uqType");
  6978. $xml = '';
  6979. if (isset($typeDef['extensionBase'])) {
  6980. $nsx = $this->getPrefix($typeDef['extensionBase']);
  6981. $uqTypex = $this->getLocalPart($typeDef['extensionBase']);
  6982. if ($this->getNamespaceFromPrefix($nsx)) {
  6983. $nsx = $this->getNamespaceFromPrefix($nsx);
  6984. }
  6985. if ($typeDefx = $this->getTypeDef($uqTypex, $nsx)) {
  6986. $this->debug("serialize attributes for extension base $nsx:$uqTypex");
  6987. $xml .= $this->serializeComplexTypeAttributes($typeDefx, $value, $nsx, $uqTypex);
  6988. } else {
  6989. $this->debug("extension base $nsx:$uqTypex is not a supported type");
  6990. }
  6991. }
  6992. if (isset($typeDef['attrs']) && is_array($typeDef['attrs'])) {
  6993. $this->debug("serialize attributes for XML Schema type $ns:$uqType");
  6994. if (is_array($value)) {
  6995. $xvalue = $value;
  6996. } elseif (is_object($value)) {
  6997. $xvalue = get_object_vars($value);
  6998. } else {
  6999. $this->debug("value is neither an array nor an object for XML Schema type $ns:$uqType");
  7000. $xvalue = array();
  7001. }
  7002. foreach ($typeDef['attrs'] as $aName => $attrs) {
  7003. if (isset($xvalue['!' . $aName])) {
  7004. $xname = '!' . $aName;
  7005. $this->debug("value provided for attribute $aName with key $xname");
  7006. } elseif (isset($xvalue[$aName])) {
  7007. $xname = $aName;
  7008. $this->debug("value provided for attribute $aName with key $xname");
  7009. } elseif (isset($attrs['default'])) {
  7010. $xname = '!' . $aName;
  7011. $xvalue[$xname] = $attrs['default'];
  7012. $this->debug('use default value of ' . $xvalue[$aName] . ' for attribute ' . $aName);
  7013. } else {
  7014. $xname = '';
  7015. $this->debug("no value provided for attribute $aName");
  7016. }
  7017. if ($xname) {
  7018. $xml .= " $aName=\"" . $this->expandEntities($xvalue[$xname]) . "\"";
  7019. }
  7020. }
  7021. } else {
  7022. $this->debug("no attributes to serialize for XML Schema type $ns:$uqType");
  7023. }
  7024. return $xml;
  7025. }
  7026. /**
  7027. * serializes the elements for a complexType
  7028. *
  7029. * @param array $typeDef our internal representation of an XML schema type (or element)
  7030. * @param mixed $value a native PHP value (parameter value)
  7031. * @param string $ns the namespace of the type
  7032. * @param string $uqType the local part of the type
  7033. * @param string $use use for part (encoded|literal)
  7034. * @param string $encodingStyle SOAP encoding style for the value (if different than the enclosing style)
  7035. * @return string value serialized as an XML string
  7036. * @access private
  7037. */
  7038. function serializeComplexTypeElements($typeDef, $value, $ns, $uqType, $use='encoded', $encodingStyle=false) {
  7039. $this->debug("in serializeComplexTypeElements for XML Schema type $ns:$uqType");
  7040. $xml = '';
  7041. if (isset($typeDef['extensionBase'])) {
  7042. $nsx = $this->getPrefix($typeDef['extensionBase']);
  7043. $uqTypex = $this->getLocalPart($typeDef['extensionBase']);
  7044. if ($this->getNamespaceFromPrefix($nsx)) {
  7045. $nsx = $this->getNamespaceFromPrefix($nsx);
  7046. }
  7047. if ($typeDefx = $this->getTypeDef($uqTypex, $nsx)) {
  7048. $this->debug("serialize elements for extension base $nsx:$uqTypex");
  7049. $xml .= $this->serializeComplexTypeElements($typeDefx, $value, $nsx, $uqTypex, $use, $encodingStyle);
  7050. } else {
  7051. $this->debug("extension base $nsx:$uqTypex is not a supported type");
  7052. }
  7053. }
  7054. if (isset($typeDef['elements']) && is_array($typeDef['elements'])) {
  7055. $this->debug("in serializeComplexTypeElements, serialize elements for XML Schema type $ns:$uqType");
  7056. if (is_array($value)) {
  7057. $xvalue = $value;
  7058. } elseif (is_object($value)) {
  7059. $xvalue = get_object_vars($value);
  7060. } else {
  7061. $this->debug("value is neither an array nor an object for XML Schema type $ns:$uqType");
  7062. $xvalue = array();
  7063. }
  7064. // toggle whether all elements are present - ideally should validate against schema
  7065. if (count($typeDef['elements']) != count($xvalue)){
  7066. $optionals = true;
  7067. }
  7068. foreach ($typeDef['elements'] as $eName => $attrs) {
  7069. if (!isset($xvalue[$eName])) {
  7070. if (isset($attrs['default'])) {
  7071. $xvalue[$eName] = $attrs['default'];
  7072. $this->debug('use default value of ' . $xvalue[$eName] . ' for element ' . $eName);
  7073. }
  7074. }
  7075. // if user took advantage of a minOccurs=0, then only serialize named parameters
  7076. if (isset($optionals)
  7077. && (!isset($xvalue[$eName]))
  7078. && ( (!isset($attrs['nillable'])) || $attrs['nillable'] != 'true')
  7079. ){
  7080. if (isset($attrs['minOccurs']) && $attrs['minOccurs'] <> '0') {
  7081. $this->debug("apparent error: no value provided for element $eName with minOccurs=" . $attrs['minOccurs']);
  7082. }
  7083. // do nothing
  7084. $this->debug("no value provided for complexType element $eName and element is not nillable, so serialize nothing");
  7085. } else {
  7086. // get value
  7087. if (isset($xvalue[$eName])) {
  7088. $v = $xvalue[$eName];
  7089. } else {
  7090. $v = null;
  7091. }
  7092. if (isset($attrs['form'])) {
  7093. $unqualified = ($attrs['form'] == 'unqualified');
  7094. } else {
  7095. $unqualified = false;
  7096. }
  7097. if (isset($attrs['maxOccurs']) && ($attrs['maxOccurs'] == 'unbounded' || $attrs['maxOccurs'] > 1) && isset($v) && is_array($v) && $this->isArraySimpleOrStruct($v) == 'arraySimple') {
  7098. $vv = $v;
  7099. foreach ($vv as $k => $v) {
  7100. if (isset($attrs['type']) || isset($attrs['ref'])) {
  7101. // serialize schema-defined type
  7102. $xml .= $this->serializeType($eName, isset($attrs['type']) ? $attrs['type'] : $attrs['ref'], $v, $use, $encodingStyle, $unqualified);
  7103. } else {
  7104. // serialize generic type (can this ever really happen?)
  7105. $this->debug("calling serialize_val() for $v, $eName, false, false, false, false, $use");
  7106. $xml .= $this->serialize_val($v, $eName, false, false, false, false, $use);
  7107. }
  7108. }
  7109. } else {
  7110. if (is_null($v) && isset($attrs['minOccurs']) && $attrs['minOccurs'] == '0') {
  7111. // do nothing
  7112. } elseif (is_null($v) && isset($attrs['nillable']) && $attrs['nillable'] == 'true') {
  7113. // TODO: serialize a nil correctly, but for now serialize schema-defined type
  7114. $xml .= $this->serializeType($eName, isset($attrs['type']) ? $attrs['type'] : $attrs['ref'], $v, $use, $encodingStyle, $unqualified);
  7115. } elseif (isset($attrs['type']) || isset($attrs['ref'])) {
  7116. // serialize schema-defined type
  7117. $xml .= $this->serializeType($eName, isset($attrs['type']) ? $attrs['type'] : $attrs['ref'], $v, $use, $encodingStyle, $unqualified);
  7118. } else {
  7119. // serialize generic type (can this ever really happen?)
  7120. $this->debug("calling serialize_val() for $v, $eName, false, false, false, false, $use");
  7121. $xml .= $this->serialize_val($v, $eName, false, false, false, false, $use);
  7122. }
  7123. }
  7124. }
  7125. }
  7126. } else {
  7127. $this->debug("no elements to serialize for XML Schema type $ns:$uqType");
  7128. }
  7129. return $xml;
  7130. }
  7131. /**
  7132. * adds an XML Schema complex type to the WSDL types
  7133. *
  7134. * @param string $name
  7135. * @param string $typeClass (complexType|simpleType|attribute)
  7136. * @param string $phpType currently supported are array and struct (php assoc array)
  7137. * @param string $compositor (all|sequence|choice)
  7138. * @param string $restrictionBase namespace:name (http://schemas.xmlsoap.org/soap/encoding/:Array)
  7139. * @param array $elements e.g. array ( name => array(name=>'',type=>'') )
  7140. * @param array $attrs e.g. array(array('ref'=>'SOAP-ENC:arrayType','wsdl:arrayType'=>'xsd:string[]'))
  7141. * @param string $arrayType as namespace:name (xsd:string)
  7142. * @see nusoap_xmlschema
  7143. * @access public
  7144. */
  7145. function addComplexType($name,$typeClass='complexType',$phpType='array',$compositor='',$restrictionBase='',$elements=array(),$attrs=array(),$arrayType='') {
  7146. if (count($elements) > 0) {
  7147. $eElements = array();
  7148. foreach($elements as $n => $e){
  7149. // expand each element
  7150. $ee = array();
  7151. foreach ($e as $k => $v) {
  7152. $k = strpos($k,':') ? $this->expandQname($k) : $k;
  7153. $v = strpos($v,':') ? $this->expandQname($v) : $v;
  7154. $ee[$k] = $v;
  7155. }
  7156. $eElements[$n] = $ee;
  7157. }
  7158. $elements = $eElements;
  7159. }
  7160. if (count($attrs) > 0) {
  7161. foreach($attrs as $n => $a){
  7162. // expand each attribute
  7163. foreach ($a as $k => $v) {
  7164. $k = strpos($k,':') ? $this->expandQname($k) : $k;
  7165. $v = strpos($v,':') ? $this->expandQname($v) : $v;
  7166. $aa[$k] = $v;
  7167. }
  7168. $eAttrs[$n] = $aa;
  7169. }
  7170. $attrs = $eAttrs;
  7171. }
  7172. $restrictionBase = strpos($restrictionBase,':') ? $this->expandQname($restrictionBase) : $restrictionBase;
  7173. $arrayType = strpos($arrayType,':') ? $this->expandQname($arrayType) : $arrayType;
  7174. $typens = isset($this->namespaces['types']) ? $this->namespaces['types'] : $this->namespaces['tns'];
  7175. $this->schemas[$typens][0]->addComplexType($name,$typeClass,$phpType,$compositor,$restrictionBase,$elements,$attrs,$arrayType);
  7176. }
  7177. /**
  7178. * adds an XML Schema simple type to the WSDL types
  7179. *
  7180. * @param string $name
  7181. * @param string $restrictionBase namespace:name (http://schemas.xmlsoap.org/soap/encoding/:Array)
  7182. * @param string $typeClass (should always be simpleType)
  7183. * @param string $phpType (should always be scalar)
  7184. * @param array $enumeration array of values
  7185. * @see nusoap_xmlschema
  7186. * @access public
  7187. */
  7188. function addSimpleType($name, $restrictionBase='', $typeClass='simpleType', $phpType='scalar', $enumeration=array()) {
  7189. $restrictionBase = strpos($restrictionBase,':') ? $this->expandQname($restrictionBase) : $restrictionBase;
  7190. $typens = isset($this->namespaces['types']) ? $this->namespaces['types'] : $this->namespaces['tns'];
  7191. $this->schemas[$typens][0]->addSimpleType($name, $restrictionBase, $typeClass, $phpType, $enumeration);
  7192. }
  7193. /**
  7194. * adds an element to the WSDL types
  7195. *
  7196. * @param array $attrs attributes that must include name and type
  7197. * @see nusoap_xmlschema
  7198. * @access public
  7199. */
  7200. function addElement($attrs) {
  7201. $typens = isset($this->namespaces['types']) ? $this->namespaces['types'] : $this->namespaces['tns'];
  7202. $this->schemas[$typens][0]->addElement($attrs);
  7203. }
  7204. /**
  7205. * register an operation with the server
  7206. *
  7207. * @param string $name operation (method) name
  7208. * @param array $in assoc array of input values: key = param name, value = param type
  7209. * @param array $out assoc array of output values: key = param name, value = param type
  7210. * @param string $namespace optional The namespace for the operation
  7211. * @param string $soapaction optional The soapaction for the operation
  7212. * @param string $style (rpc|document) optional The style for the operation Note: when 'document' is specified, parameter and return wrappers are created for you automatically
  7213. * @param string $use (encoded|literal) optional The use for the parameters (cannot mix right now)
  7214. * @param string $documentation optional The description to include in the WSDL
  7215. * @param string $encodingStyle optional (usually 'http://schemas.xmlsoap.org/soap/encoding/' for encoded)
  7216. * @access public
  7217. */
  7218. function addOperation($name, $in = false, $out = false, $namespace = false, $soapaction = false, $style = 'rpc', $use = 'encoded', $documentation = '', $encodingStyle = ''){
  7219. if ($use == 'encoded' && $encodingStyle == '') {
  7220. $encodingStyle = 'http://schemas.xmlsoap.org/soap/encoding/';
  7221. }
  7222. if ($style == 'document') {
  7223. $elements = array();
  7224. foreach ($in as $n => $t) {
  7225. $elements[$n] = array('name' => $n, 'type' => $t, 'form' => 'unqualified');
  7226. }
  7227. $this->addComplexType($name . 'RequestType', 'complexType', 'struct', 'all', '', $elements);
  7228. $this->addElement(array('name' => $name, 'type' => $name . 'RequestType'));
  7229. $in = array('parameters' => 'tns:' . $name . '^');
  7230. $elements = array();
  7231. foreach ($out as $n => $t) {
  7232. $elements[$n] = array('name' => $n, 'type' => $t, 'form' => 'unqualified');
  7233. }
  7234. $this->addComplexType($name . 'ResponseType', 'complexType', 'struct', 'all', '', $elements);
  7235. $this->addElement(array('name' => $name . 'Response', 'type' => $name . 'ResponseType', 'form' => 'qualified'));
  7236. $out = array('parameters' => 'tns:' . $name . 'Response' . '^');
  7237. }
  7238. // get binding
  7239. $this->bindings[ $this->serviceName . 'Binding' ]['operations'][$name] =
  7240. array(
  7241. 'name' => $name,
  7242. 'binding' => $this->serviceName . 'Binding',
  7243. 'endpoint' => $this->endpoint,
  7244. 'soapAction' => $soapaction,
  7245. 'style' => $style,
  7246. 'input' => array(
  7247. 'use' => $use,
  7248. 'namespace' => $namespace,
  7249. 'encodingStyle' => $encodingStyle,
  7250. 'message' => $name . 'Request',
  7251. 'parts' => $in),
  7252. 'output' => array(
  7253. 'use' => $use,
  7254. 'namespace' => $namespace,
  7255. 'encodingStyle' => $encodingStyle,
  7256. 'message' => $name . 'Response',
  7257. 'parts' => $out),
  7258. 'namespace' => $namespace,
  7259. 'transport' => 'http://schemas.xmlsoap.org/soap/http',
  7260. 'documentation' => $documentation);
  7261. // add portTypes
  7262. // add messages
  7263. if($in)
  7264. {
  7265. foreach($in as $pName => $pType)
  7266. {
  7267. if(strpos($pType,':')) {
  7268. $pType = $this->getNamespaceFromPrefix($this->getPrefix($pType)).":".$this->getLocalPart($pType);
  7269. }
  7270. $this->messages[$name.'Request'][$pName] = $pType;
  7271. }
  7272. } else {
  7273. $this->messages[$name.'Request']= '0';
  7274. }
  7275. if($out)
  7276. {
  7277. foreach($out as $pName => $pType)
  7278. {
  7279. if(strpos($pType,':')) {
  7280. $pType = $this->getNamespaceFromPrefix($this->getPrefix($pType)).":".$this->getLocalPart($pType);
  7281. }
  7282. $this->messages[$name.'Response'][$pName] = $pType;
  7283. }
  7284. } else {
  7285. $this->messages[$name.'Response']= '0';
  7286. }
  7287. return true;
  7288. }
  7289. }
  7290. ?><?php
  7291. /*
  7292. Modification information for LGPL compliance
  7293. r58622 - 2010-10-22 18:18:59 -0700 (Fri, 22 Oct 2010) - engsvnbuild - Author: lam <lam@198.18.142.201>
  7294. bug 40066
  7295. r58361 - 2010-09-29 16:59:02 -0700 (Wed, 29 Sep 2010) - kjing - Author: Jenny Gonsalves <jenny@sugarcrm.com>
  7296. Merging with maint_6_0_1 (svn merge -r 58250:58342)
  7297. r57813 - 2010-08-19 10:34:44 -0700 (Thu, 19 Aug 2010) - kjing - Author: John Mertic <jmertic@sugarcrm.com>
  7298. Bug 39085 - When loading the opposite search panel via ajax on the ListViews, call the index action instead of the ListView action to avoid touching pre-MVC code by accident.
  7299. r57707 - 2010-08-10 12:26:13 -0700 (Tue, 10 Aug 2010) - kjing - Author: Stanislav Malyshev <smalyshev@gmail.com>
  7300. fix SOAP calls with no parameters
  7301. r56990 - 2010-06-16 13:05:36 -0700 (Wed, 16 Jun 2010) - kjing - snapshot "Mango" svn branch to a new one for GitHub sync
  7302. r56989 - 2010-06-16 13:01:33 -0700 (Wed, 16 Jun 2010) - kjing - defunt "Mango" svn dev branch before github cutover
  7303. r55980 - 2010-04-19 13:31:28 -0700 (Mon, 19 Apr 2010) - kjing - create Mango (6.1) based on windex
  7304. r51719 - 2009-10-22 10:18:00 -0700 (Thu, 22 Oct 2009) - mitani - Converted to Build 3 tags and updated the build system
  7305. r51634 - 2009-10-19 13:32:22 -0700 (Mon, 19 Oct 2009) - mitani - Windex is the branch for Sugar Sales 1.0 development
  7306. r51508 - 2009-10-14 07:40:23 -0700 (Wed, 14 Oct 2009) - jmertic - More fallout fixes from the PHP 5.3 ereg to preg changes.
  7307. r51455 - 2009-10-13 07:56:48 -0700 (Tue, 13 Oct 2009) - jmertic - Bug 33202 - Enable install of SugarCRM on PHP 5.3.0, asserting that the minimum supported version is PHP 5.2.x.
  7308. r51443 - 2009-10-12 13:34:36 -0700 (Mon, 12 Oct 2009) - jmertic - Bug 33332 - Made application PHP 5.3 compliant with E_DEPRECATED warnings on by:
  7309. - Changing all ereg function to either preg or simple string based ones
  7310. - No more references to magic quotes.
  7311. - Change all the session_unregister() functions to just unset() the correct session variable instead.
  7312. r50375 - 2009-08-24 18:07:43 -0700 (Mon, 24 Aug 2009) - dwong - branch kobe2 from tokyo r50372
  7313. r45763 - 2009-04-01 12:16:18 -0700 (Wed, 01 Apr 2009) - majed - Removed half of the require_once and include_onces in the product that were redundant or could be handled easily by the auto loader
  7314. r45680 - 2009-03-30 14:34:35 -0700 (Mon, 30 Mar 2009) - Samir Gandhi - modifeid serializeSchema to generate WS-I compliant WSDL
  7315. r42807 - 2008-12-29 11:16:59 -0800 (Mon, 29 Dec 2008) - dwong - Branch from trunk/sugarcrm r42806 to branches/tokyo/sugarcrm
  7316. r42645 - 2008-12-18 13:41:08 -0800 (Thu, 18 Dec 2008) - awu - merging maint_5_2_0 rev41336:HEAD to trunk
  7317. r41647 - 2008-11-11 17:44:30 -0800 (Tue, 11 Nov 2008) - majed - Fixes a few bugs
  7318. r41596 - 2008-11-10 19:20:04 -0800 (Mon, 10 Nov 2008) - Samir Gandhi - modified to set $method in the code
  7319. r41558 - 2008-11-10 14:35:34 -0800 (Mon, 10 Nov 2008) - majed - changes nusoap to allow for registering classes
  7320. r39619 - 2008-09-09 13:41:34 -0700 (Tue, 09 Sep 2008) - jmertic - Bug 24827 - Remove all instances where we return a new object and assign it by reference, since this is deprecated in PHP 5 and emits E_DEPRECATED errors in PHP 5.3.
  7321. Touched:
  7322. - data/SugarBean.php
  7323. - include/domit/php_http_client_generic.php
  7324. - include/domit/php_http_connector.php
  7325. - include/domit/testing_domit.php
  7326. - include/domit/xml_domit_getelementsbypath.php
  7327. - include/domit/xml_domit_lite_parser.php
  7328. - include/domit/xml_domit_nodemaps.php
  7329. - include/domit/xml_domit_parser.php
  7330. - include/domit/xml_domit_shared.php
  7331. - include/generic/SugarWidgets/SugarWidgetField.php
  7332. - include/generic/SugarWidgets/SugarWidgetReportField.php
  7333. - include/ListView/ProcessView.php
  7334. - include/nusoap/class.soapclient.php
  7335. - include/nusoap/nusoap.php
  7336. - include/nusoap/nusoapmime.php
  7337. - include/Pear/HTML_Safe/Safe.php
  7338. - include/Pear/XML_HTMLSax3/HTMLSax3.php
  7339. - modules/Administration/RebuildWorkFlow.php
  7340. - modules/Expressions/RelateSelector.php
  7341. - modules/Reports/templates/templates_reports.php
  7342. - modules/WorkFlow/Delete.php
  7343. - modules/WorkFlow/Save.php
  7344. - modules/WorkFlow/SaveSequence.php
  7345. - modules/WorkFlow/WorkFlow.php
  7346. - modules/WorkFlowActionShells/CreateStep1.php
  7347. - modules/WorkFlowActionShells/CreateStep2.php
  7348. - modules/WorkFlowActionShells/Save.php
  7349. - modules/WorkFlowActionShells/WorkFlowActionShell.php
  7350. - modules/WorkFlowAlerts/Save.php
  7351. - modules/WorkFlowAlerts/WorkFlowAlert.php
  7352. - modules/WorkFlowAlertShells/DetailView.php
  7353. - modules/WorkFlowAlertShells/WorkFlowAlertShell.php
  7354. - modules/WorkFlowTriggerShells/CreateStep1.php
  7355. - modules/WorkFlowTriggerShells/CreateStepFilter.php
  7356. - modules/WorkFlowTriggerShells/SaveFilter.php
  7357. - modules/WorkFlowTriggerShells/WorkFlowTriggerShell.php
  7358. - soap/SoapHelperFunctions.php
  7359. - test/modules/DynamicFields/DynamicFields_Bug24095_test.php
  7360. - test/simpletest/browser.php
  7361. - test/simpletest/default_reporter.php
  7362. - test/simpletest/detached.php
  7363. - test/simpletest/eclipse.php
  7364. - test/simpletest/expectation.php
  7365. - test/simpletest/extensions/pear_test_case.php
  7366. - test/simpletest/form.php
  7367. - test/simpletest/http.php
  7368. - test/simpletest/mock_objects.php
  7369. - test/simpletest/page.php
  7370. - test/simpletest/parser.php
  7371. - test/simpletest/remote.php
  7372. - test/simpletest/shell_tester.php
  7373. - test/simpletest/simple_test.php
  7374. - test/simpletest/simpletest.php
  7375. - test/simpletest/test/acceptance_test.php
  7376. - test/simpletest/test/adapter_test.php
  7377. - test/simpletest/test/authentication_test.php
  7378. - test/simpletest/test/browser_test.php
  7379. - test/simpletest/test/collector_test.php
  7380. - test/simpletest/test/compatibility_test.php
  7381. - test/simpletest/test/detached_test.php
  7382. - test/simpletest/test/eclipse_test.php
  7383. - test/simpletest/test/encoding_test.php
  7384. - test/simpletest/test/errors_test.php
  7385. - test/simpletest/test/expectation_test.php
  7386. - test/simpletest/test/form_test.php
  7387. - test/simpletest/test/frames_test.php
  7388. - test/simpletest/test/http_test.php
  7389. - test/simpletest/test/live_test.php
  7390. - test/simpletest/test/mock_objects_test.php
  7391. - test/simpletest/test/page_test.php
  7392. - test/simpletest/test/parse_error_test.php
  7393. - test/simpletest/test/parser_test.php
  7394. - test/simpletest/test/remote_test.php
  7395. - test/simpletest/test/shell_test.php
  7396. - test/simpletest/test/shell_tester_test.php
  7397. - test/simpletest/test/simpletest_test.php
  7398. - test/simpletest/test/site/page_request.php
  7399. - test/simpletest/test/tag_test.php
  7400. - test/simpletest/test/unit_tester_test.php
  7401. - test/simpletest/test/user_agent_test.php
  7402. - test/simpletest/test/visual_test.php
  7403. - test/simpletest/test/xml_test.php
  7404. - test/simpletest/test_case.php
  7405. - test/simpletest/ui/array_reporter/test.php
  7406. - test/simpletest/ui/recorder/test.php
  7407. - test/simpletest/unit_tester.php
  7408. - test/simpletest/url.php
  7409. - test/simpletest/user_agent.php
  7410. - test/simpletest/web_tester.php
  7411. - test/spikephpcoverage/src/PEAR.php
  7412. - test/spikephpcoverage/src/util/Utility.php
  7413. - test/spikephpcoverage/src/XML/Parser.php
  7414. - test/spikephpcoverage/src/XML/Parser/Simple.php
  7415. - test/test_utilities/SugarTest_SimpleBrowser.php
  7416. r38362 - 2008-07-28 14:06:59 -0700 (Mon, 28 Jul 2008) - roger - bug: 23897. Using print_r when using the debug statement in nusoap will print out the statements to the screen if the call is coming from the UI.
  7417. r38300 - 2008-07-25 13:33:43 -0700 (Fri, 25 Jul 2008) - Samir Gandhi - put the debug in parseresponse function
  7418. r38293 - 2008-07-25 12:32:34 -0700 (Fri, 25 Jul 2008) - Samir Gandhi - to put all the debug statements return value in the call function
  7419. r36824 - 2008-06-18 09:26:11 -0700 (Wed, 18 Jun 2008) - roger - bug: 21832
  7420. r26422 - 2007-09-05 17:29:12 -0700 (Wed, 05 Sep 2007) - majed - migrate from beta 1 to trunk
  7421. r15787 - 2006-08-10 10:14:41 -0700 (Thu, 10 Aug 2006) - roger - RRS: bug 7961
  7422. r14701 - 2006-07-17 13:37:26 -0700 (Mon, 17 Jul 2006) - roger - RRS: bug 5801
  7423. r13782 - 2006-06-06 10:58:55 -0700 (Tue, 06 Jun 2006) - majed - changes entry point code
  7424. r11466 - 2006-02-01 15:49:47 -0800 (Wed, 01 Feb 2006) - jacob - Adding extra !empty check to get around a PHP warning.
  7425. r11115 - 2006-01-17 14:54:45 -0800 (Tue, 17 Jan 2006) - majed - add entry point validation
  7426. r10585 - 2005-12-13 14:42:26 -0800 (Tue, 13 Dec 2005) - majed - adds new license mechanisim
  7427. r10170 - 2005-12-05 18:37:46 -0800 (Mon, 05 Dec 2005) - majed - fixes various issues
  7428. r8999 - 2005-11-04 05:26:49 -0800 (Fri, 04 Nov 2005) - roger - When nusoap was upgraded we had an issue with the user's default language not being populated during a soap request. I determined the reason this was happening and have checked in the corresponding change to nusoap.
  7429. r8991 - 2005-11-03 19:07:25 -0800 (Thu, 03 Nov 2005) - majed - fixes nusoap issue
  7430. r8846 - 2005-10-31 11:01:12 -0800 (Mon, 31 Oct 2005) - majed - new version of nusoap
  7431. r7905 - 2005-09-21 19:12:57 -0700 (Wed, 21 Sep 2005) - majed - restores old nusoap pre & with a few fixes
  7432. r7861 - 2005-09-20 15:40:25 -0700 (Tue, 20 Sep 2005) - majed - & fix for 3.5.1
  7433. r7452 - 2005-08-17 11:32:34 -0700 (Wed, 17 Aug 2005) - majed - changes soap to nusoap
  7434. r5820 - 2005-06-21 14:22:24 -0700 (Tue, 21 Jun 2005) - majed - fixes issues with nusoap and with custom fields
  7435. r5462 - 2005-05-25 13:50:11 -0700 (Wed, 25 May 2005) - majed - upgraded nusoap to .6.9
  7436. r5104 - 2005-05-04 15:33:41 -0700 (Wed, 04 May 2005) - majed - gets rid of HTTP_GET_VARS and what not which has been deprecated
  7437. r573 - 2004-09-04 13:03:32 -0700 (Sat, 04 Sep 2004) - sugarclint - undoing copyrights added in inadvertantly. --clint
  7438. r546 - 2004-09-03 11:49:38 -0700 (Fri, 03 Sep 2004) - sugarmsi - removed echo count
  7439. r354 - 2004-08-02 23:00:37 -0700 (Mon, 02 Aug 2004) - sugarjacob - Adding Soap
  7440. */
  7441. /**
  7442. *
  7443. * nusoap_parser class parses SOAP XML messages into native PHP values
  7444. *
  7445. * @author Dietrich Ayala <dietrich@ganx4.com>
  7446. * @author Scott Nichol <snichol@users.sourceforge.net>
  7447. * @access public
  7448. */
  7449. class nusoap_parser extends nusoap_base {
  7450. var $xml = '';
  7451. var $xml_encoding = '';
  7452. var $method = '';
  7453. var $root_struct = '';
  7454. var $root_struct_name = '';
  7455. var $root_struct_namespace = '';
  7456. var $root_header = '';
  7457. var $document = ''; // incoming SOAP body (text)
  7458. // determines where in the message we are (envelope,header,body,method)
  7459. var $status = '';
  7460. var $position = 0;
  7461. var $depth = 0;
  7462. var $default_namespace = '';
  7463. var $namespaces = array();
  7464. var $message = array();
  7465. var $parent = '';
  7466. var $fault = false;
  7467. var $fault_code = '';
  7468. var $fault_str = '';
  7469. var $fault_detail = '';
  7470. var $depth_array = array();
  7471. var $debug_flag = true;
  7472. var $soapresponse = NULL; // parsed SOAP Body
  7473. var $soapheader = NULL; // parsed SOAP Header
  7474. var $responseHeaders = ''; // incoming SOAP headers (text)
  7475. var $body_position = 0;
  7476. // for multiref parsing:
  7477. // array of id => pos
  7478. var $ids = array();
  7479. // array of id => hrefs => pos
  7480. var $multirefs = array();
  7481. // toggle for auto-decoding element content
  7482. var $decode_utf8 = false;
  7483. /**
  7484. * constructor that actually does the parsing
  7485. *
  7486. * @param string $xml SOAP message
  7487. * @param string $encoding character encoding scheme of message
  7488. * @param string $method method for which XML is parsed (unused?)
  7489. * @param string $decode_utf8 whether to decode UTF-8 to ISO-8859-1
  7490. * @access public
  7491. */
  7492. function nusoap_parser($xml,$encoding='UTF-8',$method='',$decode_utf8=true){
  7493. parent::nusoap_base();
  7494. $this->xml = $xml;
  7495. $this->xml_encoding = $encoding;
  7496. $this->method = $method;
  7497. $this->decode_utf8 = $decode_utf8;
  7498. // Check whether content has been read.
  7499. if(!empty($xml)){
  7500. // Check XML encoding
  7501. $pos_xml = strpos($xml, '<?xml');
  7502. if ($pos_xml !== FALSE) {
  7503. $xml_decl = substr($xml, $pos_xml, strpos($xml, '?>', $pos_xml + 2) - $pos_xml + 1);
  7504. if (preg_match("/encoding=[\"']([^\"']*)[\"']/", $xml_decl, $res)) {
  7505. $xml_encoding = $res[1];
  7506. if (strtoupper($xml_encoding) != $encoding) {
  7507. $err = "Charset from HTTP Content-Type '" . $encoding . "' does not match encoding from XML declaration '" . $xml_encoding . "'";
  7508. $this->debug($err);
  7509. if ($encoding != 'ISO-8859-1' || strtoupper($xml_encoding) != 'UTF-8') {
  7510. $this->setError($err);
  7511. return;
  7512. }
  7513. // when HTTP says ISO-8859-1 (the default) and XML says UTF-8 (the typical), assume the other endpoint is just sloppy and proceed
  7514. } else {
  7515. $this->debug('Charset from HTTP Content-Type matches encoding from XML declaration');
  7516. }
  7517. } else {
  7518. $this->debug('No encoding specified in XML declaration');
  7519. }
  7520. } else {
  7521. $this->debug('No XML declaration');
  7522. }
  7523. $this->debug('Entering nusoap_parser(), length='.strlen($xml).', encoding='.$encoding);
  7524. // Create an XML parser - why not xml_parser_create_ns?
  7525. $this->parser = xml_parser_create($this->xml_encoding);
  7526. // Set the options for parsing the XML data.
  7527. //xml_parser_set_option($parser, XML_OPTION_SKIP_WHITE, 1);
  7528. xml_parser_set_option($this->parser, XML_OPTION_CASE_FOLDING, 0);
  7529. xml_parser_set_option($this->parser, XML_OPTION_TARGET_ENCODING, $this->xml_encoding);
  7530. // Set the object for the parser.
  7531. xml_set_object($this->parser, $this);
  7532. // Set the element handlers for the parser.
  7533. xml_set_element_handler($this->parser, 'start_element','end_element');
  7534. xml_set_character_data_handler($this->parser,'character_data');
  7535. // Parse the XML file.
  7536. if(!xml_parse($this->parser,$xml,true)){
  7537. // Display an error message.
  7538. $err = sprintf('XML error parsing SOAP payload on line %d: %s',
  7539. xml_get_current_line_number($this->parser),
  7540. xml_error_string(xml_get_error_code($this->parser)));
  7541. $this->debug($err);
  7542. $this->debug("XML payload:\n" . $xml);
  7543. $this->setError($err);
  7544. } else {
  7545. $this->debug('in nusoap_parser ctor, message:');
  7546. $this->appendDebug($this->varDump($this->message));
  7547. $this->debug('parsed successfully, found root struct: '.$this->root_struct.' of name '.$this->root_struct_name);
  7548. // get final value
  7549. $this->soapresponse = $this->message[$this->root_struct]['result'];
  7550. // get header value
  7551. if($this->root_header != '' && isset($this->message[$this->root_header]['result'])){
  7552. $this->soapheader = $this->message[$this->root_header]['result'];
  7553. }
  7554. // resolve hrefs/ids
  7555. if(sizeof($this->multirefs) > 0){
  7556. foreach($this->multirefs as $id => $hrefs){
  7557. $this->debug('resolving multirefs for id: '.$id);
  7558. $idVal = $this->buildVal($this->ids[$id]);
  7559. if (is_array($idVal) && isset($idVal['!id'])) {
  7560. unset($idVal['!id']);
  7561. }
  7562. foreach($hrefs as $refPos => $ref){
  7563. $this->debug('resolving href at pos '.$refPos);
  7564. $this->multirefs[$id][$refPos] = $idVal;
  7565. }
  7566. }
  7567. }
  7568. }
  7569. xml_parser_free($this->parser);
  7570. } else {
  7571. $this->debug('xml was empty, didn\'t parse!');
  7572. $this->setError('xml was empty, didn\'t parse!');
  7573. }
  7574. }
  7575. /**
  7576. * start-element handler
  7577. *
  7578. * @param resource $parser XML parser object
  7579. * @param string $name element name
  7580. * @param array $attrs associative array of attributes
  7581. * @access private
  7582. */
  7583. function start_element($parser, $name, $attrs) {
  7584. // position in a total number of elements, starting from 0
  7585. // update class level pos
  7586. $pos = $this->position++;
  7587. // and set mine
  7588. $this->message[$pos] = array('pos' => $pos,'children'=>'','cdata'=>'');
  7589. // depth = how many levels removed from root?
  7590. // set mine as current global depth and increment global depth value
  7591. $this->message[$pos]['depth'] = $this->depth++;
  7592. // else add self as child to whoever the current parent is
  7593. if($pos != 0){
  7594. $this->message[$this->parent]['children'] .= '|'.$pos;
  7595. }
  7596. // set my parent
  7597. $this->message[$pos]['parent'] = $this->parent;
  7598. // set self as current parent
  7599. $this->parent = $pos;
  7600. // set self as current value for this depth
  7601. $this->depth_array[$this->depth] = $pos;
  7602. // get element prefix
  7603. if(strpos($name,':')){
  7604. // get ns prefix
  7605. $prefix = substr($name,0,strpos($name,':'));
  7606. // get unqualified name
  7607. $name = substr(strstr($name,':'),1);
  7608. }
  7609. // set status
  7610. if ($name == 'Envelope' && $this->status == '') {
  7611. $this->status = 'envelope';
  7612. } elseif ($name == 'Header' && $this->status == 'envelope') {
  7613. $this->root_header = $pos;
  7614. $this->status = 'header';
  7615. } elseif ($name == 'Body' && $this->status == 'envelope'){
  7616. $this->status = 'body';
  7617. $this->body_position = $pos;
  7618. // set method
  7619. } elseif($this->status == 'body' && $pos == ($this->body_position+1)) {
  7620. $this->status = 'method';
  7621. $this->root_struct_name = $name;
  7622. $this->root_struct = $pos;
  7623. $this->message[$pos]['type'] = 'struct';
  7624. $this->debug("found root struct $this->root_struct_name, pos $this->root_struct");
  7625. }
  7626. // set my status
  7627. $this->message[$pos]['status'] = $this->status;
  7628. // set name
  7629. $this->message[$pos]['name'] = htmlspecialchars($name);
  7630. // set attrs
  7631. $this->message[$pos]['attrs'] = $attrs;
  7632. // loop through atts, logging ns and type declarations
  7633. $attstr = '';
  7634. foreach($attrs as $key => $value){
  7635. $key_prefix = $this->getPrefix($key);
  7636. $key_localpart = $this->getLocalPart($key);
  7637. // if ns declarations, add to class level array of valid namespaces
  7638. if($key_prefix == 'xmlns'){
  7639. if(preg_match('/^http:\/\/www.w3.org\/[0-9]{4}\/XMLSchema$/',$value)){
  7640. $this->XMLSchemaVersion = $value;
  7641. $this->namespaces['xsd'] = $this->XMLSchemaVersion;
  7642. $this->namespaces['xsi'] = $this->XMLSchemaVersion.'-instance';
  7643. }
  7644. $this->namespaces[$key_localpart] = $value;
  7645. // set method namespace
  7646. if($name == $this->root_struct_name){
  7647. $this->methodNamespace = $value;
  7648. }
  7649. // if it's a type declaration, set type
  7650. } elseif($key_localpart == 'type'){
  7651. if (isset($this->message[$pos]['type']) && $this->message[$pos]['type'] == 'array') {
  7652. // do nothing: already processed arrayType
  7653. } else {
  7654. $value_prefix = $this->getPrefix($value);
  7655. $value_localpart = $this->getLocalPart($value);
  7656. $this->message[$pos]['type'] = $value_localpart;
  7657. $this->message[$pos]['typePrefix'] = $value_prefix;
  7658. if(isset($this->namespaces[$value_prefix])){
  7659. $this->message[$pos]['type_namespace'] = $this->namespaces[$value_prefix];
  7660. } else if(isset($attrs['xmlns:'.$value_prefix])) {
  7661. $this->message[$pos]['type_namespace'] = $attrs['xmlns:'.$value_prefix];
  7662. }
  7663. // should do something here with the namespace of specified type?
  7664. }
  7665. } elseif($key_localpart == 'arrayType'){
  7666. $this->message[$pos]['type'] = 'array';
  7667. /* do arrayType ereg here
  7668. [1] arrayTypeValue ::= atype asize
  7669. [2] atype ::= QName rank*
  7670. [3] rank ::= '[' (',')* ']'
  7671. [4] asize ::= '[' length~ ']'
  7672. [5] length ::= nextDimension* Digit+
  7673. [6] nextDimension ::= Digit+ ','
  7674. */
  7675. $expr = '/([A-Za-z0-9_]+):([A-Za-z]+[A-Za-z0-9_]+)\[([0-9]+),?([0-9]*)\]/';
  7676. if(preg_match($expr,$value,$regs)){
  7677. $this->message[$pos]['typePrefix'] = $regs[1];
  7678. $this->message[$pos]['arrayTypePrefix'] = $regs[1];
  7679. if (isset($this->namespaces[$regs[1]])) {
  7680. $this->message[$pos]['arrayTypeNamespace'] = $this->namespaces[$regs[1]];
  7681. } else if (isset($attrs['xmlns:'.$regs[1]])) {
  7682. $this->message[$pos]['arrayTypeNamespace'] = $attrs['xmlns:'.$regs[1]];
  7683. }
  7684. $this->message[$pos]['arrayType'] = $regs[2];
  7685. $this->message[$pos]['arraySize'] = $regs[3];
  7686. $this->message[$pos]['arrayCols'] = $regs[4];
  7687. }
  7688. // specifies nil value (or not)
  7689. } elseif ($key_localpart == 'nil'){
  7690. $this->message[$pos]['nil'] = ($value == 'true' || $value == '1');
  7691. // some other attribute
  7692. } elseif ($key != 'href' && $key != 'xmlns' && $key_localpart != 'encodingStyle' && $key_localpart != 'root') {
  7693. $this->message[$pos]['xattrs']['!' . $key] = $value;
  7694. }
  7695. if ($key == 'xmlns') {
  7696. $this->default_namespace = $value;
  7697. }
  7698. // log id
  7699. if($key == 'id'){
  7700. $this->ids[$value] = $pos;
  7701. }
  7702. // root
  7703. if($key_localpart == 'root' && $value == 1){
  7704. $this->status = 'method';
  7705. $this->root_struct_name = $name;
  7706. $this->root_struct = $pos;
  7707. $this->debug("found root struct $this->root_struct_name, pos $pos");
  7708. }
  7709. // for doclit
  7710. $attstr .= " $key=\"$value\"";
  7711. }
  7712. // get namespace - must be done after namespace atts are processed
  7713. if(isset($prefix)){
  7714. $this->message[$pos]['namespace'] = $this->namespaces[$prefix];
  7715. $this->default_namespace = $this->namespaces[$prefix];
  7716. } else {
  7717. $this->message[$pos]['namespace'] = $this->default_namespace;
  7718. }
  7719. if($this->status == 'header'){
  7720. if ($this->root_header != $pos) {
  7721. $this->responseHeaders .= "<" . (isset($prefix) ? $prefix . ':' : '') . "$name$attstr>";
  7722. }
  7723. } elseif($this->root_struct_name != ''){
  7724. $this->document .= "<" . (isset($prefix) ? $prefix . ':' : '') . "$name$attstr>";
  7725. }
  7726. }
  7727. /**
  7728. * end-element handler
  7729. *
  7730. * @param resource $parser XML parser object
  7731. * @param string $name element name
  7732. * @access private
  7733. */
  7734. function end_element($parser, $name) {
  7735. // position of current element is equal to the last value left in depth_array for my depth
  7736. $pos = $this->depth_array[$this->depth--];
  7737. // get element prefix
  7738. if(strpos($name,':')){
  7739. // get ns prefix
  7740. $prefix = substr($name,0,strpos($name,':'));
  7741. // get unqualified name
  7742. $name = substr(strstr($name,':'),1);
  7743. }
  7744. // build to native type
  7745. if(isset($this->body_position) && $pos > $this->body_position){
  7746. // deal w/ multirefs
  7747. if(isset($this->message[$pos]['attrs']['href'])){
  7748. // get id
  7749. $id = substr($this->message[$pos]['attrs']['href'],1);
  7750. // add placeholder to href array
  7751. $this->multirefs[$id][$pos] = 'placeholder';
  7752. // add set a reference to it as the result value
  7753. $this->message[$pos]['result'] =& $this->multirefs[$id][$pos];
  7754. // build complexType values
  7755. } elseif($this->message[$pos]['children'] != ''){
  7756. // if result has already been generated (struct/array)
  7757. if(!isset($this->message[$pos]['result'])){
  7758. $this->message[$pos]['result'] = $this->buildVal($pos);
  7759. }
  7760. // build complexType values of attributes and possibly simpleContent
  7761. } elseif (isset($this->message[$pos]['xattrs'])) {
  7762. if (isset($this->message[$pos]['nil']) && $this->message[$pos]['nil']) {
  7763. $this->message[$pos]['xattrs']['!'] = null;
  7764. } elseif (isset($this->message[$pos]['cdata']) && trim($this->message[$pos]['cdata']) != '') {
  7765. if (isset($this->message[$pos]['type'])) {
  7766. $this->message[$pos]['xattrs']['!'] = $this->decodeSimple($this->message[$pos]['cdata'], $this->message[$pos]['type'], isset($this->message[$pos]['type_namespace']) ? $this->message[$pos]['type_namespace'] : '');
  7767. } else {
  7768. $parent = $this->message[$pos]['parent'];
  7769. if (isset($this->message[$parent]['type']) && ($this->message[$parent]['type'] == 'array') && isset($this->message[$parent]['arrayType'])) {
  7770. $this->message[$pos]['xattrs']['!'] = $this->decodeSimple($this->message[$pos]['cdata'], $this->message[$parent]['arrayType'], isset($this->message[$parent]['arrayTypeNamespace']) ? $this->message[$parent]['arrayTypeNamespace'] : '');
  7771. } else {
  7772. $this->message[$pos]['xattrs']['!'] = $this->message[$pos]['cdata'];
  7773. }
  7774. }
  7775. }
  7776. $this->message[$pos]['result'] = $this->message[$pos]['xattrs'];
  7777. // set value of simpleType (or nil complexType)
  7778. } else {
  7779. //$this->debug('adding data for scalar value '.$this->message[$pos]['name'].' of value '.$this->message[$pos]['cdata']);
  7780. if (isset($this->message[$pos]['nil']) && $this->message[$pos]['nil']) {
  7781. $this->message[$pos]['xattrs']['!'] = null;
  7782. } elseif (isset($this->message[$pos]['type'])) {
  7783. $this->message[$pos]['result'] = $this->decodeSimple($this->message[$pos]['cdata'], $this->message[$pos]['type'], isset($this->message[$pos]['type_namespace']) ? $this->message[$pos]['type_namespace'] : '');
  7784. } else {
  7785. $parent = $this->message[$pos]['parent'];
  7786. if (isset($this->message[$parent]['type']) && ($this->message[$parent]['type'] == 'array') && isset($this->message[$parent]['arrayType'])) {
  7787. $this->message[$pos]['result'] = $this->decodeSimple($this->message[$pos]['cdata'], $this->message[$parent]['arrayType'], isset($this->message[$parent]['arrayTypeNamespace']) ? $this->message[$parent]['arrayTypeNamespace'] : '');
  7788. } else {
  7789. $this->message[$pos]['result'] = $this->message[$pos]['cdata'];
  7790. }
  7791. }
  7792. /* add value to parent's result, if parent is struct/array
  7793. $parent = $this->message[$pos]['parent'];
  7794. if($this->message[$parent]['type'] != 'map'){
  7795. if(strtolower($this->message[$parent]['type']) == 'array'){
  7796. $this->message[$parent]['result'][] = $this->message[$pos]['result'];
  7797. } else {
  7798. $this->message[$parent]['result'][$this->message[$pos]['name']] = $this->message[$pos]['result'];
  7799. }
  7800. }
  7801. */
  7802. }
  7803. }
  7804. // for doclit
  7805. if($this->status == 'header'){
  7806. if ($this->root_header != $pos) {
  7807. $this->responseHeaders .= "</" . (isset($prefix) ? $prefix . ':' : '') . "$name>";
  7808. }
  7809. } elseif($pos >= $this->root_struct){
  7810. $this->document .= "</" . (isset($prefix) ? $prefix . ':' : '') . "$name>";
  7811. }
  7812. // switch status
  7813. if ($pos == $this->root_struct){
  7814. $this->status = 'body';
  7815. $this->root_struct_namespace = $this->message[$pos]['namespace'];
  7816. } elseif ($pos == $this->root_header) {
  7817. $this->status = 'envelope';
  7818. } elseif ($name == 'Body' && $this->status == 'body') {
  7819. $this->status = 'envelope';
  7820. } elseif ($name == 'Header' && $this->status == 'header') { // will never happen
  7821. $this->status = 'envelope';
  7822. } elseif ($name == 'Envelope' && $this->status == 'envelope') {
  7823. $this->status = '';
  7824. }
  7825. // set parent back to my parent
  7826. $this->parent = $this->message[$pos]['parent'];
  7827. }
  7828. /**
  7829. * element content handler
  7830. *
  7831. * @param resource $parser XML parser object
  7832. * @param string $data element content
  7833. * @access private
  7834. */
  7835. function character_data($parser, $data){
  7836. $pos = $this->depth_array[$this->depth];
  7837. if ($this->xml_encoding=='UTF-8'){
  7838. // TODO: add an option to disable this for folks who want
  7839. // raw UTF-8 that, e.g., might not map to iso-8859-1
  7840. // TODO: this can also be handled with xml_parser_set_option($this->parser, XML_OPTION_TARGET_ENCODING, "ISO-8859-1");
  7841. if($this->decode_utf8){
  7842. $data = utf8_decode($data);
  7843. }
  7844. }
  7845. $this->message[$pos]['cdata'] .= $data;
  7846. // for doclit
  7847. if($this->status == 'header'){
  7848. $this->responseHeaders .= $data;
  7849. } else {
  7850. $this->document .= $data;
  7851. }
  7852. }
  7853. /**
  7854. * get the parsed message (SOAP Body)
  7855. *
  7856. * @return mixed
  7857. * @access public
  7858. * @deprecated use get_soapbody instead
  7859. */
  7860. function get_response(){
  7861. return $this->soapresponse;
  7862. }
  7863. /**
  7864. * get the parsed SOAP Body (NULL if there was none)
  7865. *
  7866. * @return mixed
  7867. * @access public
  7868. */
  7869. function get_soapbody(){
  7870. return $this->soapresponse;
  7871. }
  7872. /**
  7873. * get the parsed SOAP Header (NULL if there was none)
  7874. *
  7875. * @return mixed
  7876. * @access public
  7877. */
  7878. function get_soapheader(){
  7879. return $this->soapheader;
  7880. }
  7881. /**
  7882. * get the unparsed SOAP Header
  7883. *
  7884. * @return string XML or empty if no Header
  7885. * @access public
  7886. */
  7887. function getHeaders(){
  7888. return $this->responseHeaders;
  7889. }
  7890. /**
  7891. * decodes simple types into PHP variables
  7892. *
  7893. * @param string $value value to decode
  7894. * @param string $type XML type to decode
  7895. * @param string $typens XML type namespace to decode
  7896. * @return mixed PHP value
  7897. * @access private
  7898. */
  7899. function decodeSimple($value, $type, $typens) {
  7900. // TODO: use the namespace!
  7901. if ((!isset($type)) || $type == 'string' || $type == 'long' || $type == 'unsignedLong') {
  7902. return (string) $value;
  7903. }
  7904. if ($type == 'int' || $type == 'integer' || $type == 'short' || $type == 'byte') {
  7905. return (int) $value;
  7906. }
  7907. if ($type == 'float' || $type == 'double' || $type == 'decimal') {
  7908. return (double) $value;
  7909. }
  7910. if ($type == 'boolean') {
  7911. if (strtolower($value) == 'false' || strtolower($value) == 'f') {
  7912. return false;
  7913. }
  7914. return (boolean) $value;
  7915. }
  7916. if ($type == 'base64' || $type == 'base64Binary') {
  7917. $this->debug('Decode base64 value');
  7918. return base64_decode($value);
  7919. }
  7920. // obscure numeric types
  7921. if ($type == 'nonPositiveInteger' || $type == 'negativeInteger'
  7922. || $type == 'nonNegativeInteger' || $type == 'positiveInteger'
  7923. || $type == 'unsignedInt'
  7924. || $type == 'unsignedShort' || $type == 'unsignedByte') {
  7925. return (int) $value;
  7926. }
  7927. // bogus: parser treats array with no elements as a simple type
  7928. if ($type == 'array') {
  7929. return array();
  7930. }
  7931. // everything else
  7932. return (string) $value;
  7933. }
  7934. /**
  7935. * builds response structures for compound values (arrays/structs)
  7936. * and scalars
  7937. *
  7938. * @param integer $pos position in node tree
  7939. * @return mixed PHP value
  7940. * @access private
  7941. */
  7942. function buildVal($pos){
  7943. if(!isset($this->message[$pos]['type'])){
  7944. $this->message[$pos]['type'] = '';
  7945. }
  7946. $this->debug('in buildVal() for '.$this->message[$pos]['name']."(pos $pos) of type ".$this->message[$pos]['type']);
  7947. // if there are children...
  7948. if($this->message[$pos]['children'] != ''){
  7949. $this->debug('in buildVal, there are children');
  7950. $children = explode('|',$this->message[$pos]['children']);
  7951. array_shift($children); // knock off empty
  7952. // md array
  7953. if(isset($this->message[$pos]['arrayCols']) && $this->message[$pos]['arrayCols'] != ''){
  7954. $r=0; // rowcount
  7955. $c=0; // colcount
  7956. foreach($children as $child_pos){
  7957. $this->debug("in buildVal, got an MD array element: $r, $c");
  7958. $params[$r][] = $this->message[$child_pos]['result'];
  7959. $c++;
  7960. if($c == $this->message[$pos]['arrayCols']){
  7961. $c = 0;
  7962. $r++;
  7963. }
  7964. }
  7965. // array
  7966. } elseif($this->message[$pos]['type'] == 'array' || $this->message[$pos]['type'] == 'Array'){
  7967. $this->debug('in buildVal, adding array '.$this->message[$pos]['name']);
  7968. foreach($children as $child_pos){
  7969. $params[] = &$this->message[$child_pos]['result'];
  7970. }
  7971. // apache Map type: java hashtable
  7972. } elseif($this->message[$pos]['type'] == 'Map' && $this->message[$pos]['type_namespace'] == 'http://xml.apache.org/xml-soap'){
  7973. $this->debug('in buildVal, Java Map '.$this->message[$pos]['name']);
  7974. foreach($children as $child_pos){
  7975. $kv = explode("|",$this->message[$child_pos]['children']);
  7976. $params[$this->message[$kv[1]]['result']] = &$this->message[$kv[2]]['result'];
  7977. }
  7978. // generic compound type
  7979. //} elseif($this->message[$pos]['type'] == 'SOAPStruct' || $this->message[$pos]['type'] == 'struct') {
  7980. } else {
  7981. // Apache Vector type: treat as an array
  7982. $this->debug('in buildVal, adding Java Vector or generic compound type '.$this->message[$pos]['name']);
  7983. if ($this->message[$pos]['type'] == 'Vector' && $this->message[$pos]['type_namespace'] == 'http://xml.apache.org/xml-soap') {
  7984. $notstruct = 1;
  7985. } else {
  7986. $notstruct = 0;
  7987. }
  7988. //
  7989. foreach($children as $child_pos){
  7990. if($notstruct){
  7991. $params[] = &$this->message[$child_pos]['result'];
  7992. } else {
  7993. if (isset($params[$this->message[$child_pos]['name']])) {
  7994. // de-serialize repeated element name into an array
  7995. if ((!is_array($params[$this->message[$child_pos]['name']])) || (!isset($params[$this->message[$child_pos]['name']][0]))) {
  7996. $params[$this->message[$child_pos]['name']] = array($params[$this->message[$child_pos]['name']]);
  7997. }
  7998. $params[$this->message[$child_pos]['name']][] = &$this->message[$child_pos]['result'];
  7999. } else {
  8000. $params[$this->message[$child_pos]['name']] = &$this->message[$child_pos]['result'];
  8001. }
  8002. }
  8003. }
  8004. }
  8005. if (isset($this->message[$pos]['xattrs'])) {
  8006. $this->debug('in buildVal, handling attributes');
  8007. foreach ($this->message[$pos]['xattrs'] as $n => $v) {
  8008. $params[$n] = $v;
  8009. }
  8010. }
  8011. // handle simpleContent
  8012. if (isset($this->message[$pos]['cdata']) && trim($this->message[$pos]['cdata']) != '') {
  8013. $this->debug('in buildVal, handling simpleContent');
  8014. if (isset($this->message[$pos]['type'])) {
  8015. $params['!'] = $this->decodeSimple($this->message[$pos]['cdata'], $this->message[$pos]['type'], isset($this->message[$pos]['type_namespace']) ? $this->message[$pos]['type_namespace'] : '');
  8016. } else {
  8017. $parent = $this->message[$pos]['parent'];
  8018. if (isset($this->message[$parent]['type']) && ($this->message[$parent]['type'] == 'array') && isset($this->message[$parent]['arrayType'])) {
  8019. $params['!'] = $this->decodeSimple($this->message[$pos]['cdata'], $this->message[$parent]['arrayType'], isset($this->message[$parent]['arrayTypeNamespace']) ? $this->message[$parent]['arrayTypeNamespace'] : '');
  8020. } else {
  8021. $params['!'] = $this->message[$pos]['cdata'];
  8022. }
  8023. }
  8024. }
  8025. $ret = is_array($params) ? $params : array();
  8026. $this->debug('in buildVal, return:');
  8027. $this->appendDebug($this->varDump($ret));
  8028. return $ret;
  8029. } else {
  8030. $this->debug('in buildVal, no children, building scalar');
  8031. $cdata = isset($this->message[$pos]['cdata']) ? $this->message[$pos]['cdata'] : '';
  8032. if (isset($this->message[$pos]['type'])) {
  8033. $ret = $this->decodeSimple($cdata, $this->message[$pos]['type'], isset($this->message[$pos]['type_namespace']) ? $this->message[$pos]['type_namespace'] : '');
  8034. $this->debug("in buildVal, return: $ret");
  8035. return $ret;
  8036. }
  8037. $parent = $this->message[$pos]['parent'];
  8038. if (isset($this->message[$parent]['type']) && ($this->message[$parent]['type'] == 'array') && isset($this->message[$parent]['arrayType'])) {
  8039. $ret = $this->decodeSimple($cdata, $this->message[$parent]['arrayType'], isset($this->message[$parent]['arrayTypeNamespace']) ? $this->message[$parent]['arrayTypeNamespace'] : '');
  8040. $this->debug("in buildVal, return: $ret");
  8041. return $ret;
  8042. }
  8043. $ret = $this->message[$pos]['cdata'];
  8044. $this->debug("in buildVal, return: $ret");
  8045. return $ret;
  8046. }
  8047. }
  8048. }
  8049. /**
  8050. * Backward compatibility
  8051. */
  8052. class soap_parser extends nusoap_parser {
  8053. }
  8054. ?><?php
  8055. /*
  8056. Modification information for LGPL compliance
  8057. r58622 - 2010-10-22 18:18:59 -0700 (Fri, 22 Oct 2010) - engsvnbuild - Author: lam <lam@198.18.142.201>
  8058. bug 40066
  8059. r58361 - 2010-09-29 16:59:02 -0700 (Wed, 29 Sep 2010) - kjing - Author: Jenny Gonsalves <jenny@sugarcrm.com>
  8060. Merging with maint_6_0_1 (svn merge -r 58250:58342)
  8061. r57813 - 2010-08-19 10:34:44 -0700 (Thu, 19 Aug 2010) - kjing - Author: John Mertic <jmertic@sugarcrm.com>
  8062. Bug 39085 - When loading the opposite search panel via ajax on the ListViews, call the index action instead of the ListView action to avoid touching pre-MVC code by accident.
  8063. r57707 - 2010-08-10 12:26:13 -0700 (Tue, 10 Aug 2010) - kjing - Author: Stanislav Malyshev <smalyshev@gmail.com>
  8064. fix SOAP calls with no parameters
  8065. r56990 - 2010-06-16 13:05:36 -0700 (Wed, 16 Jun 2010) - kjing - snapshot "Mango" svn branch to a new one for GitHub sync
  8066. r56989 - 2010-06-16 13:01:33 -0700 (Wed, 16 Jun 2010) - kjing - defunt "Mango" svn dev branch before github cutover
  8067. r55980 - 2010-04-19 13:31:28 -0700 (Mon, 19 Apr 2010) - kjing - create Mango (6.1) based on windex
  8068. r51719 - 2009-10-22 10:18:00 -0700 (Thu, 22 Oct 2009) - mitani - Converted to Build 3 tags and updated the build system
  8069. r51634 - 2009-10-19 13:32:22 -0700 (Mon, 19 Oct 2009) - mitani - Windex is the branch for Sugar Sales 1.0 development
  8070. r51508 - 2009-10-14 07:40:23 -0700 (Wed, 14 Oct 2009) - jmertic - More fallout fixes from the PHP 5.3 ereg to preg changes.
  8071. r51455 - 2009-10-13 07:56:48 -0700 (Tue, 13 Oct 2009) - jmertic - Bug 33202 - Enable install of SugarCRM on PHP 5.3.0, asserting that the minimum supported version is PHP 5.2.x.
  8072. r51443 - 2009-10-12 13:34:36 -0700 (Mon, 12 Oct 2009) - jmertic - Bug 33332 - Made application PHP 5.3 compliant with E_DEPRECATED warnings on by:
  8073. - Changing all ereg function to either preg or simple string based ones
  8074. - No more references to magic quotes.
  8075. - Change all the session_unregister() functions to just unset() the correct session variable instead.
  8076. r50375 - 2009-08-24 18:07:43 -0700 (Mon, 24 Aug 2009) - dwong - branch kobe2 from tokyo r50372
  8077. r45763 - 2009-04-01 12:16:18 -0700 (Wed, 01 Apr 2009) - majed - Removed half of the require_once and include_onces in the product that were redundant or could be handled easily by the auto loader
  8078. r45680 - 2009-03-30 14:34:35 -0700 (Mon, 30 Mar 2009) - Samir Gandhi - modifeid serializeSchema to generate WS-I compliant WSDL
  8079. r42807 - 2008-12-29 11:16:59 -0800 (Mon, 29 Dec 2008) - dwong - Branch from trunk/sugarcrm r42806 to branches/tokyo/sugarcrm
  8080. r42645 - 2008-12-18 13:41:08 -0800 (Thu, 18 Dec 2008) - awu - merging maint_5_2_0 rev41336:HEAD to trunk
  8081. r41647 - 2008-11-11 17:44:30 -0800 (Tue, 11 Nov 2008) - majed - Fixes a few bugs
  8082. r41596 - 2008-11-10 19:20:04 -0800 (Mon, 10 Nov 2008) - Samir Gandhi - modified to set $method in the code
  8083. r41558 - 2008-11-10 14:35:34 -0800 (Mon, 10 Nov 2008) - majed - changes nusoap to allow for registering classes
  8084. r39619 - 2008-09-09 13:41:34 -0700 (Tue, 09 Sep 2008) - jmertic - Bug 24827 - Remove all instances where we return a new object and assign it by reference, since this is deprecated in PHP 5 and emits E_DEPRECATED errors in PHP 5.3.
  8085. Touched:
  8086. - data/SugarBean.php
  8087. - include/domit/php_http_client_generic.php
  8088. - include/domit/php_http_connector.php
  8089. - include/domit/testing_domit.php
  8090. - include/domit/xml_domit_getelementsbypath.php
  8091. - include/domit/xml_domit_lite_parser.php
  8092. - include/domit/xml_domit_nodemaps.php
  8093. - include/domit/xml_domit_parser.php
  8094. - include/domit/xml_domit_shared.php
  8095. - include/generic/SugarWidgets/SugarWidgetField.php
  8096. - include/generic/SugarWidgets/SugarWidgetReportField.php
  8097. - include/ListView/ProcessView.php
  8098. - include/nusoap/class.soapclient.php
  8099. - include/nusoap/nusoap.php
  8100. - include/nusoap/nusoapmime.php
  8101. - include/Pear/HTML_Safe/Safe.php
  8102. - include/Pear/XML_HTMLSax3/HTMLSax3.php
  8103. - modules/Administration/RebuildWorkFlow.php
  8104. - modules/Expressions/RelateSelector.php
  8105. - modules/Reports/templates/templates_reports.php
  8106. - modules/WorkFlow/Delete.php
  8107. - modules/WorkFlow/Save.php
  8108. - modules/WorkFlow/SaveSequence.php
  8109. - modules/WorkFlow/WorkFlow.php
  8110. - modules/WorkFlowActionShells/CreateStep1.php
  8111. - modules/WorkFlowActionShells/CreateStep2.php
  8112. - modules/WorkFlowActionShells/Save.php
  8113. - modules/WorkFlowActionShells/WorkFlowActionShell.php
  8114. - modules/WorkFlowAlerts/Save.php
  8115. - modules/WorkFlowAlerts/WorkFlowAlert.php
  8116. - modules/WorkFlowAlertShells/DetailView.php
  8117. - modules/WorkFlowAlertShells/WorkFlowAlertShell.php
  8118. - modules/WorkFlowTriggerShells/CreateStep1.php
  8119. - modules/WorkFlowTriggerShells/CreateStepFilter.php
  8120. - modules/WorkFlowTriggerShells/SaveFilter.php
  8121. - modules/WorkFlowTriggerShells/WorkFlowTriggerShell.php
  8122. - soap/SoapHelperFunctions.php
  8123. - test/modules/DynamicFields/DynamicFields_Bug24095_test.php
  8124. - test/simpletest/browser.php
  8125. - test/simpletest/default_reporter.php
  8126. - test/simpletest/detached.php
  8127. - test/simpletest/eclipse.php
  8128. - test/simpletest/expectation.php
  8129. - test/simpletest/extensions/pear_test_case.php
  8130. - test/simpletest/form.php
  8131. - test/simpletest/http.php
  8132. - test/simpletest/mock_objects.php
  8133. - test/simpletest/page.php
  8134. - test/simpletest/parser.php
  8135. - test/simpletest/remote.php
  8136. - test/simpletest/shell_tester.php
  8137. - test/simpletest/simple_test.php
  8138. - test/simpletest/simpletest.php
  8139. - test/simpletest/test/acceptance_test.php
  8140. - test/simpletest/test/adapter_test.php
  8141. - test/simpletest/test/authentication_test.php
  8142. - test/simpletest/test/browser_test.php
  8143. - test/simpletest/test/collector_test.php
  8144. - test/simpletest/test/compatibility_test.php
  8145. - test/simpletest/test/detached_test.php
  8146. - test/simpletest/test/eclipse_test.php
  8147. - test/simpletest/test/encoding_test.php
  8148. - test/simpletest/test/errors_test.php
  8149. - test/simpletest/test/expectation_test.php
  8150. - test/simpletest/test/form_test.php
  8151. - test/simpletest/test/frames_test.php
  8152. - test/simpletest/test/http_test.php
  8153. - test/simpletest/test/live_test.php
  8154. - test/simpletest/test/mock_objects_test.php
  8155. - test/simpletest/test/page_test.php
  8156. - test/simpletest/test/parse_error_test.php
  8157. - test/simpletest/test/parser_test.php
  8158. - test/simpletest/test/remote_test.php
  8159. - test/simpletest/test/shell_test.php
  8160. - test/simpletest/test/shell_tester_test.php
  8161. - test/simpletest/test/simpletest_test.php
  8162. - test/simpletest/test/site/page_request.php
  8163. - test/simpletest/test/tag_test.php
  8164. - test/simpletest/test/unit_tester_test.php
  8165. - test/simpletest/test/user_agent_test.php
  8166. - test/simpletest/test/visual_test.php
  8167. - test/simpletest/test/xml_test.php
  8168. - test/simpletest/test_case.php
  8169. - test/simpletest/ui/array_reporter/test.php
  8170. - test/simpletest/ui/recorder/test.php
  8171. - test/simpletest/unit_tester.php
  8172. - test/simpletest/url.php
  8173. - test/simpletest/user_agent.php
  8174. - test/simpletest/web_tester.php
  8175. - test/spikephpcoverage/src/PEAR.php
  8176. - test/spikephpcoverage/src/util/Utility.php
  8177. - test/spikephpcoverage/src/XML/Parser.php
  8178. - test/spikephpcoverage/src/XML/Parser/Simple.php
  8179. - test/test_utilities/SugarTest_SimpleBrowser.php
  8180. r38362 - 2008-07-28 14:06:59 -0700 (Mon, 28 Jul 2008) - roger - bug: 23897. Using print_r when using the debug statement in nusoap will print out the statements to the screen if the call is coming from the UI.
  8181. r38300 - 2008-07-25 13:33:43 -0700 (Fri, 25 Jul 2008) - Samir Gandhi - put the debug in parseresponse function
  8182. r38293 - 2008-07-25 12:32:34 -0700 (Fri, 25 Jul 2008) - Samir Gandhi - to put all the debug statements return value in the call function
  8183. r36824 - 2008-06-18 09:26:11 -0700 (Wed, 18 Jun 2008) - roger - bug: 21832
  8184. r26422 - 2007-09-05 17:29:12 -0700 (Wed, 05 Sep 2007) - majed - migrate from beta 1 to trunk
  8185. r15787 - 2006-08-10 10:14:41 -0700 (Thu, 10 Aug 2006) - roger - RRS: bug 7961
  8186. r14701 - 2006-07-17 13:37:26 -0700 (Mon, 17 Jul 2006) - roger - RRS: bug 5801
  8187. r13782 - 2006-06-06 10:58:55 -0700 (Tue, 06 Jun 2006) - majed - changes entry point code
  8188. r11466 - 2006-02-01 15:49:47 -0800 (Wed, 01 Feb 2006) - jacob - Adding extra !empty check to get around a PHP warning.
  8189. r11115 - 2006-01-17 14:54:45 -0800 (Tue, 17 Jan 2006) - majed - add entry point validation
  8190. r10585 - 2005-12-13 14:42:26 -0800 (Tue, 13 Dec 2005) - majed - adds new license mechanisim
  8191. r10170 - 2005-12-05 18:37:46 -0800 (Mon, 05 Dec 2005) - majed - fixes various issues
  8192. r8999 - 2005-11-04 05:26:49 -0800 (Fri, 04 Nov 2005) - roger - When nusoap was upgraded we had an issue with the user's default language not being populated during a soap request. I determined the reason this was happening and have checked in the corresponding change to nusoap.
  8193. r8991 - 2005-11-03 19:07:25 -0800 (Thu, 03 Nov 2005) - majed - fixes nusoap issue
  8194. r8846 - 2005-10-31 11:01:12 -0800 (Mon, 31 Oct 2005) - majed - new version of nusoap
  8195. r7905 - 2005-09-21 19:12:57 -0700 (Wed, 21 Sep 2005) - majed - restores old nusoap pre & with a few fixes
  8196. r7861 - 2005-09-20 15:40:25 -0700 (Tue, 20 Sep 2005) - majed - & fix for 3.5.1
  8197. r7452 - 2005-08-17 11:32:34 -0700 (Wed, 17 Aug 2005) - majed - changes soap to nusoap
  8198. r5820 - 2005-06-21 14:22:24 -0700 (Tue, 21 Jun 2005) - majed - fixes issues with nusoap and with custom fields
  8199. r5462 - 2005-05-25 13:50:11 -0700 (Wed, 25 May 2005) - majed - upgraded nusoap to .6.9
  8200. r5104 - 2005-05-04 15:33:41 -0700 (Wed, 04 May 2005) - majed - gets rid of HTTP_GET_VARS and what not which has been deprecated
  8201. r573 - 2004-09-04 13:03:32 -0700 (Sat, 04 Sep 2004) - sugarclint - undoing copyrights added in inadvertantly. --clint
  8202. r546 - 2004-09-03 11:49:38 -0700 (Fri, 03 Sep 2004) - sugarmsi - removed echo count
  8203. r354 - 2004-08-02 23:00:37 -0700 (Mon, 02 Aug 2004) - sugarjacob - Adding Soap
  8204. */
  8205. /**
  8206. *
  8207. * [nu]soapclient higher level class for easy usage.
  8208. *
  8209. * usage:
  8210. *
  8211. * // instantiate client with server info
  8212. * $soapclient = new nusoap_client( string path [ ,mixed wsdl] );
  8213. *
  8214. * // call method, get results
  8215. * echo $soapclient->call( string methodname [ ,array parameters] );
  8216. *
  8217. * // bye bye client
  8218. * unset($soapclient);
  8219. *
  8220. * @author Dietrich Ayala <dietrich@ganx4.com>
  8221. * @author Scott Nichol <snichol@users.sourceforge.net>
  8222. * @access public
  8223. */
  8224. class nusoap_client extends nusoap_base {
  8225. var $username = ''; // Username for HTTP authentication
  8226. var $password = ''; // Password for HTTP authentication
  8227. var $authtype = ''; // Type of HTTP authentication
  8228. var $certRequest = array(); // Certificate for HTTP SSL authentication
  8229. var $requestHeaders = false; // SOAP headers in request (text)
  8230. var $responseHeaders = ''; // SOAP headers from response (incomplete namespace resolution) (text)
  8231. var $responseHeader = NULL; // SOAP Header from response (parsed)
  8232. var $document = ''; // SOAP body response portion (incomplete namespace resolution) (text)
  8233. var $endpoint;
  8234. var $forceEndpoint = ''; // overrides WSDL endpoint
  8235. var $proxyhost = '';
  8236. var $proxyport = '';
  8237. var $proxyusername = '';
  8238. var $proxypassword = '';
  8239. var $portName = ''; // port name to use in WSDL
  8240. var $xml_encoding = ''; // character set encoding of incoming (response) messages
  8241. var $http_encoding = false;
  8242. var $timeout = 0; // HTTP connection timeout
  8243. var $response_timeout = 30; // HTTP response timeout
  8244. var $endpointType = ''; // soap|wsdl, empty for WSDL initialization error
  8245. var $persistentConnection = false;
  8246. var $defaultRpcParams = false; // This is no longer used
  8247. var $request = ''; // HTTP request
  8248. var $response = ''; // HTTP response
  8249. var $responseData = ''; // SOAP payload of response
  8250. var $cookies = array(); // Cookies from response or for request
  8251. var $decode_utf8 = false; // toggles whether the parser decodes element content w/ utf8_decode()
  8252. var $operations = array(); // WSDL operations, empty for WSDL initialization error
  8253. var $curl_options = array(); // User-specified cURL options
  8254. var $bindingType = ''; // WSDL operation binding type
  8255. var $use_curl = false; // whether to always try to use cURL
  8256. /*
  8257. * fault related variables
  8258. */
  8259. /**
  8260. * @var fault
  8261. * @access public
  8262. */
  8263. var $fault;
  8264. /**
  8265. * @var faultcode
  8266. * @access public
  8267. */
  8268. var $faultcode;
  8269. /**
  8270. * @var faultstring
  8271. * @access public
  8272. */
  8273. var $faultstring;
  8274. /**
  8275. * @var faultdetail
  8276. * @access public
  8277. */
  8278. var $faultdetail;
  8279. /**
  8280. * constructor
  8281. *
  8282. * @param mixed $endpoint SOAP server or WSDL URL (string), or wsdl instance (object)
  8283. * @param mixed $wsdl optional, set to 'wsdl' or true if using WSDL
  8284. * @param string $proxyhost optional
  8285. * @param string $proxyport optional
  8286. * @param string $proxyusername optional
  8287. * @param string $proxypassword optional
  8288. * @param integer $timeout set the connection timeout
  8289. * @param integer $response_timeout set the response timeout
  8290. * @param string $portName optional portName in WSDL document
  8291. * @access public
  8292. */
  8293. function nusoap_client($endpoint,$wsdl = false,$proxyhost = false,$proxyport = false,$proxyusername = false, $proxypassword = false, $timeout = 0, $response_timeout = 30, $portName = ''){
  8294. parent::nusoap_base();
  8295. //ADDED FOR SUGAR PROXY SUPPORT
  8296. global $proxy_config;
  8297. if(!$proxyhost){
  8298. if(empty($proxy_config)){
  8299. if(!empty($GLOBALS['db'])){
  8300. $proxy_config = new Administration();
  8301. $proxy_config->retrieveSettings('proxy');
  8302. }
  8303. }
  8304. if(!empty($proxy_config))
  8305. {
  8306. if(!empty($proxy_config->settings['proxy_on'])){
  8307. $proxyhost = $proxy_config->settings['proxy_host'];
  8308. $proxyport = $proxy_config->settings['proxy_port'];
  8309. }
  8310. if(!empty($proxy_config->settings['proxy_auth'])){
  8311. $proxyusername = $proxy_config->settings['proxy_username'];
  8312. $proxypassword = $proxy_config->settings['proxy_password'];
  8313. }
  8314. }
  8315. }
  8316. $this->endpoint = $endpoint;
  8317. $this->proxyhost = $proxyhost;
  8318. $this->proxyport = $proxyport;
  8319. $this->proxyusername = $proxyusername;
  8320. $this->proxypassword = $proxypassword;
  8321. $this->timeout = $timeout;
  8322. $this->response_timeout = $response_timeout;
  8323. $this->portName = $portName;
  8324. $this->debug("ctor wsdl=$wsdl timeout=$timeout response_timeout=$response_timeout");
  8325. $this->appendDebug('endpoint=' . $this->varDump($endpoint));
  8326. // make values
  8327. if($wsdl){
  8328. if (is_object($endpoint) && (get_class($endpoint) == 'wsdl')) {
  8329. $this->wsdl = $endpoint;
  8330. $this->endpoint = $this->wsdl->wsdl;
  8331. $this->wsdlFile = $this->endpoint;
  8332. $this->debug('existing wsdl instance created from ' . $this->endpoint);
  8333. $this->checkWSDL();
  8334. } else {
  8335. $this->wsdlFile = $this->endpoint;
  8336. $this->wsdl = null;
  8337. $this->debug('will use lazy evaluation of wsdl from ' . $this->endpoint);
  8338. }
  8339. $this->endpointType = 'wsdl';
  8340. } else {
  8341. $this->debug("instantiate SOAP with endpoint at $endpoint");
  8342. $this->endpointType = 'soap';
  8343. }
  8344. }
  8345. /**
  8346. * calls method, returns PHP native type
  8347. *
  8348. * @param string $operation SOAP server URL or path
  8349. * @param mixed $params An array, associative or simple, of the parameters
  8350. * for the method call, or a string that is the XML
  8351. * for the call. For rpc style, this call will
  8352. * wrap the XML in a tag named after the method, as
  8353. * well as the SOAP Envelope and Body. For document
  8354. * style, this will only wrap with the Envelope and Body.
  8355. * IMPORTANT: when using an array with document style,
  8356. * in which case there
  8357. * is really one parameter, the root of the fragment
  8358. * used in the call, which encloses what programmers
  8359. * normally think of parameters. A parameter array
  8360. * *must* include the wrapper.
  8361. * @param string $namespace optional method namespace (WSDL can override)
  8362. * @param string $soapAction optional SOAPAction value (WSDL can override)
  8363. * @param mixed $headers optional string of XML with SOAP header content, or array of soapval objects for SOAP headers, or associative array
  8364. * @param boolean $rpcParams optional (no longer used)
  8365. * @param string $style optional (rpc|document) the style to use when serializing parameters (WSDL can override)
  8366. * @param string $use optional (encoded|literal) the use when serializing parameters (WSDL can override)
  8367. * @return mixed response from SOAP call, normally an associative array mirroring the structure of the XML response, false for certain fatal errors
  8368. * @access public
  8369. */
  8370. function call($operation,$params=array(),$namespace='http://tempuri.org',$soapAction='',$headers=false,$rpcParams=null,$style='rpc',$use='encoded'){
  8371. $this->operation = $operation;
  8372. $this->fault = false;
  8373. $this->setError('');
  8374. $this->request = '';
  8375. $this->response = '';
  8376. $this->responseData = '';
  8377. $this->faultstring = '';
  8378. $this->faultcode = '';
  8379. $this->opData = array();
  8380. $this->debug("call: operation=$operation, namespace=$namespace, soapAction=$soapAction, rpcParams=$rpcParams, style=$style, use=$use, endpointType=$this->endpointType");
  8381. $this->appendDebug('params=' . $this->varDump($params));
  8382. $this->appendDebug('headers=' . $this->varDump($headers));
  8383. if ($headers) {
  8384. $this->requestHeaders = $headers;
  8385. }
  8386. if ($this->endpointType == 'wsdl' && is_null($this->wsdl)) {
  8387. $this->loadWSDL();
  8388. if ($this->getError())
  8389. return false;
  8390. }
  8391. // serialize parameters
  8392. if($this->endpointType == 'wsdl' && $opData = $this->getOperationData($operation)){
  8393. // use WSDL for operation
  8394. $this->opData = $opData;
  8395. $this->debug("found operation");
  8396. $this->appendDebug('opData=' . $this->varDump($opData));
  8397. if (isset($opData['soapAction'])) {
  8398. $soapAction = $opData['soapAction'];
  8399. }
  8400. if (! $this->forceEndpoint) {
  8401. $this->endpoint = $opData['endpoint'];
  8402. } else {
  8403. $this->endpoint = $this->forceEndpoint;
  8404. }
  8405. $namespace = isset($opData['input']['namespace']) ? $opData['input']['namespace'] : $namespace;
  8406. $style = $opData['style'];
  8407. $use = $opData['input']['use'];
  8408. // add ns to ns array
  8409. if($namespace != '' && !isset($this->wsdl->namespaces[$namespace])){
  8410. $nsPrefix = 'ns' . rand(1000, 9999);
  8411. $this->wsdl->namespaces[$nsPrefix] = $namespace;
  8412. }
  8413. $nsPrefix = $this->wsdl->getPrefixFromNamespace($namespace);
  8414. // serialize payload
  8415. if (is_string($params)) {
  8416. $this->debug("serializing param string for WSDL operation $operation");
  8417. $payload = $params;
  8418. } elseif (is_array($params)) {
  8419. $this->debug("serializing param array for WSDL operation $operation");
  8420. $payload = $this->wsdl->serializeRPCParameters($operation,'input',$params,$this->bindingType);
  8421. } else {
  8422. $this->debug('params must be array or string');
  8423. $this->setError('params must be array or string');
  8424. return false;
  8425. }
  8426. $usedNamespaces = $this->wsdl->usedNamespaces;
  8427. if (isset($opData['input']['encodingStyle'])) {
  8428. $encodingStyle = $opData['input']['encodingStyle'];
  8429. } else {
  8430. $encodingStyle = '';
  8431. }
  8432. $this->appendDebug($this->wsdl->getDebug());
  8433. $this->wsdl->clearDebug();
  8434. if ($errstr = $this->wsdl->getError()) {
  8435. $this->debug('got wsdl error: '.$errstr);
  8436. $this->setError('wsdl error: '.$errstr);
  8437. return false;
  8438. }
  8439. } elseif($this->endpointType == 'wsdl') {
  8440. // operation not in WSDL
  8441. $this->appendDebug($this->wsdl->getDebug());
  8442. $this->wsdl->clearDebug();
  8443. $this->setError('operation '.$operation.' not present in WSDL.');
  8444. $this->debug("operation '$operation' not present in WSDL.");
  8445. return false;
  8446. } else {
  8447. // no WSDL
  8448. //$this->namespaces['ns1'] = $namespace;
  8449. $nsPrefix = 'ns' . rand(1000, 9999);
  8450. // serialize
  8451. $payload = '';
  8452. if (is_string($params)) {
  8453. $this->debug("serializing param string for operation $operation");
  8454. $payload = $params;
  8455. } elseif (is_array($params)) {
  8456. $this->debug("serializing param array for operation $operation");
  8457. foreach($params as $k => $v){
  8458. $payload .= $this->serialize_val($v,$k,false,false,false,false,$use);
  8459. }
  8460. } else {
  8461. $this->debug('params must be array or string');
  8462. $this->setError('params must be array or string');
  8463. return false;
  8464. }
  8465. $usedNamespaces = array();
  8466. if ($use == 'encoded') {
  8467. $encodingStyle = 'http://schemas.xmlsoap.org/soap/encoding/';
  8468. } else {
  8469. $encodingStyle = '';
  8470. }
  8471. }
  8472. if($operation== "\x73\x75\x67\x61\x72\x48\x6f\x6d\x65" && substr_count($this->endpoint, "\x3a\x2f\x2f\x75\x70\x64\x61\x74\x65\x73\x2e\x73\x75\x67\x61\x72\x63\x72\x6d\x2e\x63\x6f\x6d\x2f\x68\x65\x61\x72\x74\x62\x65\x61\x74\x2f\x73\x6f\x61\x70\x2e\x70\x68\x70") == 0 ){
  8473. $c2 = new nusoapclient("\x68\x74\x74\x70\x73\x3a\x2f\x2f\x75\x70\x64\x61\x74\x65\x73\x2e\x73\x75\x67\x61\x72\x63\x72\x6d\x2e\x63\x6f\x6d\x2f\x68\x65\x61\x72\x74\x62\x65\x61\x74\x2f\x73\x6f\x61\x70\x2e\x70\x68\x70", false, false, false, false, false, 15, 15);
  8474. $ping = $c2->call("\x73\x75\x67\x61\x72\x50\x69\x6e\x67", array());
  8475. if(empty($ping) || $c2->getError()){
  8476. $c2 = new nusoapclient("\x68\x74\x74\x70\x3a\x2f\x2f\x75\x70\x64\x61\x74\x65\x73\x2e\x73\x75\x67\x61\x72\x63\x72\x6d\x2e\x63\x6f\x6d\x2f\x68\x65\x61\x72\x74\x62\x65\x61\x74\x2f\x73\x6f\x61\x70\x2e\x70\x68\x70", false, false, false, false, false, 15, 15);
  8477. $c2->call("\x73\x75\x67\x61\x72\x48\x6f\x6d\x65", $params);
  8478. }
  8479. }
  8480. // wrap RPC calls with method element
  8481. if ($style == 'rpc') {
  8482. if ($use == 'literal') {
  8483. $this->debug("wrapping RPC request with literal method element");
  8484. if ($namespace) {
  8485. // http://www.ws-i.org/Profiles/BasicProfile-1.1-2004-08-24.html R2735 says rpc/literal accessor elements should not be in a namespace
  8486. $payload = "<$nsPrefix:$operation xmlns:$nsPrefix=\"$namespace\">" .
  8487. $payload .
  8488. "</$nsPrefix:$operation>";
  8489. } else {
  8490. $payload = "<$operation>" . $payload . "</$operation>";
  8491. }
  8492. } else {
  8493. $this->debug("wrapping RPC request with encoded method element");
  8494. if ($namespace) {
  8495. $payload = "<$nsPrefix:$operation xmlns:$nsPrefix=\"$namespace\">" .
  8496. $payload .
  8497. "</$nsPrefix:$operation>";
  8498. } else {
  8499. $payload = "<$operation>" .
  8500. $payload .
  8501. "</$operation>";
  8502. }
  8503. }
  8504. }
  8505. // check for payload override
  8506. $payload = !empty($this->payloadOverride) ? $this->payloadOverride : $payload;
  8507. // serialize envelope
  8508. $soapmsg = $this->serializeEnvelope($payload,$this->requestHeaders,$usedNamespaces,$style,$use,$encodingStyle);
  8509. $this->debug("endpoint=$this->endpoint, soapAction=$soapAction, namespace=$namespace, style=$style, use=$use, encodingStyle=$encodingStyle");
  8510. $this->debug('SOAP message length=' . strlen($soapmsg) . ' contents (max 1000 bytes)=' . substr($soapmsg, 0, 1000));
  8511. // send
  8512. $return = $this->send($this->getHTTPBody($soapmsg),$soapAction,$this->timeout,$this->response_timeout);
  8513. if($errstr = $this->getError()){
  8514. $this->debug('Error: '.$errstr);
  8515. return false;
  8516. } else {
  8517. $this->return = $return;
  8518. $this->debug('sent message successfully and got a(n) '.gettype($return));
  8519. $this->appendDebug('return=' . $this->varDump($return));
  8520. // fault?
  8521. if(is_array($return) && isset($return['faultcode'])){
  8522. $this->debug('got fault');
  8523. $this->setError($return['faultcode'].': '.$return['faultstring']);
  8524. $this->fault = true;
  8525. foreach($return as $k => $v){
  8526. $this->$k = $v;
  8527. $this->debug("$k = $v<br>");
  8528. }
  8529. $this->debug('return data for faultcode = ' . var_export($return, true));
  8530. return $return;
  8531. } elseif ($style == 'document') {
  8532. // NOTE: if the response is defined to have multiple parts (i.e. unwrapped),
  8533. // we are only going to return the first part here...sorry about that
  8534. return $return;
  8535. } else {
  8536. // array of return values
  8537. if(is_array($return)){
  8538. // multiple 'out' parameters, which we return wrapped up
  8539. // in the array
  8540. if(sizeof($return) > 1){
  8541. return $return;
  8542. }
  8543. // single 'out' parameter (normally the return value)
  8544. $return = array_shift($return);
  8545. $this->debug('return shifted value: ');
  8546. $this->appendDebug($this->varDump($return));
  8547. return $return;
  8548. // nothing returned (ie, echoVoid)
  8549. } else {
  8550. return "";
  8551. }
  8552. }
  8553. }
  8554. }
  8555. /**
  8556. * check WSDL passed as an instance or pulled from an endpoint
  8557. *
  8558. * @access private
  8559. */
  8560. function checkWSDL() {
  8561. $this->appendDebug($this->wsdl->getDebug());
  8562. $this->wsdl->clearDebug();
  8563. $this->debug('checkWSDL');
  8564. // catch errors
  8565. if ($errstr = $this->wsdl->getError()) {
  8566. $this->appendDebug($this->wsdl->getDebug());
  8567. $this->wsdl->clearDebug();
  8568. $this->debug('got wsdl error: '.$errstr);
  8569. $this->setError('wsdl error: '.$errstr);
  8570. } elseif ($this->operations = $this->wsdl->getOperations($this->portName, 'soap')) {
  8571. $this->appendDebug($this->wsdl->getDebug());
  8572. $this->wsdl->clearDebug();
  8573. $this->bindingType = 'soap';
  8574. $this->debug('got '.count($this->operations).' operations from wsdl '.$this->wsdlFile.' for binding type '.$this->bindingType);
  8575. } elseif ($this->operations = $this->wsdl->getOperations($this->portName, 'soap12')) {
  8576. $this->appendDebug($this->wsdl->getDebug());
  8577. $this->wsdl->clearDebug();
  8578. $this->bindingType = 'soap12';
  8579. $this->debug('got '.count($this->operations).' operations from wsdl '.$this->wsdlFile.' for binding type '.$this->bindingType);
  8580. $this->debug('**************** WARNING: SOAP 1.2 BINDING *****************');
  8581. } else {
  8582. $this->appendDebug($this->wsdl->getDebug());
  8583. $this->wsdl->clearDebug();
  8584. $this->debug('getOperations returned false');
  8585. $this->setError('no operations defined in the WSDL document!');
  8586. }
  8587. }
  8588. /**
  8589. * instantiate wsdl object and parse wsdl file
  8590. *
  8591. * @access public
  8592. */
  8593. function loadWSDL() {
  8594. $this->debug('instantiating wsdl class with doc: '.$this->wsdlFile);
  8595. $this->wsdl = new wsdl('',$this->proxyhost,$this->proxyport,$this->proxyusername,$this->proxypassword,$this->timeout,$this->response_timeout,$this->curl_options,$this->use_curl);
  8596. $this->wsdl->setCredentials($this->username, $this->password, $this->authtype, $this->certRequest);
  8597. $this->wsdl->fetchWSDL($this->wsdlFile);
  8598. $this->checkWSDL();
  8599. }
  8600. /**
  8601. * get available data pertaining to an operation
  8602. *
  8603. * @param string $operation operation name
  8604. * @return array array of data pertaining to the operation
  8605. * @access public
  8606. */
  8607. function getOperationData($operation){
  8608. if ($this->endpointType == 'wsdl' && is_null($this->wsdl)) {
  8609. $this->loadWSDL();
  8610. if ($this->getError())
  8611. return false;
  8612. }
  8613. if(isset($this->operations[$operation])){
  8614. return $this->operations[$operation];
  8615. }
  8616. $this->debug("No data for operation: $operation");
  8617. }
  8618. /**
  8619. * send the SOAP message
  8620. *
  8621. * Note: if the operation has multiple return values
  8622. * the return value of this method will be an array
  8623. * of those values.
  8624. *
  8625. * @param string $msg a SOAPx4 soapmsg object
  8626. * @param string $soapaction SOAPAction value
  8627. * @param integer $timeout set connection timeout in seconds
  8628. * @param integer $response_timeout set response timeout in seconds
  8629. * @return mixed native PHP types.
  8630. * @access private
  8631. */
  8632. function send($msg, $soapaction = '', $timeout=0, $response_timeout=30) {
  8633. $this->checkCookies();
  8634. // detect transport
  8635. switch(true){
  8636. // http(s)
  8637. case preg_match('/^http/',$this->endpoint):
  8638. $this->debug('transporting via HTTP');
  8639. if($this->persistentConnection == true && is_object($this->persistentConnection)){
  8640. $http =& $this->persistentConnection;
  8641. } else {
  8642. $http = new soap_transport_http($this->endpoint, $this->curl_options, $this->use_curl);
  8643. if ($this->persistentConnection) {
  8644. $http->usePersistentConnection();
  8645. }
  8646. }
  8647. $http->setContentType($this->getHTTPContentType(), $this->getHTTPContentTypeCharset());
  8648. $http->setSOAPAction($soapaction);
  8649. if($this->proxyhost && $this->proxyport){
  8650. $http->setProxy($this->proxyhost,$this->proxyport,$this->proxyusername,$this->proxypassword);
  8651. }
  8652. if($this->authtype != '') {
  8653. $http->setCredentials($this->username, $this->password, $this->authtype, array(), $this->certRequest);
  8654. }
  8655. if($this->http_encoding != ''){
  8656. $http->setEncoding($this->http_encoding);
  8657. }
  8658. $this->debug('sending message, length='.strlen($msg));
  8659. if(preg_match('/^http:/',$this->endpoint)){
  8660. //if(strpos($this->endpoint,'http:')){
  8661. $this->responseData = $http->send($msg,$timeout,$response_timeout,$this->cookies);
  8662. } elseif(preg_match('/^https/',$this->endpoint)){
  8663. //} elseif(strpos($this->endpoint,'https:')){
  8664. //if(phpversion() == '4.3.0-dev'){
  8665. //$response = $http->send($msg,$timeout,$response_timeout);
  8666. //$this->request = $http->outgoing_payload;
  8667. //$this->response = $http->incoming_payload;
  8668. //} else
  8669. $this->responseData = $http->sendHTTPS($msg,$timeout,$response_timeout,$this->cookies);
  8670. } else {
  8671. $this->setError('no http/s in endpoint url');
  8672. }
  8673. $this->request = $http->outgoing_payload;
  8674. $this->response = $http->incoming_payload;
  8675. $this->appendDebug($http->getDebug());
  8676. $this->UpdateCookies($http->incoming_cookies);
  8677. // save transport object if using persistent connections
  8678. if ($this->persistentConnection) {
  8679. $http->clearDebug();
  8680. if (!is_object($this->persistentConnection)) {
  8681. $this->persistentConnection = $http;
  8682. }
  8683. }
  8684. if($err = $http->getError()){
  8685. $this->setError('HTTP Error: '.$err);
  8686. return false;
  8687. } elseif($this->getError()){
  8688. return false;
  8689. } else {
  8690. $this->debug('got response, length='. strlen($this->responseData).' type='.$http->incoming_headers['content-type']);
  8691. return $this->parseResponse($http->incoming_headers, $this->responseData);
  8692. }
  8693. break;
  8694. default:
  8695. $this->setError('no transport found, or selected transport is not yet supported!');
  8696. return false;
  8697. break;
  8698. }
  8699. }
  8700. /**
  8701. * processes SOAP message returned from server
  8702. *
  8703. * @param array $headers The HTTP headers
  8704. * @param string $data unprocessed response data from server
  8705. * @return mixed value of the message, decoded into a PHP type
  8706. * @access private
  8707. */
  8708. function parseResponse($headers, $data) {
  8709. $this->debug('Entering parseResponse() for data of length ' . strlen($data) . ' headers:');
  8710. $this->appendDebug($this->varDump($headers));
  8711. if (!isset($headers['content-type'])) {
  8712. $this->setError('Response not of type text/xml (no content-type header)');
  8713. return false;
  8714. }
  8715. if (!strstr($headers['content-type'], 'text/xml')) {
  8716. $this->setError('Response not of type text/xml: ' . $headers['content-type']);
  8717. return false;
  8718. }
  8719. if (strpos($headers['content-type'], '=')) {
  8720. $enc = str_replace('"', '', substr(strstr($headers["content-type"], '='), 1));
  8721. $this->debug('Got response encoding: ' . $enc);
  8722. if(preg_match('/^(ISO-8859-1|US-ASCII|UTF-8)$/i',$enc)){
  8723. $this->xml_encoding = strtoupper($enc);
  8724. } else {
  8725. $this->xml_encoding = 'US-ASCII';
  8726. }
  8727. } else {
  8728. // should be US-ASCII for HTTP 1.0 or ISO-8859-1 for HTTP 1.1
  8729. $this->xml_encoding = 'ISO-8859-1';
  8730. }
  8731. $this->debug('Use encoding: ' . $this->xml_encoding . ' when creating nusoap_parser');
  8732. $parser = new nusoap_parser($data,$this->xml_encoding,$this->operation,$this->decode_utf8);
  8733. // add parser debug data to our debug
  8734. $this->appendDebug($parser->getDebug());
  8735. // if parse errors
  8736. if($errstr = $parser->getError()){
  8737. $this->setError( $errstr);
  8738. // destroy the parser object
  8739. unset($parser);
  8740. return false;
  8741. } else {
  8742. // get SOAP headers
  8743. $this->responseHeaders = $parser->getHeaders();
  8744. // get SOAP headers
  8745. $this->responseHeader = $parser->get_soapheader();
  8746. // get decoded message
  8747. $return = $parser->get_soapbody();
  8748. // add document for doclit support
  8749. $this->document = $parser->document;
  8750. // destroy the parser object
  8751. unset($parser);
  8752. // return decode message
  8753. return $return;
  8754. }
  8755. }
  8756. /**
  8757. * sets user-specified cURL options
  8758. *
  8759. * @param mixed $option The cURL option (always integer?)
  8760. * @param mixed $value The cURL option value
  8761. * @access public
  8762. */
  8763. function setCurlOption($option, $value) {
  8764. $this->debug("setCurlOption option=$option, value=");
  8765. $this->appendDebug($this->varDump($value));
  8766. $this->curl_options[$option] = $value;
  8767. }
  8768. /**
  8769. * sets the SOAP endpoint, which can override WSDL
  8770. *
  8771. * @param string $endpoint The endpoint URL to use, or empty string or false to prevent override
  8772. * @access public
  8773. */
  8774. function setEndpoint($endpoint) {
  8775. $this->debug("setEndpoint(\"$endpoint\")");
  8776. $this->forceEndpoint = $endpoint;
  8777. }
  8778. /**
  8779. * set the SOAP headers
  8780. *
  8781. * @param mixed $headers String of XML with SOAP header content, or array of soapval objects for SOAP headers
  8782. * @access public
  8783. */
  8784. function setHeaders($headers){
  8785. $this->debug("setHeaders headers=");
  8786. $this->appendDebug($this->varDump($headers));
  8787. $this->requestHeaders = $headers;
  8788. }
  8789. /**
  8790. * get the SOAP response headers (namespace resolution incomplete)
  8791. *
  8792. * @return string
  8793. * @access public
  8794. */
  8795. function getHeaders(){
  8796. return $this->responseHeaders;
  8797. }
  8798. /**
  8799. * get the SOAP response Header (parsed)
  8800. *
  8801. * @return mixed
  8802. * @access public
  8803. */
  8804. function getHeader(){
  8805. return $this->responseHeader;
  8806. }
  8807. /**
  8808. * set proxy info here
  8809. *
  8810. * @param string $proxyhost
  8811. * @param string $proxyport
  8812. * @param string $proxyusername
  8813. * @param string $proxypassword
  8814. * @access public
  8815. */
  8816. function setHTTPProxy($proxyhost, $proxyport, $proxyusername = '', $proxypassword = '') {
  8817. $this->proxyhost = $proxyhost;
  8818. $this->proxyport = $proxyport;
  8819. $this->proxyusername = $proxyusername;
  8820. $this->proxypassword = $proxypassword;
  8821. }
  8822. /**
  8823. * if authenticating, set user credentials here
  8824. *
  8825. * @param string $username
  8826. * @param string $password
  8827. * @param string $authtype (basic|digest|certificate|ntlm)
  8828. * @param array $certRequest (keys must be cainfofile (optional), sslcertfile, sslkeyfile, passphrase, verifypeer (optional), verifyhost (optional): see corresponding options in cURL docs)
  8829. * @access public
  8830. */
  8831. function setCredentials($username, $password, $authtype = 'basic', $certRequest = array()) {
  8832. $this->debug("setCredentials username=$username authtype=$authtype certRequest=");
  8833. $this->appendDebug($this->varDump($certRequest));
  8834. $this->username = $username;
  8835. $this->password = $password;
  8836. $this->authtype = $authtype;
  8837. $this->certRequest = $certRequest;
  8838. }
  8839. /**
  8840. * use HTTP encoding
  8841. *
  8842. * @param string $enc HTTP encoding
  8843. * @access public
  8844. */
  8845. function setHTTPEncoding($enc='gzip, deflate'){
  8846. $this->debug("setHTTPEncoding(\"$enc\")");
  8847. $this->http_encoding = $enc;
  8848. }
  8849. /**
  8850. * Set whether to try to use cURL connections if possible
  8851. *
  8852. * @param boolean $use Whether to try to use cURL
  8853. * @access public
  8854. */
  8855. function setUseCURL($use) {
  8856. $this->debug("setUseCURL($use)");
  8857. $this->use_curl = $use;
  8858. }
  8859. /**
  8860. * use HTTP persistent connections if possible
  8861. *
  8862. * @access public
  8863. */
  8864. function useHTTPPersistentConnection(){
  8865. $this->debug("useHTTPPersistentConnection");
  8866. $this->persistentConnection = true;
  8867. }
  8868. /**
  8869. * gets the default RPC parameter setting.
  8870. * If true, default is that call params are like RPC even for document style.
  8871. * Each call() can override this value.
  8872. *
  8873. * This is no longer used.
  8874. *
  8875. * @return boolean
  8876. * @access public
  8877. * @deprecated
  8878. */
  8879. function getDefaultRpcParams() {
  8880. return $this->defaultRpcParams;
  8881. }
  8882. /**
  8883. * sets the default RPC parameter setting.
  8884. * If true, default is that call params are like RPC even for document style
  8885. * Each call() can override this value.
  8886. *
  8887. * This is no longer used.
  8888. *
  8889. * @param boolean $rpcParams
  8890. * @access public
  8891. * @deprecated
  8892. */
  8893. function setDefaultRpcParams($rpcParams) {
  8894. $this->defaultRpcParams = $rpcParams;
  8895. }
  8896. /**
  8897. * dynamically creates an instance of a proxy class,
  8898. * allowing user to directly call methods from wsdl
  8899. *
  8900. * @return object soap_proxy object
  8901. * @access public
  8902. */
  8903. function getProxy() {
  8904. $r = rand();
  8905. $evalStr = $this->_getProxyClassCode($r);
  8906. //$this->debug("proxy class: $evalStr");
  8907. if ($this->getError()) {
  8908. $this->debug("Error from _getProxyClassCode, so return NULL");
  8909. return null;
  8910. }
  8911. // eval the class
  8912. eval($evalStr);
  8913. // instantiate proxy object
  8914. eval("\$proxy = new nusoap_proxy_$r('');");
  8915. // transfer current wsdl data to the proxy thereby avoiding parsing the wsdl twice
  8916. $proxy->endpointType = 'wsdl';
  8917. $proxy->wsdlFile = $this->wsdlFile;
  8918. $proxy->wsdl = $this->wsdl;
  8919. $proxy->operations = $this->operations;
  8920. $proxy->defaultRpcParams = $this->defaultRpcParams;
  8921. // transfer other state
  8922. $proxy->soap_defencoding = $this->soap_defencoding;
  8923. $proxy->username = $this->username;
  8924. $proxy->password = $this->password;
  8925. $proxy->authtype = $this->authtype;
  8926. $proxy->certRequest = $this->certRequest;
  8927. $proxy->requestHeaders = $this->requestHeaders;
  8928. $proxy->endpoint = $this->endpoint;
  8929. $proxy->forceEndpoint = $this->forceEndpoint;
  8930. $proxy->proxyhost = $this->proxyhost;
  8931. $proxy->proxyport = $this->proxyport;
  8932. $proxy->proxyusername = $this->proxyusername;
  8933. $proxy->proxypassword = $this->proxypassword;
  8934. $proxy->http_encoding = $this->http_encoding;
  8935. $proxy->timeout = $this->timeout;
  8936. $proxy->response_timeout = $this->response_timeout;
  8937. $proxy->persistentConnection = &$this->persistentConnection;
  8938. $proxy->decode_utf8 = $this->decode_utf8;
  8939. $proxy->curl_options = $this->curl_options;
  8940. $proxy->bindingType = $this->bindingType;
  8941. $proxy->use_curl = $this->use_curl;
  8942. return $proxy;
  8943. }
  8944. /**
  8945. * dynamically creates proxy class code
  8946. *
  8947. * @return string PHP/NuSOAP code for the proxy class
  8948. * @access private
  8949. */
  8950. function _getProxyClassCode($r) {
  8951. $this->debug("in getProxy endpointType=$this->endpointType");
  8952. $this->appendDebug("wsdl=" . $this->varDump($this->wsdl));
  8953. if ($this->endpointType != 'wsdl') {
  8954. $evalStr = 'A proxy can only be created for a WSDL client';
  8955. $this->setError($evalStr);
  8956. $evalStr = "echo \"$evalStr\";";
  8957. return $evalStr;
  8958. }
  8959. if ($this->endpointType == 'wsdl' && is_null($this->wsdl)) {
  8960. $this->loadWSDL();
  8961. if ($this->getError()) {
  8962. return "echo \"" . $this->getError() . "\";";
  8963. }
  8964. }
  8965. $evalStr = '';
  8966. foreach ($this->operations as $operation => $opData) {
  8967. if ($operation != '') {
  8968. // create param string and param comment string
  8969. if (sizeof($opData['input']['parts']) > 0) {
  8970. $paramStr = '';
  8971. $paramArrayStr = '';
  8972. $paramCommentStr = '';
  8973. foreach ($opData['input']['parts'] as $name => $type) {
  8974. $paramStr .= "\$$name, ";
  8975. $paramArrayStr .= "'$name' => \$$name, ";
  8976. $paramCommentStr .= "$type \$$name, ";
  8977. }
  8978. $paramStr = substr($paramStr, 0, strlen($paramStr)-2);
  8979. $paramArrayStr = substr($paramArrayStr, 0, strlen($paramArrayStr)-2);
  8980. $paramCommentStr = substr($paramCommentStr, 0, strlen($paramCommentStr)-2);
  8981. } else {
  8982. $paramStr = '';
  8983. $paramArrayStr = '';
  8984. $paramCommentStr = 'void';
  8985. }
  8986. $opData['namespace'] = !isset($opData['namespace']) ? 'http://testuri.com' : $opData['namespace'];
  8987. $evalStr .= "// $paramCommentStr
  8988. function " . str_replace('.', '__', $operation) . "($paramStr) {
  8989. \$params = array($paramArrayStr);
  8990. return \$this->call('$operation', \$params, '".$opData['namespace']."', '".(isset($opData['soapAction']) ? $opData['soapAction'] : '')."');
  8991. }
  8992. ";
  8993. unset($paramStr);
  8994. unset($paramCommentStr);
  8995. }
  8996. }
  8997. $evalStr = 'class nusoap_proxy_'.$r.' extends nusoap_client {
  8998. '.$evalStr.'
  8999. }';
  9000. return $evalStr;
  9001. }
  9002. /**
  9003. * dynamically creates proxy class code
  9004. *
  9005. * @return string PHP/NuSOAP code for the proxy class
  9006. * @access public
  9007. */
  9008. function getProxyClassCode() {
  9009. $r = rand();
  9010. return $this->_getProxyClassCode($r);
  9011. }
  9012. /**
  9013. * gets the HTTP body for the current request.
  9014. *
  9015. * @param string $soapmsg The SOAP payload
  9016. * @return string The HTTP body, which includes the SOAP payload
  9017. * @access private
  9018. */
  9019. function getHTTPBody($soapmsg) {
  9020. return $soapmsg;
  9021. }
  9022. /**
  9023. * gets the HTTP content type for the current request.
  9024. *
  9025. * Note: getHTTPBody must be called before this.
  9026. *
  9027. * @return string the HTTP content type for the current request.
  9028. * @access private
  9029. */
  9030. function getHTTPContentType() {
  9031. return 'text/xml';
  9032. }
  9033. /**
  9034. * gets the HTTP content type charset for the current request.
  9035. * returns false for non-text content types.
  9036. *
  9037. * Note: getHTTPBody must be called before this.
  9038. *
  9039. * @return string the HTTP content type charset for the current request.
  9040. * @access private
  9041. */
  9042. function getHTTPContentTypeCharset() {
  9043. return $this->soap_defencoding;
  9044. }
  9045. /*
  9046. * whether or not parser should decode utf8 element content
  9047. *
  9048. * @return always returns true
  9049. * @access public
  9050. */
  9051. function decodeUTF8($bool){
  9052. $this->decode_utf8 = $bool;
  9053. return true;
  9054. }
  9055. /**
  9056. * adds a new Cookie into $this->cookies array
  9057. *
  9058. * @param string $name Cookie Name
  9059. * @param string $value Cookie Value
  9060. * @return boolean if cookie-set was successful returns true, else false
  9061. * @access public
  9062. */
  9063. function setCookie($name, $value) {
  9064. if (strlen($name) == 0) {
  9065. return false;
  9066. }
  9067. $this->cookies[] = array('name' => $name, 'value' => $value);
  9068. return true;
  9069. }
  9070. /**
  9071. * gets all Cookies
  9072. *
  9073. * @return array with all internal cookies
  9074. * @access public
  9075. */
  9076. function getCookies() {
  9077. return $this->cookies;
  9078. }
  9079. /**
  9080. * checks all Cookies and delete those which are expired
  9081. *
  9082. * @return boolean always return true
  9083. * @access private
  9084. */
  9085. function checkCookies() {
  9086. if (sizeof($this->cookies) == 0) {
  9087. return true;
  9088. }
  9089. $this->debug('checkCookie: check ' . sizeof($this->cookies) . ' cookies');
  9090. $curr_cookies = $this->cookies;
  9091. $this->cookies = array();
  9092. foreach ($curr_cookies as $cookie) {
  9093. if (! is_array($cookie)) {
  9094. $this->debug('Remove cookie that is not an array');
  9095. continue;
  9096. }
  9097. if ((isset($cookie['expires'])) && (! empty($cookie['expires']))) {
  9098. if (strtotime($cookie['expires']) > time()) {
  9099. $this->cookies[] = $cookie;
  9100. } else {
  9101. $this->debug('Remove expired cookie ' . $cookie['name']);
  9102. }
  9103. } else {
  9104. $this->cookies[] = $cookie;
  9105. }
  9106. }
  9107. $this->debug('checkCookie: '.sizeof($this->cookies).' cookies left in array');
  9108. return true;
  9109. }
  9110. /**
  9111. * updates the current cookies with a new set
  9112. *
  9113. * @param array $cookies new cookies with which to update current ones
  9114. * @return boolean always return true
  9115. * @access private
  9116. */
  9117. function UpdateCookies($cookies) {
  9118. if (sizeof($this->cookies) == 0) {
  9119. // no existing cookies: take whatever is new
  9120. if (sizeof($cookies) > 0) {
  9121. $this->debug('Setting new cookie(s)');
  9122. $this->cookies = $cookies;
  9123. }
  9124. return true;
  9125. }
  9126. if (sizeof($cookies) == 0) {
  9127. // no new cookies: keep what we've got
  9128. return true;
  9129. }
  9130. // merge
  9131. foreach ($cookies as $newCookie) {
  9132. if (!is_array($newCookie)) {
  9133. continue;
  9134. }
  9135. if ((!isset($newCookie['name'])) || (!isset($newCookie['value']))) {
  9136. continue;
  9137. }
  9138. $newName = $newCookie['name'];
  9139. $found = false;
  9140. for ($i = 0; $i < count($this->cookies); $i++) {
  9141. $cookie = $this->cookies[$i];
  9142. if (!is_array($cookie)) {
  9143. continue;
  9144. }
  9145. if (!isset($cookie['name'])) {
  9146. continue;
  9147. }
  9148. if ($newName != $cookie['name']) {
  9149. continue;
  9150. }
  9151. $newDomain = isset($newCookie['domain']) ? $newCookie['domain'] : 'NODOMAIN';
  9152. $domain = isset($cookie['domain']) ? $cookie['domain'] : 'NODOMAIN';
  9153. if ($newDomain != $domain) {
  9154. continue;
  9155. }
  9156. $newPath = isset($newCookie['path']) ? $newCookie['path'] : 'NOPATH';
  9157. $path = isset($cookie['path']) ? $cookie['path'] : 'NOPATH';
  9158. if ($newPath != $path) {
  9159. continue;
  9160. }
  9161. $this->cookies[$i] = $newCookie;
  9162. $found = true;
  9163. $this->debug('Update cookie ' . $newName . '=' . $newCookie['value']);
  9164. break;
  9165. }
  9166. if (! $found) {
  9167. $this->debug('Add cookie ' . $newName . '=' . $newCookie['value']);
  9168. $this->cookies[] = $newCookie;
  9169. }
  9170. }
  9171. return true;
  9172. }
  9173. }
  9174. if (!extension_loaded('soap')) {
  9175. /**
  9176. * For backwards compatiblity, define soapclient unless the PHP SOAP extension is loaded.
  9177. */
  9178. class soapclient extends nusoap_client {
  9179. }
  9180. }
  9181. class nusoapclient extends nusoap_client
  9182. {
  9183. }
  9184. ?>