Issues (4069)

Security Analysis    not enabled

This project does not seem to handle request data directly as such no vulnerable execution paths were found.

  Cross-Site Scripting
Cross-Site Scripting enables an attacker to inject code into the response of a web-request that is viewed by other users. It can for example be used to bypass access controls, or even to take over other users' accounts.
  File Exposure
File Exposure allows an attacker to gain access to local files that he should not be able to access. These files can for example include database credentials, or other configuration files.
  File Manipulation
File Manipulation enables an attacker to write custom data to files. This potentially leads to injection of arbitrary code on the server.
  Object Injection
Object Injection enables an attacker to inject an object into PHP code, and can lead to arbitrary code execution, file exposure, or file manipulation attacks.
  Code Injection
Code Injection enables an attacker to execute arbitrary code on the server.
  Response Splitting
Response Splitting can be used to send arbitrary responses.
  File Inclusion
File Inclusion enables an attacker to inject custom files into PHP's file loading mechanism, either explicitly passed to include, or for example via PHP's auto-loading mechanism.
  Command Injection
Command Injection enables an attacker to inject a shell command that is execute with the privileges of the web-server. This can be used to expose sensitive data, or gain access of your server.
  SQL Injection
SQL Injection enables an attacker to execute arbitrary SQL code on your database server gaining access to user data, or manipulating user data.
  XPath Injection
XPath Injection enables an attacker to modify the parts of XML document that are read. If that XML document is for example used for authentication, this can lead to further vulnerabilities similar to SQL Injection.
  LDAP Injection
LDAP Injection enables an attacker to inject LDAP statements potentially granting permission to run unauthorized queries, or modify content inside the LDAP tree.
  Header Injection
  Other Vulnerability
This category comprises other attack vectors such as manipulating the PHP runtime, loading custom extensions, freezing the runtime, or similar.
  Regex Injection
Regex Injection enables an attacker to execute arbitrary code in your PHP process.
  XML Injection
XML Injection enables an attacker to read files on your local filesystem including configuration files, or can be abused to freeze your web-server process.
  Variable Injection
Variable Injection enables an attacker to overwrite program variables with custom data, and can lead to further vulnerabilities.
Unfortunately, the security analysis is currently not available for your project. If you are a non-commercial open-source project, please contact support to gain access.

include/nusoap/nusoap.php (99 issues)

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

1
<?php
2
3
/*
4
Modification information for LGPL compliance
5
6
commit 76702f8945b5e4076d406d8e3388c23d7959a2e3
7
Author: Stanislav Malyshev <[email protected]>
8
Date:   Mon Nov 26 15:35:58 2012 -0800
9
10
    bug #50736 - fix proxy with different port
11
12
commit 70759790576f88f2b0480b50d35c95c84b9e6879
13
Author: Stanislav Malyshev <[email protected]>
14
Date:   Thu Feb 17 18:09:12 2011 -0800
15
16
    bug 34897 - remove characters that aren't valid in XML
17
18
commit 1767411d701b8216cc5e043888fd1337e2eca315
19
Author: Stanislav Malyshev <[email protected]>
20
Date:   Fri Jan 7 12:19:10 2011 -0800
21
22
    conserve memory when no debug is enabled
23
24
commit 843510ebf455368865302a05b9d5041815a32c23
25
Author: John Mertic <[email protected]>
26
Date:   Wed Nov 17 13:18:09 2010 -0500
27
28
    Bug 40716 - Fix WSDL validation problem by removing hardcoded schemaLocation attribute for the <xsd:import> tag.
29
30
commit 2bd12c02078f3e291bd9c1e76179a144c788ce97
31
Author: Collin Lee <[email protected]>
32
Date:   Fri Oct 22 16:37:42 2010 -0400
33
34
    Bug: 39937
35
36
    We traced the error to a combination of the new Hoovers' WSDL + the nusoapclient code that winds up improperly encoding the parameter elem
37
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
38
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
39
 and also re-enabled those for Hoovers that were marked skipped.
40
41
r58622 - 2010-10-22 18:18:59 -0700 (Fri, 22 Oct 2010) - engsvnbuild - Author: lam <[email protected]>
42
    bug 40066
43
44
r58361 - 2010-09-29 16:59:02 -0700 (Wed, 29 Sep 2010) - kjing - Author: Jenny Gonsalves <[email protected]>
45
    Merging with maint_6_0_1 (svn merge -r 58250:58342)
46
47
r57813 - 2010-08-19 10:34:44 -0700 (Thu, 19 Aug 2010) - kjing - Author: John Mertic <[email protected]>
48
    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.
49
50
r57707 - 2010-08-10 12:26:13 -0700 (Tue, 10 Aug 2010) - kjing - Author: Stanislav Malyshev <[email protected]>
51
    fix SOAP calls with no parameters
52
53
r56990 - 2010-06-16 13:05:36 -0700 (Wed, 16 Jun 2010) - kjing - snapshot "Mango" svn branch to a new one for GitHub sync
54
55
r56989 - 2010-06-16 13:01:33 -0700 (Wed, 16 Jun 2010) - kjing - defunt "Mango" svn dev branch before github cutover
56
57
r55980 - 2010-04-19 13:31:28 -0700 (Mon, 19 Apr 2010) - kjing - create Mango (6.1) based on windex
58
59
r51719 - 2009-10-22 10:18:00 -0700 (Thu, 22 Oct 2009) - mitani - Converted to Build 3  tags and updated the build system
60
61
r51634 - 2009-10-19 13:32:22 -0700 (Mon, 19 Oct 2009) - mitani - Windex is the branch for Sugar Sales 1.0 development
62
63
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.
64
65
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.
66
67
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:
68
- Changing all ereg function to either preg or simple string based ones
69
- No more references to magic quotes.
70
- Change all the session_unregister() functions to just unset() the correct session variable instead.
71
72
r50375 - 2009-08-24 18:07:43 -0700 (Mon, 24 Aug 2009) - dwong - branch kobe2 from tokyo r50372
73
74
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
75
76
r45680 - 2009-03-30 14:34:35 -0700 (Mon, 30 Mar 2009) - Samir Gandhi - modifeid serializeSchema to generate WS-I compliant WSDL
77
78
r42807 - 2008-12-29 11:16:59 -0800 (Mon, 29 Dec 2008) - dwong - Branch from trunk/sugarcrm r42806 to branches/tokyo/sugarcrm
79
80
r42645 - 2008-12-18 13:41:08 -0800 (Thu, 18 Dec 2008) - awu - merging maint_5_2_0 rev41336:HEAD to trunk
81
82
r41647 - 2008-11-11 17:44:30 -0800 (Tue, 11 Nov 2008) - majed - Fixes a few bugs
83
84
r41596 - 2008-11-10 19:20:04 -0800 (Mon, 10 Nov 2008) - Samir Gandhi - modified to set $method in the code
85
86
r41558 - 2008-11-10 14:35:34 -0800 (Mon, 10 Nov 2008) - majed - changes nusoap to allow for registering classes
87
88
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.
89
Touched:
90
- data/SugarBean.php
91
- include/domit/php_http_client_generic.php
92
- include/domit/php_http_connector.php
93
- include/domit/testing_domit.php
94
- include/domit/xml_domit_getelementsbypath.php
95
- include/domit/xml_domit_lite_parser.php
96
- include/domit/xml_domit_nodemaps.php
97
- include/domit/xml_domit_parser.php
98
- include/domit/xml_domit_shared.php
99
- include/generic/SugarWidgets/SugarWidgetField.php
100
- include/generic/SugarWidgets/SugarWidgetReportField.php
101
- include/ListView/ProcessView.php
102
- include/nusoap/class.soapclient.php
103
- include/nusoap/nusoap.php
104
- include/nusoap/nusoapmime.php
105
- include/Pear/HTML_Safe/Safe.php
106
- include/Pear/XML_HTMLSax3/HTMLSax3.php
107
- modules/Administration/RebuildWorkFlow.php
108
- modules/Expressions/RelateSelector.php
109
- modules/Reports/templates/templates_reports.php
110
- modules/WorkFlow/Delete.php
111
- modules/WorkFlow/Save.php
112
- modules/WorkFlow/SaveSequence.php
113
- modules/WorkFlow/WorkFlow.php
114
- modules/WorkFlowActionShells/CreateStep1.php
115
- modules/WorkFlowActionShells/CreateStep2.php
116
- modules/WorkFlowActionShells/Save.php
117
- modules/WorkFlowActionShells/WorkFlowActionShell.php
118
- modules/WorkFlowAlerts/Save.php
119
- modules/WorkFlowAlerts/WorkFlowAlert.php
120
- modules/WorkFlowAlertShells/DetailView.php
121
- modules/WorkFlowAlertShells/WorkFlowAlertShell.php
122
- modules/WorkFlowTriggerShells/CreateStep1.php
123
- modules/WorkFlowTriggerShells/CreateStepFilter.php
124
- modules/WorkFlowTriggerShells/SaveFilter.php
125
- modules/WorkFlowTriggerShells/WorkFlowTriggerShell.php
126
- soap/SoapHelperFunctions.php
127
- test/modules/DynamicFields/DynamicFields_Bug24095_test.php
128
- test/simpletest/browser.php
129
- test/simpletest/default_reporter.php
130
- test/simpletest/detached.php
131
- test/simpletest/eclipse.php
132
- test/simpletest/expectation.php
133
- test/simpletest/extensions/pear_test_case.php
134
- test/simpletest/form.php
135
- test/simpletest/http.php
136
- test/simpletest/mock_objects.php
137
- test/simpletest/page.php
138
- test/simpletest/parser.php
139
- test/simpletest/remote.php
140
- test/simpletest/shell_tester.php
141
- test/simpletest/simple_test.php
142
- test/simpletest/simpletest.php
143
- test/simpletest/test/acceptance_test.php
144
- test/simpletest/test/adapter_test.php
145
- test/simpletest/test/authentication_test.php
146
- test/simpletest/test/browser_test.php
147
- test/simpletest/test/collector_test.php
148
- test/simpletest/test/compatibility_test.php
149
- test/simpletest/test/detached_test.php
150
- test/simpletest/test/eclipse_test.php
151
- test/simpletest/test/encoding_test.php
152
- test/simpletest/test/errors_test.php
153
- test/simpletest/test/expectation_test.php
154
- test/simpletest/test/form_test.php
155
- test/simpletest/test/frames_test.php
156
- test/simpletest/test/http_test.php
157
- test/simpletest/test/live_test.php
158
- test/simpletest/test/mock_objects_test.php
159
- test/simpletest/test/page_test.php
160
- test/simpletest/test/parse_error_test.php
161
- test/simpletest/test/parser_test.php
162
- test/simpletest/test/remote_test.php
163
- test/simpletest/test/shell_test.php
164
- test/simpletest/test/shell_tester_test.php
165
- test/simpletest/test/simpletest_test.php
166
- test/simpletest/test/site/page_request.php
167
- test/simpletest/test/tag_test.php
168
- test/simpletest/test/unit_tester_test.php
169
- test/simpletest/test/user_agent_test.php
170
- test/simpletest/test/visual_test.php
171
- test/simpletest/test/xml_test.php
172
- test/simpletest/test_case.php
173
- test/simpletest/ui/array_reporter/test.php
174
- test/simpletest/ui/recorder/test.php
175
- test/simpletest/unit_tester.php
176
- test/simpletest/url.php
177
- test/simpletest/user_agent.php
178
- test/simpletest/web_tester.php
179
- test/spikephpcoverage/src/PEAR.php
180
- test/spikephpcoverage/src/util/Utility.php
181
- test/spikephpcoverage/src/XML/Parser.php
182
- test/spikephpcoverage/src/XML/Parser/Simple.php
183
- test/test_utilities/SugarTest_SimpleBrowser.php
184
185
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.
186
187
r38300 - 2008-07-25 13:33:43 -0700 (Fri, 25 Jul 2008) - Samir Gandhi - put the debug in parseresponse function
188
189
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
190
191
r36824 - 2008-06-18 09:26:11 -0700 (Wed, 18 Jun 2008) - roger - bug: 21832
192
193
r26422 - 2007-09-05 17:29:12 -0700 (Wed, 05 Sep 2007) - majed - migrate from beta 1 to trunk
194
195
r15787 - 2006-08-10 10:14:41 -0700 (Thu, 10 Aug 2006) - roger - RRS: bug 7961
196
197
r14701 - 2006-07-17 13:37:26 -0700 (Mon, 17 Jul 2006) - roger - RRS: bug 5801
198
199
r13782 - 2006-06-06 10:58:55 -0700 (Tue, 06 Jun 2006) - majed - changes entry point code
200
201
r11466 - 2006-02-01 15:49:47 -0800 (Wed, 01 Feb 2006) - jacob - Adding extra !empty check to get around a PHP warning.
202
203
r11115 - 2006-01-17 14:54:45 -0800 (Tue, 17 Jan 2006) - majed - add entry point validation
204
205
r10585 - 2005-12-13 14:42:26 -0800 (Tue, 13 Dec 2005) - majed - adds new license mechanisim
206
207
r10170 - 2005-12-05 18:37:46 -0800 (Mon, 05 Dec 2005) - majed - fixes various issues
208
209
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.
210
211
r8991 - 2005-11-03 19:07:25 -0800 (Thu, 03 Nov 2005) - majed - fixes nusoap issue
212
213
r8846 - 2005-10-31 11:01:12 -0800 (Mon, 31 Oct 2005) - majed - new version of nusoap
214
215
r7905 - 2005-09-21 19:12:57 -0700 (Wed, 21 Sep 2005) - majed - restores old nusoap pre & with a few fixes
216
217
r7861 - 2005-09-20 15:40:25 -0700 (Tue, 20 Sep 2005) - majed - & fix for 3.5.1
218
219
r7452 - 2005-08-17 11:32:34 -0700 (Wed, 17 Aug 2005) - majed - changes soap to nusoap
220
221
r5820 - 2005-06-21 14:22:24 -0700 (Tue, 21 Jun 2005) - majed - fixes issues with nusoap and with custom fields
222
223
r5462 - 2005-05-25 13:50:11 -0700 (Wed, 25 May 2005) - majed - upgraded nusoap to .6.9
224
225
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
226
227
r573 - 2004-09-04 13:03:32 -0700 (Sat, 04 Sep 2004) - sugarclint - undoing copyrights added in inadvertantly.  --clint
228
229
r546 - 2004-09-03 11:49:38 -0700 (Fri, 03 Sep 2004) - sugarmsi - removed echo count
230
231
r354 - 2004-08-02 23:00:37 -0700 (Mon, 02 Aug 2004) - sugarjacob - Adding Soap
232
233
234
*/
235
236
237
if(!defined('sugarEntry') || !sugarEntry) die('Not A Valid Entry Point');
238
239
/*
240
$Id: nusoap.php 58622 2010-10-23 01:18:59Z engsvnbuild $
241
242
NuSOAP - Web Services Toolkit for PHP
243
244
Copyright (c) 2002 NuSphere Corporation
245
246
This library is free software; you can redistribute it and/or
247
modify it under the terms of the GNU Lesser General Public
248
License as published by the Free Software Foundation; either
249
version 2.1 of the License, or (at your option) any later version.
250
n
251
This library is distributed in the hope that it will be useful,
252
but WITHOUT ANY WARRANTY; without even the implied warranty of
253
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
254
Lesser General Public License for more details.
255
256
You should have received a copy of the GNU Lesser General Public
257
License along with this library; if not, write to the Free Software
258
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
259
260
The NuSOAP project home is:
261
http://sourceforge.net/projects/nusoap/
262
263
The primary support for NuSOAP is the Help forum on the project home page.
264
265
If you have any questions or comments, please email:
266
267
Dietrich Ayala
268
[email protected]
269
http://dietrich.ganx4.com/nusoap
270
271
NuSphere Corporation
272
http://www.nusphere.com
273
274
*/
275
276
/*
277
 *	Some of the standards implmented in whole or part by NuSOAP:
278
 *
279
 *	SOAP 1.1 (http://www.w3.org/TR/2000/NOTE-SOAP-20000508/)
280
 *	WSDL 1.1 (http://www.w3.org/TR/2001/NOTE-wsdl-20010315)
281
 *	SOAP Messages With Attachments (http://www.w3.org/TR/SOAP-attachments)
282
 *	XML 1.0 (http://www.w3.org/TR/2006/REC-xml-20060816/)
283
 *	Namespaces in XML 1.0 (http://www.w3.org/TR/2006/REC-xml-names-20060816/)
284
 *	XML Schema 1.0 (http://www.w3.org/TR/xmlschema-0/)
285
 *	RFC 2045 Multipurpose Internet Mail Extensions (MIME) Part One: Format of Internet Message Bodies
286
 *	RFC 2068 Hypertext Transfer Protocol -- HTTP/1.1
287
 *	RFC 2617 HTTP Authentication: Basic and Digest Access Authentication
288
 */
289
290
/* load classes
291
292
// necessary classes
293
require_once('class.soapclient.php');
294
require_once('class.soap_val.php');
295
require_once('class.soap_parser.php');
296
require_once('class.soap_fault.php');
297
298
// transport classes
299
require_once('class.soap_transport_http.php');
300
301
// optional add-on classes
302
require_once('class.xmlschema.php');
303
require_once('class.wsdl.php');
304
305
// server class
306
require_once('class.soap_server.php');*/
307
308
// class variable emulation
309
// cf. http://www.webkreator.com/php/techniques/php-static-class-variables.html
310
$GLOBALS['_transient']['static']['nusoap_base']['globalDebugLevel'] = 0;
311
312
/**
313
*
314
* nusoap_base
315
*
316
* @author   Dietrich Ayala <[email protected]>
317
* @author   Scott Nichol <[email protected]>
318
319
* @access   public
320
*/
321
class nusoap_base {
0 ignored issues
show
Comprehensibility Best Practice introduced by
The type nusoap_base has been defined more than once; this definition is ignored, only the first definition in include/nusoap/class.nusoap_base.php (L135-940) is considered.

This check looks for classes that have been defined more than once.

If you can, we would recommend to use standard object-oriented programming techniques. For example, to avoid multiple types, it might make sense to create a common interface, and then multiple, different implementations for that interface.

This also has the side-effect of providing you with better IDE auto-completion, static analysis and also better OPCode caching from PHP.

Loading history...
322
	/**
323
	 * Identification for HTTP headers.
324
	 *
325
	 * @var string
326
	 * @access private
327
	 */
328
	var $title = 'NuSOAP';
329
	/**
330
	 * Version for HTTP headers.
331
	 *
332
	 * @var string
333
	 * @access private
334
	 */
335
	var $version = '0.9.5';
336
	/**
337
	 * CVS revision for HTTP headers.
338
	 *
339
	 * @var string
340
	 * @access private
341
	 */
342
	var $revision = '$Revision: 58622 $';
343
    /**
344
     * Current error string (manipulated by getError/setError)
345
	 *
346
	 * @var string
347
	 * @access private
348
	 */
349
	var $error_str = '';
350
    /**
351
     * Current debug string (manipulated by debug/appendDebug/clearDebug/getDebug/getDebugAsXMLComment)
352
	 *
353
	 * @var string
354
	 * @access private
355
	 */
356
    var $debug_str = '';
357
    /**
358
	 * toggles automatic encoding of special characters as entities
359
	 * (should always be true, I think)
360
	 *
361
	 * @var boolean
362
	 * @access private
363
	 */
364
	var $charencoding = true;
365
	/**
366
	 * the debug level for this instance
367
	 *
368
	 * @var	integer
369
	 * @access private
370
	 */
371
	var $debugLevel;
372
373
    /**
374
	* set schema version
375
	*
376
	* @var      string
377
	* @access   public
378
	*/
379
	var $XMLSchemaVersion = 'http://www.w3.org/2001/XMLSchema';
380
381
    /**
382
	* charset encoding for outgoing messages
383
	*
384
	* @var      string
385
	* @access   public
386
	*/
387
    //var $soap_defencoding = 'ISO-8859-1';
388
	var $soap_defencoding = 'UTF-8';
389
390
	/**
391
	* namespaces in an array of prefix => uri
392
	*
393
	* this is "seeded" by a set of constants, but it may be altered by code
394
	*
395
	* @var      array
396
	* @access   public
397
	*/
398
	var $namespaces = array(
399
		'SOAP-ENV' => 'http://schemas.xmlsoap.org/soap/envelope/',
400
		'xsd' => 'http://www.w3.org/2001/XMLSchema',
401
		'xsi' => 'http://www.w3.org/2001/XMLSchema-instance',
402
		'SOAP-ENC' => 'http://schemas.xmlsoap.org/soap/encoding/'
403
		);
404
405
	/**
406
	* namespaces used in the current context, e.g. during serialization
407
	*
408
	* @var      array
409
	* @access   private
410
	*/
411
	var $usedNamespaces = array();
412
413
	/**
414
	* XML Schema types in an array of uri => (array of xml type => php type)
415
	* is this legacy yet?
416
	* no, this is used by the nusoap_xmlschema class to verify type => namespace mappings.
417
	* @var      array
418
	* @access   public
419
	*/
420
	var $typemap = array(
421
	'http://www.w3.org/2001/XMLSchema' => array(
422
		'string'=>'string','boolean'=>'boolean','float'=>'double','double'=>'double','decimal'=>'double',
423
		'duration'=>'','dateTime'=>'string','time'=>'string','date'=>'string','gYearMonth'=>'',
424
		'gYear'=>'','gMonthDay'=>'','gDay'=>'','gMonth'=>'','hexBinary'=>'string','base64Binary'=>'string',
425
		// abstract "any" types
426
		'anyType'=>'string','anySimpleType'=>'string',
427
		// derived datatypes
428
		'normalizedString'=>'string','token'=>'string','language'=>'','NMTOKEN'=>'','NMTOKENS'=>'','Name'=>'','NCName'=>'','ID'=>'',
429
		'IDREF'=>'','IDREFS'=>'','ENTITY'=>'','ENTITIES'=>'','integer'=>'integer','nonPositiveInteger'=>'integer',
430
		'negativeInteger'=>'integer','long'=>'integer','int'=>'integer','short'=>'integer','byte'=>'integer','nonNegativeInteger'=>'integer',
431
		'unsignedLong'=>'','unsignedInt'=>'','unsignedShort'=>'','unsignedByte'=>'','positiveInteger'=>''),
432
	'http://www.w3.org/2000/10/XMLSchema' => array(
433
		'i4'=>'','int'=>'integer','boolean'=>'boolean','string'=>'string','double'=>'double',
434
		'float'=>'double','dateTime'=>'string',
435
		'timeInstant'=>'string','base64Binary'=>'string','base64'=>'string','ur-type'=>'array'),
436
	'http://www.w3.org/1999/XMLSchema' => array(
437
		'i4'=>'','int'=>'integer','boolean'=>'boolean','string'=>'string','double'=>'double',
438
		'float'=>'double','dateTime'=>'string',
439
		'timeInstant'=>'string','base64Binary'=>'string','base64'=>'string','ur-type'=>'array'),
440
	'http://soapinterop.org/xsd' => array('SOAPStruct'=>'struct'),
441
	'http://schemas.xmlsoap.org/soap/encoding/' => array('base64'=>'string','array'=>'array','Array'=>'array'),
442
    'http://xml.apache.org/xml-soap' => array('Map')
443
	);
444
445
	/**
446
	* XML entities to convert
447
	*
448
	* @var      array
449
	* @access   public
450
	* @deprecated
451
	* @see	expandEntities
452
	*/
453
	var $xmlEntities = array('quot' => '"','amp' => '&',
454
		'lt' => '<','gt' => '>','apos' => "'");
455
456
	/**
457
	 * Payload override
458
	 * This is to allows us to override the payload to resolve issues where we need to take
459
	 * control of the xml content
460
	 * @var string
461
	 * @access public
462
	 *
463
	 */
464
	var $payloadOverride;
465
466
	/**
467
	* constructor
468
	*
469
	* @access	public
470
	*/
471
	function nusoap_base() {
472
		$this->debugLevel = $GLOBALS['_transient']['static']['nusoap_base']['globalDebugLevel'];
473
	}
474
475
	/**
476
	* gets the global debug level, which applies to future instances
477
	*
478
	* @return	integer	Debug level 0-9, where 0 turns off
479
	* @access	public
480
	*/
481
	function getGlobalDebugLevel() {
482
		return $GLOBALS['_transient']['static']['nusoap_base']['globalDebugLevel'];
483
	}
484
485
	/**
486
	* sets the global debug level, which applies to future instances
487
	*
488
	* @param	int	$level	Debug level 0-9, where 0 turns off
489
	* @access	public
490
	*/
491
	function setGlobalDebugLevel($level) {
492
		$GLOBALS['_transient']['static']['nusoap_base']['globalDebugLevel'] = $level;
493
	}
494
495
	/**
496
	* gets the debug level for this instance
497
	*
498
	* @return	int	Debug level 0-9, where 0 turns off
499
	* @access	public
500
	*/
501
	function getDebugLevel() {
502
		return $this->debugLevel;
503
	}
504
505
	/**
506
	* sets the debug level for this instance
507
	*
508
	* @param	int	$level	Debug level 0-9, where 0 turns off
509
	* @access	public
510
	*/
511
	function setDebugLevel($level) {
512
		$this->debugLevel = $level;
513
	}
514
515
	/**
516
	* adds debug data to the instance debug string with formatting
517
	*
518
	* @param    string $string debug data
519
	* @access   private
520
	*/
521
	function debug($string){
522
		if ($this->debugLevel > 0) {
523
			$this->appendDebug($this->getmicrotime().' '.get_class($this).": $string\n");
524
		}
525
	}
526
527
	/**
528
	* adds debug data to the instance debug string without formatting
529
	*
530
	* @param    string $string debug data
531
	* @access   public
532
	*/
533
	function appendDebug($string){
534
		if ($this->debugLevel > 0) {
535
			// it would be nice to use a memory stream here to use
536
			// memory more efficiently
537
			$this->debug_str .= $string;
538
		}
539
	}
540
541
	/**
542
	* clears the current debug data for this instance
543
	*
544
	* @access   public
545
	*/
546
	function clearDebug() {
547
		// it would be nice to use a memory stream here to use
548
		// memory more efficiently
549
		$this->debug_str = '';
550
	}
551
552
	/**
553
	* gets the current debug data for this instance
554
	*
555
	* @return   debug data
556
	* @access   public
557
	*/
558
	function &getDebug() {
559
		// it would be nice to use a memory stream here to use
560
		// memory more efficiently
561
		return $this->debug_str;
562
	}
563
564
	/**
565
	* gets the current debug data for this instance as an XML comment
566
	* this may change the contents of the debug data
567
	*
568
	* @return   debug data as an XML comment
569
	* @access   public
570
	*/
571
	function &getDebugAsXMLComment() {
572
		// it would be nice to use a memory stream here to use
573
		// memory more efficiently
574
		while (strpos($this->debug_str, '--')) {
575
			$this->debug_str = str_replace('--', '- -', $this->debug_str);
576
		}
577
		$ret = "<!--\n" . $this->debug_str . "\n-->";
578
    	return $ret;
579
	}
580
581
	/**
582
	* expands entities, e.g. changes '<' to '&lt;'.
583
	*
584
	* @param	string	$val	The string in which to expand entities.
585
	* @access	private
586
	*/
587
	function expandEntities($val) {
588
		if ($this->charencoding) {
589
	    	$val = htmlspecialchars($val, ENT_QUOTES, $this->soap_defencoding);
590
	    	// XML 1.0 doesn't allow those...
591
	    	$val = preg_replace("/([\\x00-\\x08\\x0B\\x0C\\x0E-\\x1F])/", '', $val);
592
	    }
593
	    return $val;
594
	}
595
596
	/**
597
	* returns error string if present
598
	*
599
	* @return   mixed error string or false
600
	* @access   public
601
	*/
602
	function getError(){
603
		if($this->error_str != ''){
604
			return $this->error_str;
605
		}
606
		return false;
607
	}
608
609
	/**
610
	* sets error string
611
	*
612
	* @return   boolean $string error string
613
	* @access   private
614
	*/
615
	function setError($str){
616
		$this->error_str = $str;
617
	}
618
619
	/**
620
	* detect if array is a simple array or a struct (associative array)
621
	*
622
	* @param	mixed	$val	The PHP array
623
	* @return	string	(arraySimple|arrayStruct)
624
	* @access	private
625
	*/
626
	function isArraySimpleOrStruct($val) {
627
        $keyList = array_keys($val);
628
		foreach ($keyList as $keyListValue) {
629
			if (!is_int($keyListValue)) {
630
				return 'arrayStruct';
631
			}
632
		}
633
		return 'arraySimple';
634
	}
635
636
	/**
637
	* serializes PHP values in accordance w/ section 5. Type information is
638
	* not serialized if $use == 'literal'.
639
	*
640
	* @param	mixed	$val	The value to serialize
641
	* @param	string	$name	The name (local part) of the XML element
642
	* @param	string	$type	The XML schema type (local part) for the element
643
	* @param	string	$name_ns	The namespace for the name of the XML element
644
	* @param	string	$type_ns	The namespace for the type of the element
645
	* @param	array	$attributes	The attributes to serialize as name=>value pairs
646
	* @param	string	$use	The WSDL "use" (encoded|literal)
647
	* @param	boolean	$soapval	Whether this is called from soapval.
648
	* @return	string	The serialized element, possibly with child elements
649
    * @access	public
650
	*/
651
	function serialize_val($val,$name=false,$type=false,$name_ns=false,$type_ns=false,$attributes=false,$use='encoded',$soapval=false) {
652
		$this->debug("in serialize_val: name=$name, type=$type, name_ns=$name_ns, type_ns=$type_ns, use=$use, soapval=$soapval");
653
		$this->appendDebug('value=' . $this->varDump($val));
654
		$this->appendDebug('attributes=' . $this->varDump($attributes));
655
656
    	if (is_object($val) && get_class($val) == 'soapval' && (! $soapval)) {
657
    		$this->debug("serialize_val: serialize soapval");
658
        	$xml = $val->serialize($use);
659
			$this->appendDebug($val->getDebug());
660
			$val->clearDebug();
661
			$this->debug("serialize_val of soapval returning $xml");
662
			return $xml;
663
        }
664
		// force valid name if necessary
665
		if (is_numeric($name)) {
666
			$name = '__numeric_' . $name;
667
		} elseif (! $name) {
668
			$name = 'noname';
669
		}
670
		// if name has ns, add ns prefix to name
671
		$xmlns = '';
672
        if($name_ns){
673
			$prefix = 'nu'.rand(1000,9999);
674
			$name = $prefix.':'.$name;
675
			$xmlns .= " xmlns:$prefix=\"$name_ns\"";
676
		}
677
		// if type is prefixed, create type prefix
678
		if($type_ns != '' && $type_ns == $this->namespaces['xsd']){
679
			// need to fix this. shouldn't default to xsd if no ns specified
680
		    // w/o checking against typemap
681
			$type_prefix = 'xsd';
682
		} elseif($type_ns){
683
			$type_prefix = 'ns'.rand(1000,9999);
684
			$xmlns .= " xmlns:$type_prefix=\"$type_ns\"";
685
		}
686
		// serialize attributes if present
687
		$atts = '';
688
		if($attributes){
689
			foreach($attributes as $k => $v){
690
				$atts .= " $k=\"".$this->expandEntities($v).'"';
691
			}
692
		}
693
		// serialize null value
694
		if (is_null($val)) {
695
    		$this->debug("serialize_val: serialize null");
696
			if ($use == 'literal') {
697
				// TODO: depends on minOccurs
698
				$xml = "<$name$xmlns$atts/>";
699
				$this->debug("serialize_val returning $xml");
700
	        	return $xml;
701
        	} else {
702
				if (isset($type) && isset($type_prefix)) {
703
					$type_str = " xsi:type=\"$type_prefix:$type\"";
704
				} else {
705
					$type_str = '';
706
				}
707
				$xml = "<$name$xmlns$type_str$atts xsi:nil=\"true\"/>";
708
				$this->debug("serialize_val returning $xml");
709
	        	return $xml;
710
        	}
711
		}
712
        // serialize if an xsd built-in primitive type
713
        if($type != '' && isset($this->typemap[$this->XMLSchemaVersion][$type])){
714
    		$this->debug("serialize_val: serialize xsd built-in primitive type");
715
        	if (is_bool($val)) {
716
        		if ($type == 'boolean') {
717
	        		$val = $val ? 'true' : 'false';
718
	        	} elseif (! $val) {
719
	        		$val = 0;
720
	        	}
721
			} else if (is_string($val)) {
722
				$val = $this->expandEntities($val);
723
			}
724
			if ($use == 'literal') {
725
				$xml = "<$name$xmlns$atts>$val</$name>";
726
				$this->debug("serialize_val returning $xml");
727
	        	return $xml;
728
        	} else {
729
				$xml = "<$name$xmlns xsi:type=\"xsd:$type\"$atts>$val</$name>";
730
				$this->debug("serialize_val returning $xml");
731
	        	return $xml;
732
        	}
733
        }
734
		// detect type and serialize
735
		$xml = '';
736
		switch(true) {
737
			case (is_bool($val) || $type == 'boolean'):
738
		   		$this->debug("serialize_val: serialize boolean");
739
        		if ($type == 'boolean') {
740
	        		$val = $val ? 'true' : 'false';
741
	        	} elseif (! $val) {
742
	        		$val = 0;
743
	        	}
744
				if ($use == 'literal') {
745
					$xml .= "<$name$xmlns$atts>$val</$name>";
746
				} else {
747
					$xml .= "<$name$xmlns xsi:type=\"xsd:boolean\"$atts>$val</$name>";
748
				}
749
				break;
750
			case (is_int($val) || is_long($val) || $type == 'int'):
751
		   		$this->debug("serialize_val: serialize int");
752
				if ($use == 'literal') {
753
					$xml .= "<$name$xmlns$atts>$val</$name>";
754
				} else {
755
					$xml .= "<$name$xmlns xsi:type=\"xsd:int\"$atts>$val</$name>";
756
				}
757
				break;
758
			case (is_float($val)|| is_double($val) || $type == 'float'):
759
		   		$this->debug("serialize_val: serialize float");
760
				if ($use == 'literal') {
761
					$xml .= "<$name$xmlns$atts>$val</$name>";
762
				} else {
763
					$xml .= "<$name$xmlns xsi:type=\"xsd:float\"$atts>$val</$name>";
764
				}
765
				break;
766
			case (is_string($val) || $type == 'string'):
767
		   		$this->debug("serialize_val: serialize string");
768
				$val = $this->expandEntities($val);
0 ignored issues
show
It seems like $val can also be of type array or object; however, nusoap_base::expandEntities() does only seem to accept string, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
769
				if ($use == 'literal') {
770
					$xml .= "<$name$xmlns$atts>$val</$name>";
771
				} else {
772
					$xml .= "<$name$xmlns xsi:type=\"xsd:string\"$atts>$val</$name>";
773
				}
774
				break;
775
			case is_object($val):
776
		   		$this->debug("serialize_val: serialize object");
777
		    	if (get_class($val) == 'soapval') {
778
		    		$this->debug("serialize_val: serialize soapval object");
779
		        	$pXml = $val->serialize($use);
780
					$this->appendDebug($val->getDebug());
781
					$val->clearDebug();
782
		        } else {
783
					if (! $name) {
784
						$name = get_class($val);
785
						$this->debug("In serialize_val, used class name $name as element name");
786
					} else {
787
						$this->debug("In serialize_val, do not override name $name for element name for class " . get_class($val));
788
					}
789
					foreach(get_object_vars($val) as $k => $v){
790
						$pXml = isset($pXml) ? $pXml.$this->serialize_val($v,$k,false,false,false,false,$use) : $this->serialize_val($v,$k,false,false,false,false,$use);
791
					}
792
				}
793
				if(isset($type) && isset($type_prefix)){
794
					$type_str = " xsi:type=\"$type_prefix:$type\"";
795
				} else {
796
					$type_str = '';
797
				}
798
				if ($use == 'literal') {
799
					$xml .= "<$name$xmlns$atts>$pXml</$name>";
800
				} else {
801
					$xml .= "<$name$xmlns$type_str$atts>$pXml</$name>";
802
				}
803
				break;
804
			break;
0 ignored issues
show
break; does not seem to be reachable.

This check looks for unreachable code. It uses sophisticated control flow analysis techniques to find statements which will never be executed.

Unreachable code is most often the result of return, die or exit statements that have been added for debug purposes.

function fx() {
    try {
        doSomething();
        return true;
    }
    catch (\Exception $e) {
        return false;
    }

    return false;
}

In the above example, the last return false will never be executed, because a return statement has already been met in every possible execution path.

Loading history...
805
			case (is_array($val) || $type):
806
				// detect if struct or array
807
				$valueType = $this->isArraySimpleOrStruct($val);
808
                if($valueType=='arraySimple' || preg_match('/^ArrayOf/',$type)){
809
			   		$this->debug("serialize_val: serialize array");
810
					$i = 0;
811
					if(is_array($val) && count($val)> 0){
812
						foreach($val as $v){
813
	                    	if(is_object($v) && get_class($v) ==  'soapval'){
814
								$tt_ns = $v->type_ns;
815
								$tt = $v->type;
816
							} elseif (is_array($v)) {
817
								$tt = $this->isArraySimpleOrStruct($v);
818
							} else {
819
								$tt = gettype($v);
820
	                        }
821
							$array_types[$tt] = 1;
822
							// TODO: for literal, the name should be $name
823
							$xml .= $this->serialize_val($v,'item',false,false,false,false,$use);
824
							++$i;
825
						}
826
						if(count($array_types) > 1){
827
							$array_typename = 'xsd:anyType';
828
						} elseif(isset($tt) && isset($this->typemap[$this->XMLSchemaVersion][$tt])) {
829
							if ($tt == 'integer') {
830
								$tt = 'int';
831
							}
832
							$array_typename = 'xsd:'.$tt;
833
						} elseif(isset($tt) && $tt == 'arraySimple'){
834
							$array_typename = 'SOAP-ENC:Array';
835
						} elseif(isset($tt) && $tt == 'arrayStruct'){
836
							$array_typename = 'unnamed_struct_use_soapval';
837
						} else {
838
							// if type is prefixed, create type prefix
839
							if ($tt_ns != '' && $tt_ns == $this->namespaces['xsd']){
840
								 $array_typename = 'xsd:' . $tt;
841
							} elseif ($tt_ns) {
842
								$tt_prefix = 'ns' . rand(1000, 9999);
843
								$array_typename = "$tt_prefix:$tt";
844
								$xmlns .= " xmlns:$tt_prefix=\"$tt_ns\"";
845
							} else {
846
								$array_typename = $tt;
847
							}
848
						}
849
						$array_type = $i;
850
						if ($use == 'literal') {
851
							$type_str = '';
852
						} else if (isset($type) && isset($type_prefix)) {
853
							$type_str = " xsi:type=\"$type_prefix:$type\"";
854
						} else {
855
							$type_str = " xsi:type=\"SOAP-ENC:Array\" SOAP-ENC:arrayType=\"".$array_typename."[$array_type]\"";
856
						}
857
					// empty array
858
					} else {
859
						if ($use == 'literal') {
860
							$type_str = '';
861
						} else if (isset($type) && isset($type_prefix)) {
862
							$type_str = " xsi:type=\"$type_prefix:$type\"";
863
						} else {
864
							$type_str = " xsi:type=\"SOAP-ENC:Array\" SOAP-ENC:arrayType=\"xsd:anyType[0]\"";
865
						}
866
					}
867
					// TODO: for array in literal, there is no wrapper here
868
					$xml = "<$name$xmlns$type_str$atts>".$xml."</$name>";
869
				} else {
870
					// got a struct
871
			   		$this->debug("serialize_val: serialize struct");
872
					if(isset($type) && isset($type_prefix)){
873
						$type_str = " xsi:type=\"$type_prefix:$type\"";
874
					} else {
875
						$type_str = '';
876
					}
877
					if ($use == 'literal') {
878
						$xml .= "<$name$xmlns$atts>";
879
					} else {
880
						$xml .= "<$name$xmlns$type_str$atts>";
881
					}
882
					foreach($val as $k => $v){
883
						// Apache Map
884
						if ($type == 'Map' && $type_ns == 'http://xml.apache.org/xml-soap') {
885
							$xml .= '<item>';
886
							$xml .= $this->serialize_val($k,'key',false,false,false,false,$use);
887
							$xml .= $this->serialize_val($v,'value',false,false,false,false,$use);
888
							$xml .= '</item>';
889
						} else {
890
							$xml .= $this->serialize_val($v,$k,false,false,false,false,$use);
891
						}
892
					}
893
					$xml .= "</$name>";
894
				}
895
				break;
896
			default:
897
		   		$this->debug("serialize_val: serialize unknown");
898
				$xml .= 'not detected, got '.gettype($val).' for '.$val;
899
				break;
900
		}
901
		$this->debug("serialize_val returning $xml");
902
		return $xml;
903
	}
904
905
    /**
906
    * serializes a message
907
    *
908
    * @param string $body the XML of the SOAP body
909
    * @param mixed $headers optional string of XML with SOAP header content, or array of soapval objects for SOAP headers, or associative array
910
    * @param array $namespaces optional the namespaces used in generating the body and headers
911
    * @param string $style optional (rpc|document)
912
    * @param string $use optional (encoded|literal)
913
    * @param string $encodingStyle optional (usually 'http://schemas.xmlsoap.org/soap/encoding/' for encoded)
914
    * @return string the message
915
    * @access public
916
    */
917
    function serializeEnvelope($body,$headers=false,$namespaces=array(),$style='rpc',$use='encoded',$encodingStyle='http://schemas.xmlsoap.org/soap/encoding/'){
918
    // TODO: add an option to automatically run utf8_encode on $body and $headers
919
    // if $this->soap_defencoding is UTF-8.  Not doing this automatically allows
920
    // one to send arbitrary UTF-8 characters, not just characters that map to ISO-8859-1
921
922
	$this->debug("In serializeEnvelope length=" . strlen($body) . " body (max 1000 characters)=" . substr($body, 0, 1000) . " style=$style use=$use encodingStyle=$encodingStyle");
923
	$this->debug("headers:");
924
	$this->appendDebug($this->varDump($headers));
925
	$this->debug("namespaces:");
926
	$this->appendDebug($this->varDump($namespaces));
927
928
	// serialize namespaces
929
    $ns_string = '';
930
	foreach(array_merge($this->namespaces,$namespaces) as $k => $v){
931
		$ns_string .= " xmlns:$k=\"$v\"";
932
	}
933
	if($encodingStyle) {
934
		$ns_string = " SOAP-ENV:encodingStyle=\"$encodingStyle\"$ns_string";
935
	}
936
937
	// serialize headers
938
	if($headers){
939
		if (is_array($headers)) {
940
			$xml = '';
941
			foreach ($headers as $k => $v) {
942
				if (is_object($v) && get_class($v) == 'soapval') {
943
					$xml .= $this->serialize_val($v, false, false, false, false, false, $use);
944
				} else {
945
					$xml .= $this->serialize_val($v, $k, false, false, false, false, $use);
946
				}
947
			}
948
			$headers = $xml;
949
			$this->debug("In serializeEnvelope, serialized array of headers to $headers");
950
		}
951
		$headers = "<SOAP-ENV:Header>".$headers."</SOAP-ENV:Header>";
952
	}
953
	// serialize envelope
954
	return
955
	'<?xml version="1.0" encoding="'.$this->soap_defencoding .'"?'.">".
956
	'<SOAP-ENV:Envelope'.$ns_string.">".
957
	$headers.
958
	"<SOAP-ENV:Body>".
959
		$body.
960
	"</SOAP-ENV:Body>".
961
	"</SOAP-ENV:Envelope>";
962
    }
963
964
	/**
965
	 * formats a string to be inserted into an HTML stream
966
	 *
967
	 * @param string $str The string to format
968
	 * @return string The formatted string
969
	 * @access public
970
	 * @deprecated
971
	 */
972
    function formatDump($str){
973
		$str = htmlspecialchars($str);
974
		return nl2br($str);
975
    }
976
977
	/**
978
	* contracts (changes namespace to prefix) a qualified name
979
	*
980
	* @param    string $qname qname
981
	* @return	string contracted qname
982
	* @access   private
983
	*/
984
	function contractQname($qname){
985
		// get element namespace
986
		//$this->xdebug("Contract $qname");
987
		if (strrpos($qname, ':')) {
988
			// get unqualified name
989
			$name = substr($qname, strrpos($qname, ':') + 1);
990
			// get ns
991
			$ns = substr($qname, 0, strrpos($qname, ':'));
992
			$p = $this->getPrefixFromNamespace($ns);
993
			if ($p) {
994
				return $p . ':' . $name;
995
			}
996
			return $qname;
997
		} else {
998
			return $qname;
999
		}
1000
	}
1001
1002
	/**
1003
	* expands (changes prefix to namespace) a qualified name
1004
	*
1005
	* @param    string $qname qname
1006
	* @return	string expanded qname
1007
	* @access   private
1008
	*/
1009
	function expandQname($qname){
1010
		// get element prefix
1011
		if(strpos($qname,':') && !preg_match('/^http:\/\//',$qname)){
1012
			// get unqualified name
1013
			$name = substr(strstr($qname,':'),1);
1014
			// get ns prefix
1015
			$prefix = substr($qname,0,strpos($qname,':'));
1016
			if(isset($this->namespaces[$prefix])){
1017
				return $this->namespaces[$prefix].':'.$name;
1018
			} else {
1019
				return $qname;
1020
			}
1021
		} else {
1022
			return $qname;
1023
		}
1024
	}
1025
1026
    /**
1027
    * returns the local part of a prefixed string
1028
    * returns the original string, if not prefixed
1029
    *
1030
    * @param string $str The prefixed string
1031
    * @return string The local part
1032
    * @access public
1033
    */
1034
	function getLocalPart($str){
1035
		if($sstr = strrchr($str,':')){
1036
			// get unqualified name
1037
			return substr( $sstr, 1 );
1038
		} else {
1039
			return $str;
1040
		}
1041
	}
1042
1043
	/**
1044
    * returns the prefix part of a prefixed string
1045
    * returns false, if not prefixed
1046
    *
1047
    * @param string $str The prefixed string
1048
    * @return mixed The prefix or false if there is no prefix
1049
    * @access public
1050
    */
1051
	function getPrefix($str){
1052
		if($pos = strrpos($str,':')){
1053
			// get prefix
1054
			return substr($str,0,$pos);
1055
		}
1056
		return false;
1057
	}
1058
1059
	/**
1060
    * pass it a prefix, it returns a namespace
1061
    *
1062
    * @param string $prefix The prefix
1063
    * @return mixed The namespace, false if no namespace has the specified prefix
1064
    * @access public
1065
    */
1066
	function getNamespaceFromPrefix($prefix){
1067
		if (isset($this->namespaces[$prefix])) {
1068
			return $this->namespaces[$prefix];
1069
		}
1070
		//$this->setError("No namespace registered for prefix '$prefix'");
1071
		return false;
1072
	}
1073
1074
	/**
1075
    * returns the prefix for a given namespace (or prefix)
1076
    * or false if no prefixes registered for the given namespace
1077
    *
1078
    * @param string $ns The namespace
1079
    * @return mixed The prefix, false if the namespace has no prefixes
1080
    * @access public
1081
    */
1082
	function getPrefixFromNamespace($ns) {
1083
		foreach ($this->namespaces as $p => $n) {
1084
			if ($ns == $n || $ns == $p) {
1085
			    $this->usedNamespaces[$p] = $n;
1086
				return $p;
1087
			}
1088
		}
1089
		return false;
1090
	}
1091
1092
	/**
1093
    * returns the time in ODBC canonical form with microseconds
1094
    *
1095
    * @return string The time in ODBC canonical form with microseconds
1096
    * @access public
1097
    */
1098
	function getmicrotime() {
1099
		if (function_exists('gettimeofday')) {
1100
			$tod = gettimeofday();
1101
			$sec = $tod['sec'];
1102
			$usec = $tod['usec'];
1103
		} else {
1104
			$sec = time();
1105
			$usec = 0;
1106
		}
1107
		return strftime('%Y-%m-%d %H:%M:%S', $sec) . '.' . sprintf('%06d', $usec);
1108
	}
1109
1110
	/**
1111
	 * Returns a string with the output of var_dump
1112
	 *
1113
	 * @param mixed $data The variable to var_dump
1114
	 * @return string The output of var_dump
1115
	 * @access public
1116
	 */
1117
    function varDump($data) {
1118
        if ($this->debugLevel <= 0) {
1119
            return '';
1120
        }
1121
        ob_start();
1122
		var_dump($data);
0 ignored issues
show
Security Debugging Code introduced by
var_dump($data); looks like debug code. Are you sure you do not want to remove it? This might expose sensitive data.
Loading history...
1123
		$ret_val = ob_get_contents();
1124
		ob_end_clean();
1125
		return $ret_val;
1126
	}
1127
1128
	/**
1129
	* represents the object as a string
1130
	*
1131
	* @return	string
1132
	* @access   public
1133
	*/
1134
	function __toString() {
1135
		return $this->varDump($this);
1136
	}
1137
}
1138
1139
// XML Schema Datatype Helper Functions
1140
1141
//xsd:dateTime helpers
1142
1143
/**
1144
* convert unix timestamp to ISO 8601 compliant date string
1145
*
1146
* @param    int $timestamp Unix time stamp
1147
* @param	boolean $utc Whether the time stamp is UTC or local
1148
* @return	mixed ISO 8601 date string or false
1149
* @access   public
1150
*/
1151
function timestamp_to_iso8601($timestamp,$utc=true){
0 ignored issues
show
The function timestamp_to_iso8601() has been defined more than once; this definition is ignored, only the first definition in include/nusoap/class.nusoap_base.php (L954-984) is considered.

This check looks for functions that have already been defined in other files.

Some Codebases, like WordPress, make a practice of defining functions multiple times. This may lead to problems with the detection of function parameters and types. If you really need to do this, you can mark the duplicate definition with the @ignore annotation.

/**
 * @ignore
 */
function getUser() {

}

function getUser($id, $realm) {

}

See also the PhpDoc documentation for @ignore.

Loading history...
1152
	$datestr = date('Y-m-d\TH:i:sO',$timestamp);
1153
	$pos = strrpos($datestr, "+");
1154
	if ($pos === FALSE) {
1155
		$pos = strrpos($datestr, "-");
1156
	}
1157
	if ($pos !== FALSE) {
1158
		if (strlen($datestr) == $pos + 5) {
1159
			$datestr = substr($datestr, 0, $pos + 3) . ':' . substr($datestr, -2);
1160
		}
1161
	}
1162
	if($utc){
1163
		$pattern = '/'.
1164
		'([0-9]{4})-'.	// centuries & years CCYY-
1165
		'([0-9]{2})-'.	// months MM-
1166
		'([0-9]{2})'.	// days DD
1167
		'T'.			// separator T
1168
		'([0-9]{2}):'.	// hours hh:
1169
		'([0-9]{2}):'.	// minutes mm:
1170
		'([0-9]{2})(\.[0-9]*)?'. // seconds ss.ss...
1171
		'(Z|[+\-][0-9]{2}:?[0-9]{2})?'. // Z to indicate UTC, -/+HH:MM:SS.SS... for local tz's
1172
		'/';
1173
1174
		if(preg_match($pattern,$datestr,$regs)){
1175
			return sprintf('%04d-%02d-%02dT%02d:%02d:%02dZ',$regs[1],$regs[2],$regs[3],$regs[4],$regs[5],$regs[6]);
1176
		}
1177
		return false;
1178
	} else {
1179
		return $datestr;
1180
	}
1181
}
1182
1183
/**
1184
* convert ISO 8601 compliant date string to unix timestamp
1185
*
1186
* @param    string $datestr ISO 8601 compliant date string
1187
* @return	mixed Unix timestamp (int) or false
1188
* @access   public
1189
*/
1190
function iso8601_to_timestamp($datestr){
0 ignored issues
show
The function iso8601_to_timestamp() has been defined more than once; this definition is ignored, only the first definition in include/nusoap/class.nusoap_base.php (L993-1023) is considered.

This check looks for functions that have already been defined in other files.

Some Codebases, like WordPress, make a practice of defining functions multiple times. This may lead to problems with the detection of function parameters and types. If you really need to do this, you can mark the duplicate definition with the @ignore annotation.

/**
 * @ignore
 */
function getUser() {

}

function getUser($id, $realm) {

}

See also the PhpDoc documentation for @ignore.

Loading history...
1191
	$pattern = '/'.
1192
	'([0-9]{4})-'.	// centuries & years CCYY-
1193
	'([0-9]{2})-'.	// months MM-
1194
	'([0-9]{2})'.	// days DD
1195
	'T'.			// separator T
1196
	'([0-9]{2}):'.	// hours hh:
1197
	'([0-9]{2}):'.	// minutes mm:
1198
	'([0-9]{2})(\.[0-9]+)?'. // seconds ss.ss...
1199
	'(Z|[+\-][0-9]{2}:?[0-9]{2})?'. // Z to indicate UTC, -/+HH:MM:SS.SS... for local tz's
1200
	'/';
1201
	if(preg_match($pattern,$datestr,$regs)){
1202
		// not utc
1203
		if($regs[8] != 'Z'){
1204
			$op = substr($regs[8],0,1);
1205
			$h = substr($regs[8],1,2);
1206
			$m = substr($regs[8],strlen($regs[8])-2,2);
1207
			if($op == '-'){
1208
				$regs[4] = $regs[4] + $h;
1209
				$regs[5] = $regs[5] + $m;
1210
			} elseif($op == '+'){
1211
				$regs[4] = $regs[4] - $h;
1212
				$regs[5] = $regs[5] - $m;
1213
			}
1214
		}
1215
		return gmmktime($regs[4], $regs[5], $regs[6], $regs[2], $regs[3], $regs[1]);
1216
//		return strtotime("$regs[1]-$regs[2]-$regs[3] $regs[4]:$regs[5]:$regs[6]Z");
1217
	} else {
1218
		return false;
1219
	}
1220
}
1221
1222
/**
1223
* sleeps some number of microseconds
1224
*
1225
* @param    string $usec the number of microseconds to sleep
1226
* @access   public
1227
* @deprecated
1228
*/
1229
function usleepWindows($usec)
0 ignored issues
show
The function usleepWindows() has been defined more than once; this definition is ignored, only the first definition in include/nusoap/class.nusoap_base.php (L1032-1043) is considered.

This check looks for functions that have already been defined in other files.

Some Codebases, like WordPress, make a practice of defining functions multiple times. This may lead to problems with the detection of function parameters and types. If you really need to do this, you can mark the duplicate definition with the @ignore annotation.

/**
 * @ignore
 */
function getUser() {

}

function getUser($id, $realm) {

}

See also the PhpDoc documentation for @ignore.

Loading history...
1230
{
1231
	$start = gettimeofday();
1232
1233
	do
1234
	{
1235
		$stop = gettimeofday();
1236
		$timePassed = 1000000 * ($stop['sec'] - $start['sec'])
1237
		+ $stop['usec'] - $start['usec'];
1238
	}
1239
	while ($timePassed < $usec);
1240
}
1241
1242
?><?php
1243
1244
/*
1245
1246
Modification information for LGPL compliance
1247
1248
r58622 - 2010-10-22 18:18:59 -0700 (Fri, 22 Oct 2010) - engsvnbuild - Author: lam <[email protected]>
1249
    bug 40066
1250
1251
r58361 - 2010-09-29 16:59:02 -0700 (Wed, 29 Sep 2010) - kjing - Author: Jenny Gonsalves <[email protected]>
1252
    Merging with maint_6_0_1 (svn merge -r 58250:58342)
1253
1254
r57813 - 2010-08-19 10:34:44 -0700 (Thu, 19 Aug 2010) - kjing - Author: John Mertic <[email protected]>
1255
    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.
1256
1257
r57707 - 2010-08-10 12:26:13 -0700 (Tue, 10 Aug 2010) - kjing - Author: Stanislav Malyshev <[email protected]>
1258
    fix SOAP calls with no parameters
1259
1260
r56990 - 2010-06-16 13:05:36 -0700 (Wed, 16 Jun 2010) - kjing - snapshot "Mango" svn branch to a new one for GitHub sync
1261
1262
r56989 - 2010-06-16 13:01:33 -0700 (Wed, 16 Jun 2010) - kjing - defunt "Mango" svn dev branch before github cutover
1263
1264
r55980 - 2010-04-19 13:31:28 -0700 (Mon, 19 Apr 2010) - kjing - create Mango (6.1) based on windex
1265
1266
r51719 - 2009-10-22 10:18:00 -0700 (Thu, 22 Oct 2009) - mitani - Converted to Build 3  tags and updated the build system
1267
1268
r51634 - 2009-10-19 13:32:22 -0700 (Mon, 19 Oct 2009) - mitani - Windex is the branch for Sugar Sales 1.0 development
1269
1270
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.
1271
1272
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.
1273
1274
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:
1275
- Changing all ereg function to either preg or simple string based ones
1276
- No more references to magic quotes.
1277
- Change all the session_unregister() functions to just unset() the correct session variable instead.
1278
1279
r50375 - 2009-08-24 18:07:43 -0700 (Mon, 24 Aug 2009) - dwong - branch kobe2 from tokyo r50372
1280
1281
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
1282
1283
r45680 - 2009-03-30 14:34:35 -0700 (Mon, 30 Mar 2009) - Samir Gandhi - modifeid serializeSchema to generate WS-I compliant WSDL
1284
1285
r42807 - 2008-12-29 11:16:59 -0800 (Mon, 29 Dec 2008) - dwong - Branch from trunk/sugarcrm r42806 to branches/tokyo/sugarcrm
1286
1287
r42645 - 2008-12-18 13:41:08 -0800 (Thu, 18 Dec 2008) - awu - merging maint_5_2_0 rev41336:HEAD to trunk
1288
1289
r41647 - 2008-11-11 17:44:30 -0800 (Tue, 11 Nov 2008) - majed - Fixes a few bugs
1290
1291
r41596 - 2008-11-10 19:20:04 -0800 (Mon, 10 Nov 2008) - Samir Gandhi - modified to set $method in the code
1292
1293
r41558 - 2008-11-10 14:35:34 -0800 (Mon, 10 Nov 2008) - majed - changes nusoap to allow for registering classes
1294
1295
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.
1296
Touched:
1297
- data/SugarBean.php
1298
- include/domit/php_http_client_generic.php
1299
- include/domit/php_http_connector.php
1300
- include/domit/testing_domit.php
1301
- include/domit/xml_domit_getelementsbypath.php
1302
- include/domit/xml_domit_lite_parser.php
1303
- include/domit/xml_domit_nodemaps.php
1304
- include/domit/xml_domit_parser.php
1305
- include/domit/xml_domit_shared.php
1306
- include/generic/SugarWidgets/SugarWidgetField.php
1307
- include/generic/SugarWidgets/SugarWidgetReportField.php
1308
- include/ListView/ProcessView.php
1309
- include/nusoap/class.soapclient.php
1310
- include/nusoap/nusoap.php
1311
- include/nusoap/nusoapmime.php
1312
- include/Pear/HTML_Safe/Safe.php
1313
- include/Pear/XML_HTMLSax3/HTMLSax3.php
1314
- modules/Administration/RebuildWorkFlow.php
1315
- modules/Expressions/RelateSelector.php
1316
- modules/Reports/templates/templates_reports.php
1317
- modules/WorkFlow/Delete.php
1318
- modules/WorkFlow/Save.php
1319
- modules/WorkFlow/SaveSequence.php
1320
- modules/WorkFlow/WorkFlow.php
1321
- modules/WorkFlowActionShells/CreateStep1.php
1322
- modules/WorkFlowActionShells/CreateStep2.php
1323
- modules/WorkFlowActionShells/Save.php
1324
- modules/WorkFlowActionShells/WorkFlowActionShell.php
1325
- modules/WorkFlowAlerts/Save.php
1326
- modules/WorkFlowAlerts/WorkFlowAlert.php
1327
- modules/WorkFlowAlertShells/DetailView.php
1328
- modules/WorkFlowAlertShells/WorkFlowAlertShell.php
1329
- modules/WorkFlowTriggerShells/CreateStep1.php
1330
- modules/WorkFlowTriggerShells/CreateStepFilter.php
1331
- modules/WorkFlowTriggerShells/SaveFilter.php
1332
- modules/WorkFlowTriggerShells/WorkFlowTriggerShell.php
1333
- soap/SoapHelperFunctions.php
1334
- test/modules/DynamicFields/DynamicFields_Bug24095_test.php
1335
- test/simpletest/browser.php
1336
- test/simpletest/default_reporter.php
1337
- test/simpletest/detached.php
1338
- test/simpletest/eclipse.php
1339
- test/simpletest/expectation.php
1340
- test/simpletest/extensions/pear_test_case.php
1341
- test/simpletest/form.php
1342
- test/simpletest/http.php
1343
- test/simpletest/mock_objects.php
1344
- test/simpletest/page.php
1345
- test/simpletest/parser.php
1346
- test/simpletest/remote.php
1347
- test/simpletest/shell_tester.php
1348
- test/simpletest/simple_test.php
1349
- test/simpletest/simpletest.php
1350
- test/simpletest/test/acceptance_test.php
1351
- test/simpletest/test/adapter_test.php
1352
- test/simpletest/test/authentication_test.php
1353
- test/simpletest/test/browser_test.php
1354
- test/simpletest/test/collector_test.php
1355
- test/simpletest/test/compatibility_test.php
1356
- test/simpletest/test/detached_test.php
1357
- test/simpletest/test/eclipse_test.php
1358
- test/simpletest/test/encoding_test.php
1359
- test/simpletest/test/errors_test.php
1360
- test/simpletest/test/expectation_test.php
1361
- test/simpletest/test/form_test.php
1362
- test/simpletest/test/frames_test.php
1363
- test/simpletest/test/http_test.php
1364
- test/simpletest/test/live_test.php
1365
- test/simpletest/test/mock_objects_test.php
1366
- test/simpletest/test/page_test.php
1367
- test/simpletest/test/parse_error_test.php
1368
- test/simpletest/test/parser_test.php
1369
- test/simpletest/test/remote_test.php
1370
- test/simpletest/test/shell_test.php
1371
- test/simpletest/test/shell_tester_test.php
1372
- test/simpletest/test/simpletest_test.php
1373
- test/simpletest/test/site/page_request.php
1374
- test/simpletest/test/tag_test.php
1375
- test/simpletest/test/unit_tester_test.php
1376
- test/simpletest/test/user_agent_test.php
1377
- test/simpletest/test/visual_test.php
1378
- test/simpletest/test/xml_test.php
1379
- test/simpletest/test_case.php
1380
- test/simpletest/ui/array_reporter/test.php
1381
- test/simpletest/ui/recorder/test.php
1382
- test/simpletest/unit_tester.php
1383
- test/simpletest/url.php
1384
- test/simpletest/user_agent.php
1385
- test/simpletest/web_tester.php
1386
- test/spikephpcoverage/src/PEAR.php
1387
- test/spikephpcoverage/src/util/Utility.php
1388
- test/spikephpcoverage/src/XML/Parser.php
1389
- test/spikephpcoverage/src/XML/Parser/Simple.php
1390
- test/test_utilities/SugarTest_SimpleBrowser.php
1391
1392
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.
1393
1394
r38300 - 2008-07-25 13:33:43 -0700 (Fri, 25 Jul 2008) - Samir Gandhi - put the debug in parseresponse function
1395
1396
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
1397
1398
r36824 - 2008-06-18 09:26:11 -0700 (Wed, 18 Jun 2008) - roger - bug: 21832
1399
1400
r26422 - 2007-09-05 17:29:12 -0700 (Wed, 05 Sep 2007) - majed - migrate from beta 1 to trunk
1401
1402
r15787 - 2006-08-10 10:14:41 -0700 (Thu, 10 Aug 2006) - roger - RRS: bug 7961
1403
1404
r14701 - 2006-07-17 13:37:26 -0700 (Mon, 17 Jul 2006) - roger - RRS: bug 5801
1405
1406
r13782 - 2006-06-06 10:58:55 -0700 (Tue, 06 Jun 2006) - majed - changes entry point code
1407
1408
r11466 - 2006-02-01 15:49:47 -0800 (Wed, 01 Feb 2006) - jacob - Adding extra !empty check to get around a PHP warning.
1409
1410
r11115 - 2006-01-17 14:54:45 -0800 (Tue, 17 Jan 2006) - majed - add entry point validation
1411
1412
r10585 - 2005-12-13 14:42:26 -0800 (Tue, 13 Dec 2005) - majed - adds new license mechanisim
1413
1414
r10170 - 2005-12-05 18:37:46 -0800 (Mon, 05 Dec 2005) - majed - fixes various issues
1415
1416
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.
1417
1418
r8991 - 2005-11-03 19:07:25 -0800 (Thu, 03 Nov 2005) - majed - fixes nusoap issue
1419
1420
r8846 - 2005-10-31 11:01:12 -0800 (Mon, 31 Oct 2005) - majed - new version of nusoap
1421
1422
r7905 - 2005-09-21 19:12:57 -0700 (Wed, 21 Sep 2005) - majed - restores old nusoap pre & with a few fixes
1423
1424
r7861 - 2005-09-20 15:40:25 -0700 (Tue, 20 Sep 2005) - majed - & fix for 3.5.1
1425
1426
r7452 - 2005-08-17 11:32:34 -0700 (Wed, 17 Aug 2005) - majed - changes soap to nusoap
1427
1428
r5820 - 2005-06-21 14:22:24 -0700 (Tue, 21 Jun 2005) - majed - fixes issues with nusoap and with custom fields
1429
1430
r5462 - 2005-05-25 13:50:11 -0700 (Wed, 25 May 2005) - majed - upgraded nusoap to .6.9
1431
1432
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
1433
1434
r573 - 2004-09-04 13:03:32 -0700 (Sat, 04 Sep 2004) - sugarclint - undoing copyrights added in inadvertantly.  --clint
1435
1436
r546 - 2004-09-03 11:49:38 -0700 (Fri, 03 Sep 2004) - sugarmsi - removed echo count
1437
1438
r354 - 2004-08-02 23:00:37 -0700 (Mon, 02 Aug 2004) - sugarjacob - Adding Soap
1439
1440
1441
*/
1442
1443
1444
1445
1446
1447
/**
1448
* Contains information for a SOAP fault.
1449
* Mainly used for returning faults from deployed functions
1450
* in a server instance.
1451
* @author   Dietrich Ayala <[email protected]>
1452
1453
* @access public
1454
*/
1455
class nusoap_fault extends nusoap_base {
0 ignored issues
show
Comprehensibility Best Practice introduced by
The type nusoap_fault has been defined more than once; this definition is ignored, only the first definition in include/nusoap/class.soap_fault.php (L55-122) is considered.

This check looks for classes that have been defined more than once.

If you can, we would recommend to use standard object-oriented programming techniques. For example, to avoid multiple types, it might make sense to create a common interface, and then multiple, different implementations for that interface.

This also has the side-effect of providing you with better IDE auto-completion, static analysis and also better OPCode caching from PHP.

Loading history...
Coding Style Compatibility introduced by
PSR1 recommends that each class should be in its own file to aid autoloaders.

Having each class in a dedicated file usually plays nice with PSR autoloaders and is therefore a well established practice. If you use other autoloaders, you might not want to follow this rule.

Loading history...
1456
	/**
1457
	 * The fault code (client|server)
1458
	 * @var string
1459
	 * @access private
1460
	 */
1461
	var $faultcode;
1462
	/**
1463
	 * The fault actor
1464
	 * @var string
1465
	 * @access private
1466
	 */
1467
	var $faultactor;
1468
	/**
1469
	 * The fault string, a description of the fault
1470
	 * @var string
1471
	 * @access private
1472
	 */
1473
	var $faultstring;
1474
	/**
1475
	 * The fault detail, typically a string or array of string
1476
	 * @var mixed
1477
	 * @access private
1478
	 */
1479
	var $faultdetail;
1480
1481
	/**
1482
	* constructor
1483
    *
1484
    * @param string $faultcode (SOAP-ENV:Client | SOAP-ENV:Server)
1485
    * @param string $faultactor only used when msg routed between multiple actors
1486
    * @param string $faultstring human readable error message
1487
    * @param mixed $faultdetail detail, typically a string or array of string
1488
	*/
1489
	function nusoap_fault($faultcode,$faultactor='',$faultstring='',$faultdetail=''){
1490
		parent::nusoap_base();
1491
		$this->faultcode = $faultcode;
1492
		$this->faultactor = $faultactor;
1493
		$this->faultstring = $faultstring;
1494
		$this->faultdetail = $faultdetail;
1495
	}
1496
1497
	/**
1498
	* serialize a fault
1499
	*
1500
	* @return	string	The serialization of the fault instance.
1501
	* @access   public
1502
	*/
1503
	function serialize(){
1504
		$ns_string = '';
1505
		foreach($this->namespaces as $k => $v){
1506
			$ns_string .= "\n  xmlns:$k=\"$v\"";
1507
		}
1508
		$return_msg =
1509
			'<?xml version="1.0" encoding="'.$this->soap_defencoding.'"?>'.
1510
			'<SOAP-ENV:Envelope SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"'.$ns_string.">\n".
1511
				'<SOAP-ENV:Body>'.
1512
				'<SOAP-ENV:Fault>'.
1513
					$this->serialize_val($this->faultcode, 'faultcode').
1514
					$this->serialize_val($this->faultactor, 'faultactor').
1515
					$this->serialize_val($this->faultstring, 'faultstring').
1516
					$this->serialize_val($this->faultdetail, 'detail').
1517
				'</SOAP-ENV:Fault>'.
1518
				'</SOAP-ENV:Body>'.
1519
			'</SOAP-ENV:Envelope>';
1520
		return $return_msg;
1521
	}
1522
}
1523
1524
/**
1525
 * Backward compatibility
1526
 */
1527
class soap_fault extends nusoap_fault {
0 ignored issues
show
Comprehensibility Best Practice introduced by
The type soap_fault has been defined more than once; this definition is ignored, only the first definition in include/nusoap/class.soap_fault.php (L127-128) is considered.

This check looks for classes that have been defined more than once.

If you can, we would recommend to use standard object-oriented programming techniques. For example, to avoid multiple types, it might make sense to create a common interface, and then multiple, different implementations for that interface.

This also has the side-effect of providing you with better IDE auto-completion, static analysis and also better OPCode caching from PHP.

Loading history...
Coding Style Compatibility introduced by
PSR1 recommends that each class should be in its own file to aid autoloaders.

Having each class in a dedicated file usually plays nice with PSR autoloaders and is therefore a well established practice. If you use other autoloaders, you might not want to follow this rule.

Loading history...
1528
}
1529
1530
?><?php
1531
1532
/*
1533
1534
Modification information for LGPL compliance
1535
1536
r58622 - 2010-10-22 18:18:59 -0700 (Fri, 22 Oct 2010) - engsvnbuild - Author: lam <[email protected]>
1537
    bug 40066
1538
1539
r58361 - 2010-09-29 16:59:02 -0700 (Wed, 29 Sep 2010) - kjing - Author: Jenny Gonsalves <[email protected]>
1540
    Merging with maint_6_0_1 (svn merge -r 58250:58342)
1541
1542
r57813 - 2010-08-19 10:34:44 -0700 (Thu, 19 Aug 2010) - kjing - Author: John Mertic <[email protected]>
1543
    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.
1544
1545
r57707 - 2010-08-10 12:26:13 -0700 (Tue, 10 Aug 2010) - kjing - Author: Stanislav Malyshev <[email protected]>
1546
    fix SOAP calls with no parameters
1547
1548
r56990 - 2010-06-16 13:05:36 -0700 (Wed, 16 Jun 2010) - kjing - snapshot "Mango" svn branch to a new one for GitHub sync
1549
1550
r56989 - 2010-06-16 13:01:33 -0700 (Wed, 16 Jun 2010) - kjing - defunt "Mango" svn dev branch before github cutover
1551
1552
r55980 - 2010-04-19 13:31:28 -0700 (Mon, 19 Apr 2010) - kjing - create Mango (6.1) based on windex
1553
1554
r51719 - 2009-10-22 10:18:00 -0700 (Thu, 22 Oct 2009) - mitani - Converted to Build 3  tags and updated the build system
1555
1556
r51634 - 2009-10-19 13:32:22 -0700 (Mon, 19 Oct 2009) - mitani - Windex is the branch for Sugar Sales 1.0 development
1557
1558
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.
1559
1560
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.
1561
1562
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:
1563
- Changing all ereg function to either preg or simple string based ones
1564
- No more references to magic quotes.
1565
- Change all the session_unregister() functions to just unset() the correct session variable instead.
1566
1567
r50375 - 2009-08-24 18:07:43 -0700 (Mon, 24 Aug 2009) - dwong - branch kobe2 from tokyo r50372
1568
1569
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
1570
1571
r45680 - 2009-03-30 14:34:35 -0700 (Mon, 30 Mar 2009) - Samir Gandhi - modifeid serializeSchema to generate WS-I compliant WSDL
1572
1573
r42807 - 2008-12-29 11:16:59 -0800 (Mon, 29 Dec 2008) - dwong - Branch from trunk/sugarcrm r42806 to branches/tokyo/sugarcrm
1574
1575
r42645 - 2008-12-18 13:41:08 -0800 (Thu, 18 Dec 2008) - awu - merging maint_5_2_0 rev41336:HEAD to trunk
1576
1577
r41647 - 2008-11-11 17:44:30 -0800 (Tue, 11 Nov 2008) - majed - Fixes a few bugs
1578
1579
r41596 - 2008-11-10 19:20:04 -0800 (Mon, 10 Nov 2008) - Samir Gandhi - modified to set $method in the code
1580
1581
r41558 - 2008-11-10 14:35:34 -0800 (Mon, 10 Nov 2008) - majed - changes nusoap to allow for registering classes
1582
1583
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.
1584
Touched:
1585
- data/SugarBean.php
1586
- include/domit/php_http_client_generic.php
1587
- include/domit/php_http_connector.php
1588
- include/domit/testing_domit.php
1589
- include/domit/xml_domit_getelementsbypath.php
1590
- include/domit/xml_domit_lite_parser.php
1591
- include/domit/xml_domit_nodemaps.php
1592
- include/domit/xml_domit_parser.php
1593
- include/domit/xml_domit_shared.php
1594
- include/generic/SugarWidgets/SugarWidgetField.php
1595
- include/generic/SugarWidgets/SugarWidgetReportField.php
1596
- include/ListView/ProcessView.php
1597
- include/nusoap/class.soapclient.php
1598
- include/nusoap/nusoap.php
1599
- include/nusoap/nusoapmime.php
1600
- include/Pear/HTML_Safe/Safe.php
1601
- include/Pear/XML_HTMLSax3/HTMLSax3.php
1602
- modules/Administration/RebuildWorkFlow.php
1603
- modules/Expressions/RelateSelector.php
1604
- modules/Reports/templates/templates_reports.php
1605
- modules/WorkFlow/Delete.php
1606
- modules/WorkFlow/Save.php
1607
- modules/WorkFlow/SaveSequence.php
1608
- modules/WorkFlow/WorkFlow.php
1609
- modules/WorkFlowActionShells/CreateStep1.php
1610
- modules/WorkFlowActionShells/CreateStep2.php
1611
- modules/WorkFlowActionShells/Save.php
1612
- modules/WorkFlowActionShells/WorkFlowActionShell.php
1613
- modules/WorkFlowAlerts/Save.php
1614
- modules/WorkFlowAlerts/WorkFlowAlert.php
1615
- modules/WorkFlowAlertShells/DetailView.php
1616
- modules/WorkFlowAlertShells/WorkFlowAlertShell.php
1617
- modules/WorkFlowTriggerShells/CreateStep1.php
1618
- modules/WorkFlowTriggerShells/CreateStepFilter.php
1619
- modules/WorkFlowTriggerShells/SaveFilter.php
1620
- modules/WorkFlowTriggerShells/WorkFlowTriggerShell.php
1621
- soap/SoapHelperFunctions.php
1622
- test/modules/DynamicFields/DynamicFields_Bug24095_test.php
1623
- test/simpletest/browser.php
1624
- test/simpletest/default_reporter.php
1625
- test/simpletest/detached.php
1626
- test/simpletest/eclipse.php
1627
- test/simpletest/expectation.php
1628
- test/simpletest/extensions/pear_test_case.php
1629
- test/simpletest/form.php
1630
- test/simpletest/http.php
1631
- test/simpletest/mock_objects.php
1632
- test/simpletest/page.php
1633
- test/simpletest/parser.php
1634
- test/simpletest/remote.php
1635
- test/simpletest/shell_tester.php
1636
- test/simpletest/simple_test.php
1637
- test/simpletest/simpletest.php
1638
- test/simpletest/test/acceptance_test.php
1639
- test/simpletest/test/adapter_test.php
1640
- test/simpletest/test/authentication_test.php
1641
- test/simpletest/test/browser_test.php
1642
- test/simpletest/test/collector_test.php
1643
- test/simpletest/test/compatibility_test.php
1644
- test/simpletest/test/detached_test.php
1645
- test/simpletest/test/eclipse_test.php
1646
- test/simpletest/test/encoding_test.php
1647
- test/simpletest/test/errors_test.php
1648
- test/simpletest/test/expectation_test.php
1649
- test/simpletest/test/form_test.php
1650
- test/simpletest/test/frames_test.php
1651
- test/simpletest/test/http_test.php
1652
- test/simpletest/test/live_test.php
1653
- test/simpletest/test/mock_objects_test.php
1654
- test/simpletest/test/page_test.php
1655
- test/simpletest/test/parse_error_test.php
1656
- test/simpletest/test/parser_test.php
1657
- test/simpletest/test/remote_test.php
1658
- test/simpletest/test/shell_test.php
1659
- test/simpletest/test/shell_tester_test.php
1660
- test/simpletest/test/simpletest_test.php
1661
- test/simpletest/test/site/page_request.php
1662
- test/simpletest/test/tag_test.php
1663
- test/simpletest/test/unit_tester_test.php
1664
- test/simpletest/test/user_agent_test.php
1665
- test/simpletest/test/visual_test.php
1666
- test/simpletest/test/xml_test.php
1667
- test/simpletest/test_case.php
1668
- test/simpletest/ui/array_reporter/test.php
1669
- test/simpletest/ui/recorder/test.php
1670
- test/simpletest/unit_tester.php
1671
- test/simpletest/url.php
1672
- test/simpletest/user_agent.php
1673
- test/simpletest/web_tester.php
1674
- test/spikephpcoverage/src/PEAR.php
1675
- test/spikephpcoverage/src/util/Utility.php
1676
- test/spikephpcoverage/src/XML/Parser.php
1677
- test/spikephpcoverage/src/XML/Parser/Simple.php
1678
- test/test_utilities/SugarTest_SimpleBrowser.php
1679
1680
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.
1681
1682
r38300 - 2008-07-25 13:33:43 -0700 (Fri, 25 Jul 2008) - Samir Gandhi - put the debug in parseresponse function
1683
1684
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
1685
1686
r36824 - 2008-06-18 09:26:11 -0700 (Wed, 18 Jun 2008) - roger - bug: 21832
1687
1688
r26422 - 2007-09-05 17:29:12 -0700 (Wed, 05 Sep 2007) - majed - migrate from beta 1 to trunk
1689
1690
r15787 - 2006-08-10 10:14:41 -0700 (Thu, 10 Aug 2006) - roger - RRS: bug 7961
1691
1692
r14701 - 2006-07-17 13:37:26 -0700 (Mon, 17 Jul 2006) - roger - RRS: bug 5801
1693
1694
r13782 - 2006-06-06 10:58:55 -0700 (Tue, 06 Jun 2006) - majed - changes entry point code
1695
1696
r11466 - 2006-02-01 15:49:47 -0800 (Wed, 01 Feb 2006) - jacob - Adding extra !empty check to get around a PHP warning.
1697
1698
r11115 - 2006-01-17 14:54:45 -0800 (Tue, 17 Jan 2006) - majed - add entry point validation
1699
1700
r10585 - 2005-12-13 14:42:26 -0800 (Tue, 13 Dec 2005) - majed - adds new license mechanisim
1701
1702
r10170 - 2005-12-05 18:37:46 -0800 (Mon, 05 Dec 2005) - majed - fixes various issues
1703
1704
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.
1705
1706
r8991 - 2005-11-03 19:07:25 -0800 (Thu, 03 Nov 2005) - majed - fixes nusoap issue
1707
1708
r8846 - 2005-10-31 11:01:12 -0800 (Mon, 31 Oct 2005) - majed - new version of nusoap
1709
1710
r7905 - 2005-09-21 19:12:57 -0700 (Wed, 21 Sep 2005) - majed - restores old nusoap pre & with a few fixes
1711
1712
r7861 - 2005-09-20 15:40:25 -0700 (Tue, 20 Sep 2005) - majed - & fix for 3.5.1
1713
1714
r7452 - 2005-08-17 11:32:34 -0700 (Wed, 17 Aug 2005) - majed - changes soap to nusoap
1715
1716
r5820 - 2005-06-21 14:22:24 -0700 (Tue, 21 Jun 2005) - majed - fixes issues with nusoap and with custom fields
1717
1718
r5462 - 2005-05-25 13:50:11 -0700 (Wed, 25 May 2005) - majed - upgraded nusoap to .6.9
1719
1720
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
1721
1722
r573 - 2004-09-04 13:03:32 -0700 (Sat, 04 Sep 2004) - sugarclint - undoing copyrights added in inadvertantly.  --clint
1723
1724
r546 - 2004-09-03 11:49:38 -0700 (Fri, 03 Sep 2004) - sugarmsi - removed echo count
1725
1726
r354 - 2004-08-02 23:00:37 -0700 (Mon, 02 Aug 2004) - sugarjacob - Adding Soap
1727
1728
1729
*/
1730
1731
1732
1733
1734
1735
/**
1736
* parses an XML Schema, allows access to it's data, other utility methods.
1737
* imperfect, no validation... yet, but quite functional.
1738
*
1739
* @author   Dietrich Ayala <[email protected]>
1740
* @author   Scott Nichol <[email protected]>
1741
1742
* @access   public
1743
*/
1744
class nusoap_xmlschema extends nusoap_base  {
0 ignored issues
show
Comprehensibility Best Practice introduced by
The type nusoap_xmlschema has been defined more than once; this definition is ignored, only the first definition in include/nusoap/class.xmlschema.php (L61-1010) is considered.

This check looks for classes that have been defined more than once.

If you can, we would recommend to use standard object-oriented programming techniques. For example, to avoid multiple types, it might make sense to create a common interface, and then multiple, different implementations for that interface.

This also has the side-effect of providing you with better IDE auto-completion, static analysis and also better OPCode caching from PHP.

Loading history...
Coding Style Compatibility introduced by
PSR1 recommends that each class should be in its own file to aid autoloaders.

Having each class in a dedicated file usually plays nice with PSR autoloaders and is therefore a well established practice. If you use other autoloaders, you might not want to follow this rule.

Loading history...
1745
1746
	// files
1747
	var $schema = '';
1748
	var $xml = '';
1749
	// namespaces
1750
	var $enclosingNamespaces;
1751
	// schema info
1752
	var $schemaInfo = array();
1753
	var $schemaTargetNamespace = '';
1754
	// types, elements, attributes defined by the schema
1755
	var $attributes = array();
1756
	var $complexTypes = array();
1757
	var $complexTypeStack = array();
1758
	var $currentComplexType = null;
1759
	var $elements = array();
1760
	var $elementStack = array();
1761
	var $currentElement = null;
1762
	var $simpleTypes = array();
1763
	var $simpleTypeStack = array();
1764
	var $currentSimpleType = null;
1765
	// imports
1766
	var $imports = array();
1767
	// parser vars
1768
	var $parser;
1769
	var $position = 0;
1770
	var $depth = 0;
1771
	var $depth_array = array();
1772
	var $message = array();
1773
	var $defaultNamespace = array();
1774
1775
	/**
1776
	* constructor
1777
	*
1778
	* @param    string $schema schema document URI
1779
	* @param    string $xml xml document URI
1780
	* @param	string $namespaces namespaces defined in enclosing XML
1781
	* @access   public
1782
	*/
1783
	function nusoap_xmlschema($schema='',$xml='',$namespaces=array()){
1784
		parent::nusoap_base();
1785
		$this->debug('nusoap_xmlschema class instantiated, inside constructor');
1786
		// files
1787
		$this->schema = $schema;
1788
		$this->xml = $xml;
1789
1790
		// namespaces
1791
		$this->enclosingNamespaces = $namespaces;
1792
		$this->namespaces = array_merge($this->namespaces, $namespaces);
1793
1794
		// parse schema file
1795
		if($schema != ''){
1796
			$this->debug('initial schema file: '.$schema);
1797
			$this->parseFile($schema, 'schema');
1798
		}
1799
1800
		// parse xml file
1801
		if($xml != ''){
1802
			$this->debug('initial xml file: '.$xml);
1803
			$this->parseFile($xml, 'xml');
1804
		}
1805
1806
	}
1807
1808
    /**
1809
    * parse an XML file
1810
    *
1811
    * @param string $xml path/URL to XML file
1812
    * @param string $type (schema | xml)
1813
	* @return boolean
1814
    * @access public
1815
    */
1816
	function parseFile($xml,$type){
1817
		// parse xml file
1818
		if($xml != ""){
1819
			$xmlStr = @join("",@file($xml));
1820
			if($xmlStr == ""){
1821
				$msg = 'Error reading XML from '.$xml;
1822
				$this->setError($msg);
1823
				$this->debug($msg);
1824
			return false;
1825
			} else {
1826
				$this->debug("parsing $xml");
1827
				$this->parseString($xmlStr,$type);
1828
				$this->debug("done parsing $xml");
1829
			return true;
1830
			}
1831
		}
1832
		return false;
1833
	}
1834
1835
	/**
1836
	* parse an XML string
1837
	*
1838
	* @param    string $xml path or URL
1839
    * @param	string $type (schema|xml)
1840
	* @access   private
1841
	*/
1842
	function parseString($xml,$type){
1843
		// parse xml string
1844
		if($xml != ""){
1845
1846
	    	// Create an XML parser.
1847
	    	$this->parser = xml_parser_create();
1848
	    	// Set the options for parsing the XML data.
1849
	    	xml_parser_set_option($this->parser, XML_OPTION_CASE_FOLDING, 0);
1850
1851
	    	// Set the object for the parser.
1852
	    	xml_set_object($this->parser, $this);
1853
1854
	    	// Set the element handlers for the parser.
1855
			if($type == "schema"){
1856
		    	xml_set_element_handler($this->parser, 'schemaStartElement','schemaEndElement');
1857
		    	xml_set_character_data_handler($this->parser,'schemaCharacterData');
1858
			} elseif($type == "xml"){
1859
				xml_set_element_handler($this->parser, 'xmlStartElement','xmlEndElement');
1860
		    	xml_set_character_data_handler($this->parser,'xmlCharacterData');
1861
			}
1862
1863
		    // Parse the XML file.
1864
		    if(!xml_parse($this->parser,$xml,true)){
1865
			// Display an error message.
1866
				$errstr = sprintf('XML error parsing XML schema on line %d: %s',
1867
				xml_get_current_line_number($this->parser),
1868
				xml_error_string(xml_get_error_code($this->parser))
1869
				);
1870
				$this->debug($errstr);
1871
				$this->debug("XML payload:\n" . $xml);
1872
				$this->setError($errstr);
1873
	    	}
1874
1875
			xml_parser_free($this->parser);
1876
		} else{
1877
			$this->debug('no xml passed to parseString()!!');
1878
			$this->setError('no xml passed to parseString()!!');
1879
		}
1880
	}
1881
1882
	/**
1883
	 * gets a type name for an unnamed type
1884
	 *
1885
	 * @param	string	Element name
1886
	 * @return	string	A type name for an unnamed type
1887
	 * @access	private
1888
	 */
1889
	function CreateTypeName($ename) {
1890
		$scope = '';
1891
		for ($i = 0; $i < count($this->complexTypeStack); $i++) {
0 ignored issues
show
Performance Best Practice introduced by
It seems like you are calling the size function count() as part of the test condition. You might want to compute the size beforehand, and not on each iteration.

If the size of the collection does not change during the iteration, it is generally a good practice to compute it beforehand, and not on each iteration:

for ($i=0; $i<count($array); $i++) { // calls count() on each iteration
}

// Better
for ($i=0, $c=count($array); $i<$c; $i++) { // calls count() just once
}
Loading history...
1892
			$scope .= $this->complexTypeStack[$i] . '_';
1893
		}
1894
		return $scope . $ename . '_ContainedType';
1895
	}
1896
1897
	/**
1898
	* start-element handler
1899
	*
1900
	* @param    string $parser XML parser object
1901
	* @param    string $name element name
1902
	* @param    string $attrs associative array of attributes
1903
	* @access   private
1904
	*/
1905
	function schemaStartElement($parser, $name, $attrs) {
1906
1907
		// position in the total number of elements, starting from 0
1908
		$pos = $this->position++;
1909
		$depth = $this->depth++;
1910
		// set self as current value for this depth
1911
		$this->depth_array[$depth] = $pos;
1912
		$this->message[$pos] = array('cdata' => '');
1913
		if ($depth > 0) {
1914
			$this->defaultNamespace[$pos] = $this->defaultNamespace[$this->depth_array[$depth - 1]];
1915
		} else {
1916
			$this->defaultNamespace[$pos] = false;
1917
		}
1918
1919
		// get element prefix
1920
		if($prefix = $this->getPrefix($name)){
1921
			// get unqualified name
1922
			$name = $this->getLocalPart($name);
1923
		} else {
1924
        	$prefix = '';
1925
        }
1926
1927
        // loop thru attributes, expanding, and registering namespace declarations
1928
        if(count($attrs) > 0){
1929
        	foreach($attrs as $k => $v){
0 ignored issues
show
The expression $attrs of type string is not traversable.
Loading history...
1930
                // if ns declarations, add to class level array of valid namespaces
1931
				if(preg_match('/^xmlns/',$k)){
1932
                	//$this->xdebug("$k: $v");
1933
                	//$this->xdebug('ns_prefix: '.$this->getPrefix($k));
1934
                	if($ns_prefix = substr(strrchr($k,':'),1)){
1935
                		//$this->xdebug("Add namespace[$ns_prefix] = $v");
1936
						$this->namespaces[$ns_prefix] = $v;
1937
					} else {
1938
						$this->defaultNamespace[$pos] = $v;
1939
						if (! $this->getPrefixFromNamespace($v)) {
1940
							$this->namespaces['ns'.(count($this->namespaces)+1)] = $v;
1941
						}
1942
					}
1943
					if($v == 'http://www.w3.org/2001/XMLSchema' || $v == 'http://www.w3.org/1999/XMLSchema' || $v == 'http://www.w3.org/2000/10/XMLSchema'){
1944
						$this->XMLSchemaVersion = $v;
1945
						$this->namespaces['xsi'] = $v.'-instance';
1946
					}
1947
				}
1948
        	}
1949
        	foreach($attrs as $k => $v){
0 ignored issues
show
The expression $attrs of type string is not traversable.
Loading history...
1950
                // expand each attribute
1951
                $k = strpos($k,':') ? $this->expandQname($k) : $k;
1952
                $v = strpos($v,':') ? $this->expandQname($v) : $v;
1953
        		$eAttrs[$k] = $v;
1954
        	}
1955
        	$attrs = $eAttrs;
1956
        } else {
1957
        	$attrs = array();
1958
        }
1959
		// find status, register data
1960
		switch($name){
1961
			case 'all':			// (optional) compositor content for a complexType
1962
			case 'choice':
1963
			case 'group':
1964
			case 'sequence':
1965
				//$this->xdebug("compositor $name for currentComplexType: $this->currentComplexType and currentElement: $this->currentElement");
1966
				$this->complexTypes[$this->currentComplexType]['compositor'] = $name;
1967
				//if($name == 'all' || $name == 'sequence'){
1968
				//	$this->complexTypes[$this->currentComplexType]['phpType'] = 'struct';
1969
				//}
1970
			break;
1971
			case 'attribute':	// complexType attribute
1972
            	//$this->xdebug("parsing attribute $attrs[name] $attrs[ref] of value: ".$attrs['http://schemas.xmlsoap.org/wsdl/:arrayType']);
1973
            	$this->xdebug("parsing attribute:");
1974
            	$this->appendDebug($this->varDump($attrs));
1975
				if (!isset($attrs['form'])) {
1976
					// TODO: handle globals
1977
					$attrs['form'] = $this->schemaInfo['attributeFormDefault'];
1978
				}
1979
            	if (isset($attrs['http://schemas.xmlsoap.org/wsdl/:arrayType'])) {
1980
					$v = $attrs['http://schemas.xmlsoap.org/wsdl/:arrayType'];
1981
					if (!strpos($v, ':')) {
1982
						// no namespace in arrayType attribute value...
1983
						if ($this->defaultNamespace[$pos]) {
1984
							// ...so use the default
1985
							$attrs['http://schemas.xmlsoap.org/wsdl/:arrayType'] = $this->defaultNamespace[$pos] . ':' . $attrs['http://schemas.xmlsoap.org/wsdl/:arrayType'];
1986
						}
1987
					}
1988
            	}
1989
                if(isset($attrs['name'])){
1990
					$this->attributes[$attrs['name']] = $attrs;
1991
					$aname = $attrs['name'];
1992
				} elseif(isset($attrs['ref']) && $attrs['ref'] == 'http://schemas.xmlsoap.org/soap/encoding/:arrayType'){
1993
					if (isset($attrs['http://schemas.xmlsoap.org/wsdl/:arrayType'])) {
1994
	                	$aname = $attrs['http://schemas.xmlsoap.org/wsdl/:arrayType'];
1995
	                } else {
1996
	                	$aname = '';
1997
	                }
1998
				} elseif(isset($attrs['ref'])){
1999
					$aname = $attrs['ref'];
2000
                    $this->attributes[$attrs['ref']] = $attrs;
2001
				}
2002
2003
				if($this->currentComplexType){	// This should *always* be
2004
					$this->complexTypes[$this->currentComplexType]['attrs'][$aname] = $attrs;
2005
				}
2006
				// arrayType attribute
2007
				if(isset($attrs['http://schemas.xmlsoap.org/wsdl/:arrayType']) || $this->getLocalPart($aname) == 'arrayType'){
2008
					$this->complexTypes[$this->currentComplexType]['phpType'] = 'array';
2009
                	$prefix = $this->getPrefix($aname);
2010
					if(isset($attrs['http://schemas.xmlsoap.org/wsdl/:arrayType'])){
2011
						$v = $attrs['http://schemas.xmlsoap.org/wsdl/:arrayType'];
2012
					} else {
2013
						$v = '';
2014
					}
2015
                    if(strpos($v,'[,]')){
2016
                        $this->complexTypes[$this->currentComplexType]['multidimensional'] = true;
2017
                    }
2018
                    $v = substr($v,0,strpos($v,'[')); // clip the []
2019
                    if(!strpos($v,':') && isset($this->typemap[$this->XMLSchemaVersion][$v])){
2020
                        $v = $this->XMLSchemaVersion.':'.$v;
2021
                    }
2022
                    $this->complexTypes[$this->currentComplexType]['arrayType'] = $v;
2023
				}
2024
			break;
2025
			case 'complexContent':	// (optional) content for a complexType
2026
				$this->xdebug("do nothing for element $name");
2027
			break;
2028
			case 'complexType':
2029
				array_push($this->complexTypeStack, $this->currentComplexType);
2030
				if(isset($attrs['name'])){
2031
					// TODO: what is the scope of named complexTypes that appear
2032
					//       nested within other c complexTypes?
2033
					$this->xdebug('processing named complexType '.$attrs['name']);
2034
					//$this->currentElement = false;
2035
					$this->currentComplexType = $attrs['name'];
2036
					$this->complexTypes[$this->currentComplexType] = $attrs;
2037
					$this->complexTypes[$this->currentComplexType]['typeClass'] = 'complexType';
2038
					// This is for constructs like
2039
					//           <complexType name="ListOfString" base="soap:Array">
2040
					//                <sequence>
2041
					//                    <element name="string" type="xsd:string"
2042
					//                        minOccurs="0" maxOccurs="unbounded" />
2043
					//                </sequence>
2044
					//            </complexType>
2045
					if(isset($attrs['base']) && preg_match('/:Array$/',$attrs['base'])){
2046
						$this->xdebug('complexType is unusual array');
2047
						$this->complexTypes[$this->currentComplexType]['phpType'] = 'array';
2048
					} else {
2049
						$this->complexTypes[$this->currentComplexType]['phpType'] = 'struct';
2050
					}
2051
				} else {
2052
					$name = $this->CreateTypeName($this->currentElement);
2053
					$this->xdebug('processing unnamed complexType for element ' . $this->currentElement . ' named ' . $name);
2054
					$this->currentComplexType = $name;
2055
					//$this->currentElement = false;
2056
					$this->complexTypes[$this->currentComplexType] = $attrs;
2057
					$this->complexTypes[$this->currentComplexType]['typeClass'] = 'complexType';
2058
					// This is for constructs like
2059
					//           <complexType name="ListOfString" base="soap:Array">
2060
					//                <sequence>
2061
					//                    <element name="string" type="xsd:string"
2062
					//                        minOccurs="0" maxOccurs="unbounded" />
2063
					//                </sequence>
2064
					//            </complexType>
2065
					if(isset($attrs['base']) && preg_match('/:Array$/',$attrs['base'])){
2066
						$this->xdebug('complexType is unusual array');
2067
						$this->complexTypes[$this->currentComplexType]['phpType'] = 'array';
2068
					} else {
2069
						$this->complexTypes[$this->currentComplexType]['phpType'] = 'struct';
2070
					}
2071
				}
2072
				$this->complexTypes[$this->currentComplexType]['simpleContent'] = 'false';
2073
			break;
2074
			case 'element':
2075
				array_push($this->elementStack, $this->currentElement);
2076
				if (!isset($attrs['form'])) {
2077
					if ($this->currentComplexType) {
2078
						$attrs['form'] = $this->schemaInfo['elementFormDefault'];
2079
					} else {
2080
						// global
2081
						$attrs['form'] = 'qualified';
2082
					}
2083
				}
2084
				if(isset($attrs['type'])){
2085
					$this->xdebug("processing typed element ".$attrs['name']." of type ".$attrs['type']);
2086
					if (! $this->getPrefix($attrs['type'])) {
2087
						if ($this->defaultNamespace[$pos]) {
2088
							$attrs['type'] = $this->defaultNamespace[$pos] . ':' . $attrs['type'];
2089
							$this->xdebug('used default namespace to make type ' . $attrs['type']);
2090
						}
2091
					}
2092
					// This is for constructs like
2093
					//           <complexType name="ListOfString" base="soap:Array">
2094
					//                <sequence>
2095
					//                    <element name="string" type="xsd:string"
2096
					//                        minOccurs="0" maxOccurs="unbounded" />
2097
					//                </sequence>
2098
					//            </complexType>
2099
					if ($this->currentComplexType && $this->complexTypes[$this->currentComplexType]['phpType'] == 'array') {
2100
						$this->xdebug('arrayType for unusual array is ' . $attrs['type']);
2101
						$this->complexTypes[$this->currentComplexType]['arrayType'] = $attrs['type'];
2102
					}
2103
					$this->currentElement = $attrs['name'];
2104
					$ename = $attrs['name'];
2105
				} elseif(isset($attrs['ref'])){
2106
					$this->xdebug("processing element as ref to ".$attrs['ref']);
2107
					$this->currentElement = "ref to ".$attrs['ref'];
2108
					$ename = $this->getLocalPart($attrs['ref']);
2109
				} else {
2110
					$type = $this->CreateTypeName($this->currentComplexType . '_' . $attrs['name']);
2111
					$this->xdebug("processing untyped element " . $attrs['name'] . ' type ' . $type);
2112
					$this->currentElement = $attrs['name'];
2113
					$attrs['type'] = $this->schemaTargetNamespace . ':' . $type;
2114
					$ename = $attrs['name'];
2115
				}
2116
				if (isset($ename) && $this->currentComplexType) {
2117
					$this->xdebug("add element $ename to complexType $this->currentComplexType");
2118
					$this->complexTypes[$this->currentComplexType]['elements'][$ename] = $attrs;
2119
				} elseif (!isset($attrs['ref'])) {
2120
					$this->xdebug("add element $ename to elements array");
2121
					$this->elements[ $attrs['name'] ] = $attrs;
2122
					$this->elements[ $attrs['name'] ]['typeClass'] = 'element';
2123
				}
2124
			break;
2125
			case 'enumeration':	//	restriction value list member
2126
				$this->xdebug('enumeration ' . $attrs['value']);
2127
				if ($this->currentSimpleType) {
2128
					$this->simpleTypes[$this->currentSimpleType]['enumeration'][] = $attrs['value'];
2129
				} elseif ($this->currentComplexType) {
2130
					$this->complexTypes[$this->currentComplexType]['enumeration'][] = $attrs['value'];
2131
				}
2132
			break;
2133
			case 'extension':	// simpleContent or complexContent type extension
2134
				$this->xdebug('extension ' . $attrs['base']);
2135
				if ($this->currentComplexType) {
2136
					$ns = $this->getPrefix($attrs['base']);
2137
					if ($ns == '') {
2138
						$this->complexTypes[$this->currentComplexType]['extensionBase'] = $this->schemaTargetNamespace . ':' . $attrs['base'];
2139
					} else {
2140
						$this->complexTypes[$this->currentComplexType]['extensionBase'] = $attrs['base'];
2141
					}
2142
				} else {
2143
					$this->xdebug('no current complexType to set extensionBase');
2144
				}
2145
			break;
2146
			case 'import':
2147
			    if (isset($attrs['schemaLocation'])) {
2148
					$this->xdebug('import namespace ' . $attrs['namespace'] . ' from ' . $attrs['schemaLocation']);
2149
                    $this->imports[$attrs['namespace']][] = array('location' => $attrs['schemaLocation'], 'loaded' => false);
2150
				} else {
2151
					$this->xdebug('import namespace ' . $attrs['namespace']);
2152
                    $this->imports[$attrs['namespace']][] = array('location' => '', 'loaded' => true);
2153
					if (! $this->getPrefixFromNamespace($attrs['namespace'])) {
2154
						$this->namespaces['ns'.(count($this->namespaces)+1)] = $attrs['namespace'];
2155
					}
2156
				}
2157
			break;
2158
			case 'include':
2159
			    if (isset($attrs['schemaLocation'])) {
2160
					$this->xdebug('include into namespace ' . $this->schemaTargetNamespace . ' from ' . $attrs['schemaLocation']);
2161
                    $this->imports[$this->schemaTargetNamespace][] = array('location' => $attrs['schemaLocation'], 'loaded' => false);
2162
				} else {
2163
					$this->xdebug('ignoring invalid XML Schema construct: include without schemaLocation attribute');
2164
				}
2165
			break;
2166
			case 'list':	// simpleType value list
2167
				$this->xdebug("do nothing for element $name");
2168
			break;
2169
			case 'restriction':	// simpleType, simpleContent or complexContent value restriction
2170
				$this->xdebug('restriction ' . $attrs['base']);
2171
				if($this->currentSimpleType){
2172
					$this->simpleTypes[$this->currentSimpleType]['type'] = $attrs['base'];
2173
				} elseif($this->currentComplexType){
2174
					$this->complexTypes[$this->currentComplexType]['restrictionBase'] = $attrs['base'];
2175
					if(strstr($attrs['base'],':') == ':Array'){
2176
						$this->complexTypes[$this->currentComplexType]['phpType'] = 'array';
2177
					}
2178
				}
2179
			break;
2180
			case 'schema':
2181
				$this->schemaInfo = $attrs;
2182
				$this->schemaInfo['schemaVersion'] = $this->getNamespaceFromPrefix($prefix);
2183
				if (isset($attrs['targetNamespace'])) {
2184
					$this->schemaTargetNamespace = $attrs['targetNamespace'];
2185
				}
2186
				if (!isset($attrs['elementFormDefault'])) {
2187
					$this->schemaInfo['elementFormDefault'] = 'unqualified';
2188
				}
2189
				if (!isset($attrs['attributeFormDefault'])) {
2190
					$this->schemaInfo['attributeFormDefault'] = 'unqualified';
2191
				}
2192
			break;
2193
			case 'simpleContent':	// (optional) content for a complexType
2194
				if ($this->currentComplexType) {	// This should *always* be
2195
					$this->complexTypes[$this->currentComplexType]['simpleContent'] = 'true';
2196
				} else {
2197
					$this->xdebug("do nothing for element $name because there is no current complexType");
2198
				}
2199
			break;
2200
			case 'simpleType':
2201
				array_push($this->simpleTypeStack, $this->currentSimpleType);
2202
				if(isset($attrs['name'])){
2203
					$this->xdebug("processing simpleType for name " . $attrs['name']);
2204
					$this->currentSimpleType = $attrs['name'];
2205
					$this->simpleTypes[ $attrs['name'] ] = $attrs;
2206
					$this->simpleTypes[ $attrs['name'] ]['typeClass'] = 'simpleType';
2207
					$this->simpleTypes[ $attrs['name'] ]['phpType'] = 'scalar';
2208
				} else {
2209
					$name = $this->CreateTypeName($this->currentComplexType . '_' . $this->currentElement);
2210
					$this->xdebug('processing unnamed simpleType for element ' . $this->currentElement . ' named ' . $name);
2211
					$this->currentSimpleType = $name;
2212
					//$this->currentElement = false;
2213
					$this->simpleTypes[$this->currentSimpleType] = $attrs;
2214
					$this->simpleTypes[$this->currentSimpleType]['phpType'] = 'scalar';
2215
				}
2216
			break;
2217
			case 'union':	// simpleType type list
2218
				$this->xdebug("do nothing for element $name");
2219
			break;
2220
			default:
2221
				$this->xdebug("do not have any logic to process element $name");
2222
		}
2223
	}
2224
2225
	/**
2226
	* end-element handler
2227
	*
2228
	* @param    string $parser XML parser object
2229
	* @param    string $name element name
2230
	* @access   private
2231
	*/
2232
	function schemaEndElement($parser, $name) {
2233
		// bring depth down a notch
2234
		$this->depth--;
2235
		// position of current element is equal to the last value left in depth_array for my depth
2236
		if(isset($this->depth_array[$this->depth])){
2237
        	$pos = $this->depth_array[$this->depth];
2238
        }
2239
		// get element prefix
2240
		if ($prefix = $this->getPrefix($name)){
2241
			// get unqualified name
2242
			$name = $this->getLocalPart($name);
2243
		} else {
2244
        	$prefix = '';
2245
        }
2246
		// move on...
2247
		if($name == 'complexType'){
2248
			$this->xdebug('done processing complexType ' . ($this->currentComplexType ? $this->currentComplexType : '(unknown)'));
2249
			$this->xdebug($this->varDump($this->complexTypes[$this->currentComplexType]));
2250
			$this->currentComplexType = array_pop($this->complexTypeStack);
2251
			//$this->currentElement = false;
2252
		}
2253
		if($name == 'element'){
2254
			$this->xdebug('done processing element ' . ($this->currentElement ? $this->currentElement : '(unknown)'));
2255
			$this->currentElement = array_pop($this->elementStack);
2256
		}
2257
		if($name == 'simpleType'){
2258
			$this->xdebug('done processing simpleType ' . ($this->currentSimpleType ? $this->currentSimpleType : '(unknown)'));
2259
			$this->xdebug($this->varDump($this->simpleTypes[$this->currentSimpleType]));
2260
			$this->currentSimpleType = array_pop($this->simpleTypeStack);
2261
		}
2262
	}
2263
2264
	/**
2265
	* element content handler
2266
	*
2267
	* @param    string $parser XML parser object
2268
	* @param    string $data element content
2269
	* @access   private
2270
	*/
2271
	function schemaCharacterData($parser, $data){
2272
		$pos = $this->depth_array[$this->depth - 1];
2273
		$this->message[$pos]['cdata'] .= $data;
2274
	}
2275
2276
	/**
2277
	* serialize the schema
2278
	*
2279
	* @access   public
2280
	*/
2281
	function serializeSchema(){
2282
2283
		$schemaPrefix = $this->getPrefixFromNamespace($this->XMLSchemaVersion);
2284
		$xml = '';
2285
		// imports
2286
		$schemaLocationCount = 0;
2287
		if (sizeof($this->imports) > 0) {
2288
			foreach($this->imports as $ns => $list) {
2289
				foreach ($list as $ii) {
2290
					if ($ii['location'] != '') {
2291
						$xml .= " <$schemaPrefix:import location=\"" . $ii['location'] . '" namespace="' . $ns . "\" />\n";
2292
					} else {
2293
						if ($schemaLocationCount == 0) {
2294
							$xml .= " <$schemaPrefix:import namespace=\"" . $ns . "\" schemaLocation=\"" . $ns . "\"/>\n";
2295
						} else {
2296
							$xml .= " <$schemaPrefix:import namespace=\"" . $ns . "\" />\n";
2297
						}
2298
					}
2299
				}
2300
			}
2301
		}
2302
		// complex types
2303
		foreach($this->complexTypes as $typeName => $attrs){
2304
			$contentStr = '';
2305
			// serialize child elements
2306
			if(isset($attrs['elements']) && (count($attrs['elements']) > 0)){
2307
				foreach($attrs['elements'] as $element => $eParts){
2308
					if(isset($eParts['ref'])){
2309
						$contentStr .= "   <$schemaPrefix:element ref=\"$element\"/>\n";
2310
					} else {
2311
						$contentStr .= "   <$schemaPrefix:element name=\"$element\" type=\"" . $this->contractQName($eParts['type']) . "\"";
2312
						foreach ($eParts as $aName => $aValue) {
2313
							// handle, e.g., abstract, default, form, minOccurs, maxOccurs, nillable
2314
							if ($aName != 'name' && $aName != 'type') {
2315
								$contentStr .= " $aName=\"$aValue\"";
2316
							}
2317
						}
2318
						$contentStr .= "/>\n";
2319
					}
2320
				}
2321
				// compositor wraps elements
2322
				if (isset($attrs['compositor']) && ($attrs['compositor'] != '')) {
2323
					$contentStr = "  <$schemaPrefix:$attrs[compositor]>\n".$contentStr."  </$schemaPrefix:$attrs[compositor]>\n";
2324
				}
2325
			}
2326
			// attributes
2327
			if(isset($attrs['attrs']) && (count($attrs['attrs']) >= 1)){
2328
				foreach($attrs['attrs'] as $attr => $aParts){
2329
					$contentStr .= "    <$schemaPrefix:attribute";
2330
					foreach ($aParts as $a => $v) {
2331
						if ($a == 'ref' || $a == 'type') {
2332
							$contentStr .= " $a=\"".$this->contractQName($v).'"';
2333
						} elseif ($a == 'http://schemas.xmlsoap.org/wsdl/:arrayType') {
2334
							$this->usedNamespaces['wsdl'] = $this->namespaces['wsdl'];
2335
							$contentStr .= ' wsdl:arrayType="'.$this->contractQName($v).'"';
2336
						} else {
2337
							$contentStr .= " $a=\"$v\"";
2338
						}
2339
					}
2340
					$contentStr .= "/>\n";
2341
				}
2342
			}
2343
			// if restriction
2344
			if (isset($attrs['restrictionBase']) && $attrs['restrictionBase'] != ''){
2345
				$contentStr = "   <$schemaPrefix:restriction base=\"".$this->contractQName($attrs['restrictionBase'])."\">\n".$contentStr."   </$schemaPrefix:restriction>\n";
2346
				// complex or simple content
2347
				if ((isset($attrs['elements']) && count($attrs['elements']) > 0) || (isset($attrs['attrs']) && count($attrs['attrs']) > 0)){
2348
					$contentStr = "  <$schemaPrefix:complexContent>\n".$contentStr."  </$schemaPrefix:complexContent>\n";
2349
				}
2350
			}
2351
			// finalize complex type
2352
			if($contentStr != ''){
2353
				$contentStr = " <$schemaPrefix:complexType name=\"$typeName\">\n".$contentStr." </$schemaPrefix:complexType>\n";
2354
			} else {
2355
				$contentStr = " <$schemaPrefix:complexType name=\"$typeName\"/>\n";
2356
			}
2357
			$xml .= $contentStr;
2358
		}
2359
		// simple types
2360
		if(isset($this->simpleTypes) && count($this->simpleTypes) > 0){
2361
			foreach($this->simpleTypes as $typeName => $eParts){
2362
				$xml .= " <$schemaPrefix:simpleType name=\"$typeName\">\n  <$schemaPrefix:restriction base=\"".$this->contractQName($eParts['type'])."\">\n";
2363
				if (isset($eParts['enumeration'])) {
2364
					foreach ($eParts['enumeration'] as $e) {
2365
						$xml .= "  <$schemaPrefix:enumeration value=\"$e\"/>\n";
2366
					}
2367
				}
2368
				$xml .= "  </$schemaPrefix:restriction>\n </$schemaPrefix:simpleType>";
2369
			}
2370
		}
2371
		// elements
2372
		if(isset($this->elements) && count($this->elements) > 0){
2373
			foreach($this->elements as $element => $eParts){
2374
				$xml .= " <$schemaPrefix:element name=\"$element\" type=\"".$this->contractQName($eParts['type'])."\"/>\n";
2375
			}
2376
		}
2377
		// attributes
2378
		if(isset($this->attributes) && count($this->attributes) > 0){
2379
			foreach($this->attributes as $attr => $aParts){
2380
				$xml .= " <$schemaPrefix:attribute name=\"$attr\" type=\"".$this->contractQName($aParts['type'])."\"\n/>";
2381
			}
2382
		}
2383
		// finish 'er up
2384
		$attr = '';
2385
		foreach ($this->schemaInfo as $k => $v) {
2386
			if ($k == 'elementFormDefault' || $k == 'attributeFormDefault') {
2387
				$attr .= " $k=\"$v\"";
2388
			}
2389
		}
2390
		$el = "<$schemaPrefix:schema$attr targetNamespace=\"$this->schemaTargetNamespace\"\n";
2391
		foreach (array_diff($this->usedNamespaces, $this->enclosingNamespaces) as $nsp => $ns) {
2392
			$el .= " xmlns:$nsp=\"$ns\"";
2393
		}
2394
		$xml = $el . ">\n".$xml."</$schemaPrefix:schema>\n";
2395
		return $xml;
2396
	}
2397
2398
	/**
2399
	* adds debug data to the clas level debug string
2400
	*
2401
	* @param    string $string debug data
2402
	* @access   private
2403
	*/
2404
	function xdebug($string){
2405
	    if($this->debugLevel > 0) {
2406
		    $this->debug('<' . $this->schemaTargetNamespace . '> '.$string);
2407
	    }
2408
	}
2409
2410
    /**
2411
    * get the PHP type of a user defined type in the schema
2412
    * PHP type is kind of a misnomer since it actually returns 'struct' for assoc. arrays
2413
    * returns false if no type exists, or not w/ the given namespace
2414
    * else returns a string that is either a native php type, or 'struct'
2415
    *
2416
    * @param string $type name of defined type
2417
    * @param string $ns namespace of type
2418
    * @return mixed
2419
    * @access public
2420
    * @deprecated
2421
    */
2422
	function getPHPType($type,$ns){
2423
		if(isset($this->typemap[$ns][$type])){
2424
			//print "found type '$type' and ns $ns in typemap<br>";
2425
			return $this->typemap[$ns][$type];
2426
		} elseif(isset($this->complexTypes[$type])){
2427
			//print "getting type '$type' and ns $ns from complexTypes array<br>";
2428
			return $this->complexTypes[$type]['phpType'];
2429
		}
2430
		return false;
2431
	}
2432
2433
	/**
2434
    * returns an associative array of information about a given type
2435
    * returns false if no type exists by the given name
2436
    *
2437
	*	For a complexType typeDef = array(
2438
	*	'restrictionBase' => '',
2439
	*	'phpType' => '',
2440
	*	'compositor' => '(sequence|all)',
2441
	*	'elements' => array(), // refs to elements array
2442
	*	'attrs' => array() // refs to attributes array
2443
	*	... and so on (see addComplexType)
2444
	*	)
2445
	*
2446
	*   For simpleType or element, the array has different keys.
2447
    *
2448
    * @param string $type
2449
    * @return mixed
2450
    * @access public
2451
    * @see addComplexType
2452
    * @see addSimpleType
2453
    * @see addElement
2454
    */
2455
	function getTypeDef($type){
2456
		//$this->debug("in getTypeDef for type $type");
2457
		if (substr($type, -1) == '^') {
2458
			$is_element = 1;
2459
			$type = substr($type, 0, -1);
2460
		} else {
2461
			$is_element = 0;
2462
		}
2463
2464
		if((! $is_element) && isset($this->complexTypes[$type])){
2465
			$this->xdebug("in getTypeDef, found complexType $type");
2466
			return $this->complexTypes[$type];
2467
		} elseif((! $is_element) && isset($this->simpleTypes[$type])){
2468
			$this->xdebug("in getTypeDef, found simpleType $type");
2469
			if (!isset($this->simpleTypes[$type]['phpType'])) {
2470
				// get info for type to tack onto the simple type
2471
				// TODO: can this ever really apply (i.e. what is a simpleType really?)
2472
				$uqType = substr($this->simpleTypes[$type]['type'], strrpos($this->simpleTypes[$type]['type'], ':') + 1);
2473
				$ns = substr($this->simpleTypes[$type]['type'], 0, strrpos($this->simpleTypes[$type]['type'], ':'));
2474
				$etype = $this->getTypeDef($uqType);
2475
				if ($etype) {
2476
					$this->xdebug("in getTypeDef, found type for simpleType $type:");
2477
					$this->xdebug($this->varDump($etype));
2478
					if (isset($etype['phpType'])) {
2479
						$this->simpleTypes[$type]['phpType'] = $etype['phpType'];
2480
					}
2481
					if (isset($etype['elements'])) {
2482
						$this->simpleTypes[$type]['elements'] = $etype['elements'];
2483
					}
2484
				}
2485
			}
2486
			return $this->simpleTypes[$type];
2487
		} elseif(isset($this->elements[$type])){
2488
			$this->xdebug("in getTypeDef, found element $type");
2489
			if (!isset($this->elements[$type]['phpType'])) {
2490
				// get info for type to tack onto the element
2491
				$uqType = substr($this->elements[$type]['type'], strrpos($this->elements[$type]['type'], ':') + 1);
2492
				$ns = substr($this->elements[$type]['type'], 0, strrpos($this->elements[$type]['type'], ':'));
2493
				$etype = $this->getTypeDef($uqType);
2494
				if ($etype) {
2495
					$this->xdebug("in getTypeDef, found type for element $type:");
2496
					$this->xdebug($this->varDump($etype));
2497
					if (isset($etype['phpType'])) {
2498
						$this->elements[$type]['phpType'] = $etype['phpType'];
2499
					}
2500
					if (isset($etype['elements'])) {
2501
						$this->elements[$type]['elements'] = $etype['elements'];
2502
					}
2503
					if (isset($etype['extensionBase'])) {
2504
						$this->elements[$type]['extensionBase'] = $etype['extensionBase'];
2505
					}
2506
				} elseif ($ns == 'http://www.w3.org/2001/XMLSchema') {
2507
					$this->xdebug("in getTypeDef, element $type is an XSD type");
2508
					$this->elements[$type]['phpType'] = 'scalar';
2509
				}
2510
			}
2511
			return $this->elements[$type];
2512
		} elseif(isset($this->attributes[$type])){
2513
			$this->xdebug("in getTypeDef, found attribute $type");
2514
			return $this->attributes[$type];
2515
		} elseif (preg_match('/_ContainedType$/', $type)) {
2516
			$this->xdebug("in getTypeDef, have an untyped element $type");
2517
			$typeDef['typeClass'] = 'simpleType';
2518
			$typeDef['phpType'] = 'scalar';
2519
			$typeDef['type'] = 'http://www.w3.org/2001/XMLSchema:string';
2520
			return $typeDef;
2521
		}
2522
		$this->xdebug("in getTypeDef, did not find $type");
2523
		return false;
2524
	}
2525
2526
	/**
2527
    * returns a sample serialization of a given type, or false if no type by the given name
2528
    *
2529
    * @param string $type name of type
2530
    * @return mixed
2531
    * @access public
2532
    * @deprecated
2533
    */
2534
    function serializeTypeDef($type){
2535
    	//print "in sTD() for type $type<br>";
2536
	if($typeDef = $this->getTypeDef($type)){
2537
		$str .= '<'.$type;
2538
	    if(is_array($typeDef['attrs'])){
2539
		foreach($typeDef['attrs'] as $attName => $data){
2540
		    $str .= " $attName=\"{type = ".$data['type']."}\"";
2541
		}
2542
	    }
2543
	    $str .= " xmlns=\"".$this->schema['targetNamespace']."\"";
2544
	    if(count($typeDef['elements']) > 0){
2545
		$str .= ">";
2546
		foreach($typeDef['elements'] as $element => $eData){
2547
		    $str .= $this->serializeTypeDef($element);
0 ignored issues
show
Deprecated Code introduced by
The method nusoap_xmlschema::serializeTypeDef() has been deprecated.

This method has been deprecated.

Loading history...
2548
		}
2549
		$str .= "</$type>";
2550
	    } elseif($typeDef['typeClass'] == 'element') {
2551
		$str .= "></$type>";
2552
	    } else {
2553
		$str .= "/>";
2554
	    }
2555
			return $str;
2556
	}
2557
    	return false;
2558
    }
2559
2560
    /**
2561
    * returns HTML form elements that allow a user
2562
    * to enter values for creating an instance of the given type.
2563
    *
2564
    * @param string $name name for type instance
2565
    * @param string $type name of type
2566
    * @return string
2567
    * @access public
2568
    * @deprecated
2569
	*/
2570
	function typeToForm($name,$type){
2571
		// get typedef
2572
		if($typeDef = $this->getTypeDef($type)){
2573
			// if struct
2574
			if($typeDef['phpType'] == 'struct'){
2575
				$buffer .= '<table>';
2576
				foreach($typeDef['elements'] as $child => $childDef){
2577
					$buffer .= "
2578
					<tr><td align='right'>$childDef[name] (type: ".$this->getLocalPart($childDef['type'])."):</td>
2579
					<td><input type='text' name='parameters[".$name."][$childDef[name]]'></td></tr>";
2580
				}
2581
				$buffer .= '</table>';
2582
			// if array
2583
			} elseif($typeDef['phpType'] == 'array'){
2584
				$buffer .= '<table>';
2585
				for($i=0;$i < 3; $i++){
2586
					$buffer .= "
2587
					<tr><td align='right'>array item (type: $typeDef[arrayType]):</td>
2588
					<td><input type='text' name='parameters[".$name."][]'></td></tr>";
2589
				}
2590
				$buffer .= '</table>';
2591
			// if scalar
2592
			} else {
2593
				$buffer .= "<input type='text' name='parameters[$name]'>";
2594
			}
2595
		} else {
2596
			$buffer .= "<input type='text' name='parameters[$name]'>";
2597
		}
2598
		return $buffer;
2599
	}
2600
2601
	/**
2602
	* adds a complex type to the schema
2603
	*
2604
	* example: array
2605
	*
2606
	* addType(
2607
	* 	'ArrayOfstring',
2608
	* 	'complexType',
2609
	* 	'array',
2610
	* 	'',
2611
	* 	'SOAP-ENC:Array',
2612
	* 	array('ref'=>'SOAP-ENC:arrayType','wsdl:arrayType'=>'string[]'),
2613
	* 	'xsd:string'
2614
	* );
2615
	*
2616
	* example: PHP associative array ( SOAP Struct )
2617
	*
2618
	* addType(
2619
	* 	'SOAPStruct',
2620
	* 	'complexType',
2621
	* 	'struct',
2622
	* 	'all',
2623
	* 	array('myVar'=> array('name'=>'myVar','type'=>'string')
2624
	* );
2625
	*
2626
	* @param name
2627
	* @param typeClass (complexType|simpleType|attribute)
2628
	* @param phpType: currently supported are array and struct (php assoc array)
2629
	* @param compositor (all|sequence|choice)
2630
	* @param restrictionBase namespace:name (http://schemas.xmlsoap.org/soap/encoding/:Array)
2631
	* @param elements = array ( name = array(name=>'',type=>'') )
2632
	* @param attrs = array(
2633
	* 	array(
2634
	*		'ref' => "http://schemas.xmlsoap.org/soap/encoding/:arrayType",
2635
	*		"http://schemas.xmlsoap.org/wsdl/:arrayType" => "string[]"
2636
	* 	)
2637
	* )
2638
	* @param arrayType: namespace:name (http://www.w3.org/2001/XMLSchema:string)
2639
	* @access public
2640
	* @see getTypeDef
2641
	*/
2642
	function addComplexType($name,$typeClass='complexType',$phpType='array',$compositor='',$restrictionBase='',$elements=array(),$attrs=array(),$arrayType=''){
2643
		$this->complexTypes[$name] = array(
2644
	    'name'		=> $name,
2645
	    'typeClass'	=> $typeClass,
2646
	    'phpType'	=> $phpType,
2647
		'compositor'=> $compositor,
2648
	    'restrictionBase' => $restrictionBase,
2649
		'elements'	=> $elements,
2650
	    'attrs'		=> $attrs,
2651
	    'arrayType'	=> $arrayType
2652
		);
2653
2654
		$this->xdebug("addComplexType $name:");
2655
		$this->appendDebug($this->varDump($this->complexTypes[$name]));
2656
	}
2657
2658
	/**
2659
	* adds a simple type to the schema
2660
	*
2661
	* @param string $name
2662
	* @param string $restrictionBase namespace:name (http://schemas.xmlsoap.org/soap/encoding/:Array)
2663
	* @param string $typeClass (should always be simpleType)
2664
	* @param string $phpType (should always be scalar)
2665
	* @param array $enumeration array of values
2666
	* @access public
2667
	* @see nusoap_xmlschema
2668
	* @see getTypeDef
2669
	*/
2670
	function addSimpleType($name, $restrictionBase='', $typeClass='simpleType', $phpType='scalar', $enumeration=array()) {
2671
		$this->simpleTypes[$name] = array(
2672
	    'name'			=> $name,
2673
	    'typeClass'		=> $typeClass,
2674
	    'phpType'		=> $phpType,
2675
	    'type'			=> $restrictionBase,
2676
	    'enumeration'	=> $enumeration
2677
		);
2678
2679
		$this->xdebug("addSimpleType $name:");
2680
		$this->appendDebug($this->varDump($this->simpleTypes[$name]));
2681
	}
2682
2683
	/**
2684
	* adds an element to the schema
2685
	*
2686
	* @param array $attrs attributes that must include name and type
2687
	* @see nusoap_xmlschema
2688
	* @access public
2689
	*/
2690
	function addElement($attrs) {
2691
		if (! $this->getPrefix($attrs['type'])) {
2692
			$attrs['type'] = $this->schemaTargetNamespace . ':' . $attrs['type'];
2693
		}
2694
		$this->elements[ $attrs['name'] ] = $attrs;
2695
		$this->elements[ $attrs['name'] ]['typeClass'] = 'element';
2696
2697
		$this->xdebug("addElement " . $attrs['name']);
2698
		$this->appendDebug($this->varDump($this->elements[ $attrs['name'] ]));
2699
	}
2700
}
2701
2702
/**
2703
 * Backward compatibility
2704
 */
2705
class XMLSchema extends nusoap_xmlschema {
0 ignored issues
show
Comprehensibility Best Practice introduced by
The type XMLSchema has been defined more than once; this definition is ignored, only the first definition in include/nusoap/class.xmlschema.php (L1015-1016) is considered.

This check looks for classes that have been defined more than once.

If you can, we would recommend to use standard object-oriented programming techniques. For example, to avoid multiple types, it might make sense to create a common interface, and then multiple, different implementations for that interface.

This also has the side-effect of providing you with better IDE auto-completion, static analysis and also better OPCode caching from PHP.

Loading history...
Coding Style Compatibility introduced by
PSR1 recommends that each class should be in its own file to aid autoloaders.

Having each class in a dedicated file usually plays nice with PSR autoloaders and is therefore a well established practice. If you use other autoloaders, you might not want to follow this rule.

Loading history...
2706
}
2707
2708
?><?php
2709
2710
/*
2711
2712
Modification information for LGPL compliance
2713
2714
r58622 - 2010-10-22 18:18:59 -0700 (Fri, 22 Oct 2010) - engsvnbuild - Author: lam <[email protected]>
2715
    bug 40066
2716
2717
r58361 - 2010-09-29 16:59:02 -0700 (Wed, 29 Sep 2010) - kjing - Author: Jenny Gonsalves <[email protected]>
2718
    Merging with maint_6_0_1 (svn merge -r 58250:58342)
2719
2720
r57813 - 2010-08-19 10:34:44 -0700 (Thu, 19 Aug 2010) - kjing - Author: John Mertic <[email protected]>
2721
    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.
2722
2723
r57707 - 2010-08-10 12:26:13 -0700 (Tue, 10 Aug 2010) - kjing - Author: Stanislav Malyshev <[email protected]>
2724
    fix SOAP calls with no parameters
2725
2726
r56990 - 2010-06-16 13:05:36 -0700 (Wed, 16 Jun 2010) - kjing - snapshot "Mango" svn branch to a new one for GitHub sync
2727
2728
r56989 - 2010-06-16 13:01:33 -0700 (Wed, 16 Jun 2010) - kjing - defunt "Mango" svn dev branch before github cutover
2729
2730
r55980 - 2010-04-19 13:31:28 -0700 (Mon, 19 Apr 2010) - kjing - create Mango (6.1) based on windex
2731
2732
r51719 - 2009-10-22 10:18:00 -0700 (Thu, 22 Oct 2009) - mitani - Converted to Build 3  tags and updated the build system
2733
2734
r51634 - 2009-10-19 13:32:22 -0700 (Mon, 19 Oct 2009) - mitani - Windex is the branch for Sugar Sales 1.0 development
2735
2736
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.
2737
2738
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.
2739
2740
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:
2741
- Changing all ereg function to either preg or simple string based ones
2742
- No more references to magic quotes.
2743
- Change all the session_unregister() functions to just unset() the correct session variable instead.
2744
2745
r50375 - 2009-08-24 18:07:43 -0700 (Mon, 24 Aug 2009) - dwong - branch kobe2 from tokyo r50372
2746
2747
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
2748
2749
r45680 - 2009-03-30 14:34:35 -0700 (Mon, 30 Mar 2009) - Samir Gandhi - modifeid serializeSchema to generate WS-I compliant WSDL
2750
2751
r42807 - 2008-12-29 11:16:59 -0800 (Mon, 29 Dec 2008) - dwong - Branch from trunk/sugarcrm r42806 to branches/tokyo/sugarcrm
2752
2753
r42645 - 2008-12-18 13:41:08 -0800 (Thu, 18 Dec 2008) - awu - merging maint_5_2_0 rev41336:HEAD to trunk
2754
2755
r41647 - 2008-11-11 17:44:30 -0800 (Tue, 11 Nov 2008) - majed - Fixes a few bugs
2756
2757
r41596 - 2008-11-10 19:20:04 -0800 (Mon, 10 Nov 2008) - Samir Gandhi - modified to set $method in the code
2758
2759
r41558 - 2008-11-10 14:35:34 -0800 (Mon, 10 Nov 2008) - majed - changes nusoap to allow for registering classes
2760
2761
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.
2762
Touched:
2763
- data/SugarBean.php
2764
- include/domit/php_http_client_generic.php
2765
- include/domit/php_http_connector.php
2766
- include/domit/testing_domit.php
2767
- include/domit/xml_domit_getelementsbypath.php
2768
- include/domit/xml_domit_lite_parser.php
2769
- include/domit/xml_domit_nodemaps.php
2770
- include/domit/xml_domit_parser.php
2771
- include/domit/xml_domit_shared.php
2772
- include/generic/SugarWidgets/SugarWidgetField.php
2773
- include/generic/SugarWidgets/SugarWidgetReportField.php
2774
- include/ListView/ProcessView.php
2775
- include/nusoap/class.soapclient.php
2776
- include/nusoap/nusoap.php
2777
- include/nusoap/nusoapmime.php
2778
- include/Pear/HTML_Safe/Safe.php
2779
- include/Pear/XML_HTMLSax3/HTMLSax3.php
2780
- modules/Administration/RebuildWorkFlow.php
2781
- modules/Expressions/RelateSelector.php
2782
- modules/Reports/templates/templates_reports.php
2783
- modules/WorkFlow/Delete.php
2784
- modules/WorkFlow/Save.php
2785
- modules/WorkFlow/SaveSequence.php
2786
- modules/WorkFlow/WorkFlow.php
2787
- modules/WorkFlowActionShells/CreateStep1.php
2788
- modules/WorkFlowActionShells/CreateStep2.php
2789
- modules/WorkFlowActionShells/Save.php
2790
- modules/WorkFlowActionShells/WorkFlowActionShell.php
2791
- modules/WorkFlowAlerts/Save.php
2792
- modules/WorkFlowAlerts/WorkFlowAlert.php
2793
- modules/WorkFlowAlertShells/DetailView.php
2794
- modules/WorkFlowAlertShells/WorkFlowAlertShell.php
2795
- modules/WorkFlowTriggerShells/CreateStep1.php
2796
- modules/WorkFlowTriggerShells/CreateStepFilter.php
2797
- modules/WorkFlowTriggerShells/SaveFilter.php
2798
- modules/WorkFlowTriggerShells/WorkFlowTriggerShell.php
2799
- soap/SoapHelperFunctions.php
2800
- test/modules/DynamicFields/DynamicFields_Bug24095_test.php
2801
- test/simpletest/browser.php
2802
- test/simpletest/default_reporter.php
2803
- test/simpletest/detached.php
2804
- test/simpletest/eclipse.php
2805
- test/simpletest/expectation.php
2806
- test/simpletest/extensions/pear_test_case.php
2807
- test/simpletest/form.php
2808
- test/simpletest/http.php
2809
- test/simpletest/mock_objects.php
2810
- test/simpletest/page.php
2811
- test/simpletest/parser.php
2812
- test/simpletest/remote.php
2813
- test/simpletest/shell_tester.php
2814
- test/simpletest/simple_test.php
2815
- test/simpletest/simpletest.php
2816
- test/simpletest/test/acceptance_test.php
2817
- test/simpletest/test/adapter_test.php
2818
- test/simpletest/test/authentication_test.php
2819
- test/simpletest/test/browser_test.php
2820
- test/simpletest/test/collector_test.php
2821
- test/simpletest/test/compatibility_test.php
2822
- test/simpletest/test/detached_test.php
2823
- test/simpletest/test/eclipse_test.php
2824
- test/simpletest/test/encoding_test.php
2825
- test/simpletest/test/errors_test.php
2826
- test/simpletest/test/expectation_test.php
2827
- test/simpletest/test/form_test.php
2828
- test/simpletest/test/frames_test.php
2829
- test/simpletest/test/http_test.php
2830
- test/simpletest/test/live_test.php
2831
- test/simpletest/test/mock_objects_test.php
2832
- test/simpletest/test/page_test.php
2833
- test/simpletest/test/parse_error_test.php
2834
- test/simpletest/test/parser_test.php
2835
- test/simpletest/test/remote_test.php
2836
- test/simpletest/test/shell_test.php
2837
- test/simpletest/test/shell_tester_test.php
2838
- test/simpletest/test/simpletest_test.php
2839
- test/simpletest/test/site/page_request.php
2840
- test/simpletest/test/tag_test.php
2841
- test/simpletest/test/unit_tester_test.php
2842
- test/simpletest/test/user_agent_test.php
2843
- test/simpletest/test/visual_test.php
2844
- test/simpletest/test/xml_test.php
2845
- test/simpletest/test_case.php
2846
- test/simpletest/ui/array_reporter/test.php
2847
- test/simpletest/ui/recorder/test.php
2848
- test/simpletest/unit_tester.php
2849
- test/simpletest/url.php
2850
- test/simpletest/user_agent.php
2851
- test/simpletest/web_tester.php
2852
- test/spikephpcoverage/src/PEAR.php
2853
- test/spikephpcoverage/src/util/Utility.php
2854
- test/spikephpcoverage/src/XML/Parser.php
2855
- test/spikephpcoverage/src/XML/Parser/Simple.php
2856
- test/test_utilities/SugarTest_SimpleBrowser.php
2857
2858
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.
2859
2860
r38300 - 2008-07-25 13:33:43 -0700 (Fri, 25 Jul 2008) - Samir Gandhi - put the debug in parseresponse function
2861
2862
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
2863
2864
r36824 - 2008-06-18 09:26:11 -0700 (Wed, 18 Jun 2008) - roger - bug: 21832
2865
2866
r26422 - 2007-09-05 17:29:12 -0700 (Wed, 05 Sep 2007) - majed - migrate from beta 1 to trunk
2867
2868
r15787 - 2006-08-10 10:14:41 -0700 (Thu, 10 Aug 2006) - roger - RRS: bug 7961
2869
2870
r14701 - 2006-07-17 13:37:26 -0700 (Mon, 17 Jul 2006) - roger - RRS: bug 5801
2871
2872
r13782 - 2006-06-06 10:58:55 -0700 (Tue, 06 Jun 2006) - majed - changes entry point code
2873
2874
r11466 - 2006-02-01 15:49:47 -0800 (Wed, 01 Feb 2006) - jacob - Adding extra !empty check to get around a PHP warning.
2875
2876
r11115 - 2006-01-17 14:54:45 -0800 (Tue, 17 Jan 2006) - majed - add entry point validation
2877
2878
r10585 - 2005-12-13 14:42:26 -0800 (Tue, 13 Dec 2005) - majed - adds new license mechanisim
2879
2880
r10170 - 2005-12-05 18:37:46 -0800 (Mon, 05 Dec 2005) - majed - fixes various issues
2881
2882
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.
2883
2884
r8991 - 2005-11-03 19:07:25 -0800 (Thu, 03 Nov 2005) - majed - fixes nusoap issue
2885
2886
r8846 - 2005-10-31 11:01:12 -0800 (Mon, 31 Oct 2005) - majed - new version of nusoap
2887
2888
r7905 - 2005-09-21 19:12:57 -0700 (Wed, 21 Sep 2005) - majed - restores old nusoap pre & with a few fixes
2889
2890
r7861 - 2005-09-20 15:40:25 -0700 (Tue, 20 Sep 2005) - majed - & fix for 3.5.1
2891
2892
r7452 - 2005-08-17 11:32:34 -0700 (Wed, 17 Aug 2005) - majed - changes soap to nusoap
2893
2894
r5820 - 2005-06-21 14:22:24 -0700 (Tue, 21 Jun 2005) - majed - fixes issues with nusoap and with custom fields
2895
2896
r5462 - 2005-05-25 13:50:11 -0700 (Wed, 25 May 2005) - majed - upgraded nusoap to .6.9
2897
2898
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
2899
2900
r573 - 2004-09-04 13:03:32 -0700 (Sat, 04 Sep 2004) - sugarclint - undoing copyrights added in inadvertantly.  --clint
2901
2902
r546 - 2004-09-03 11:49:38 -0700 (Fri, 03 Sep 2004) - sugarmsi - removed echo count
2903
2904
r354 - 2004-08-02 23:00:37 -0700 (Mon, 02 Aug 2004) - sugarjacob - Adding Soap
2905
2906
2907
*/
2908
2909
2910
2911
2912
2913
/**
2914
* For creating serializable abstractions of native PHP types.  This class
2915
* allows element name/namespace, XSD type, and XML attributes to be
2916
* associated with a value.  This is extremely useful when WSDL is not
2917
* used, but is also useful when WSDL is used with polymorphic types, including
2918
* xsd:anyType and user-defined types.
2919
*
2920
* @author   Dietrich Ayala <[email protected]>
2921
2922
* @access   public
2923
*/
2924
class soapval extends nusoap_base {
0 ignored issues
show
Comprehensibility Best Practice introduced by
The type soapval has been defined more than once; this definition is ignored, only the first definition in include/nusoap/class.soap_val.php (L58-143) is considered.

This check looks for classes that have been defined more than once.

If you can, we would recommend to use standard object-oriented programming techniques. For example, to avoid multiple types, it might make sense to create a common interface, and then multiple, different implementations for that interface.

This also has the side-effect of providing you with better IDE auto-completion, static analysis and also better OPCode caching from PHP.

Loading history...
Coding Style Compatibility introduced by
PSR1 recommends that each class should be in its own file to aid autoloaders.

Having each class in a dedicated file usually plays nice with PSR autoloaders and is therefore a well established practice. If you use other autoloaders, you might not want to follow this rule.

Loading history...
2925
	/**
2926
	 * The XML element name
2927
	 *
2928
	 * @var string
2929
	 * @access private
2930
	 */
2931
	var $name;
2932
	/**
2933
	 * The XML type name (string or false)
2934
	 *
2935
	 * @var mixed
2936
	 * @access private
2937
	 */
2938
	var $type;
2939
	/**
2940
	 * The PHP value
2941
	 *
2942
	 * @var mixed
2943
	 * @access private
2944
	 */
2945
	var $value;
2946
	/**
2947
	 * The XML element namespace (string or false)
2948
	 *
2949
	 * @var mixed
2950
	 * @access private
2951
	 */
2952
	var $element_ns;
2953
	/**
2954
	 * The XML type namespace (string or false)
2955
	 *
2956
	 * @var mixed
2957
	 * @access private
2958
	 */
2959
	var $type_ns;
2960
	/**
2961
	 * The XML element attributes (array or false)
2962
	 *
2963
	 * @var mixed
2964
	 * @access private
2965
	 */
2966
	var $attributes;
2967
2968
	/**
2969
	* constructor
2970
	*
2971
	* @param    string $name optional name
2972
	* @param    mixed $type optional type name
2973
	* @param	mixed $value optional value
2974
	* @param	mixed $element_ns optional namespace of value
2975
	* @param	mixed $type_ns optional namespace of type
2976
	* @param	mixed $attributes associative array of attributes to add to element serialization
2977
	* @access   public
2978
	*/
2979
  	function soapval($name='soapval',$type=false,$value=-1,$element_ns=false,$type_ns=false,$attributes=false) {
2980
		parent::nusoap_base();
2981
		$this->name = $name;
2982
		$this->type = $type;
2983
		$this->value = $value;
2984
		$this->element_ns = $element_ns;
2985
		$this->type_ns = $type_ns;
2986
		$this->attributes = $attributes;
2987
    }
2988
2989
	/**
2990
	* return serialized value
2991
	*
2992
	* @param	string $use The WSDL use value (encoded|literal)
2993
	* @return	string XML data
2994
	* @access   public
2995
	*/
2996
	function serialize($use='encoded') {
2997
		return $this->serialize_val($this->value, $this->name, $this->type, $this->element_ns, $this->type_ns, $this->attributes, $use, true);
2998
    }
2999
3000
	/**
3001
	* decodes a soapval object into a PHP native type
3002
	*
3003
	* @return	mixed
3004
	* @access   public
3005
	*/
3006
	function decode(){
3007
		return $this->value;
3008
	}
3009
}
3010
3011
3012
3013
?><?php
3014
3015
/*
3016
3017
Modification information for LGPL compliance
3018
3019
r58622 - 2010-10-22 18:18:59 -0700 (Fri, 22 Oct 2010) - engsvnbuild - Author: lam <[email protected]>
3020
    bug 40066
3021
3022
r58361 - 2010-09-29 16:59:02 -0700 (Wed, 29 Sep 2010) - kjing - Author: Jenny Gonsalves <[email protected]>
3023
    Merging with maint_6_0_1 (svn merge -r 58250:58342)
3024
3025
r57813 - 2010-08-19 10:34:44 -0700 (Thu, 19 Aug 2010) - kjing - Author: John Mertic <[email protected]>
3026
    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.
3027
3028
r57707 - 2010-08-10 12:26:13 -0700 (Tue, 10 Aug 2010) - kjing - Author: Stanislav Malyshev <[email protected]>
3029
    fix SOAP calls with no parameters
3030
3031
r56990 - 2010-06-16 13:05:36 -0700 (Wed, 16 Jun 2010) - kjing - snapshot "Mango" svn branch to a new one for GitHub sync
3032
3033
r56989 - 2010-06-16 13:01:33 -0700 (Wed, 16 Jun 2010) - kjing - defunt "Mango" svn dev branch before github cutover
3034
3035
r55980 - 2010-04-19 13:31:28 -0700 (Mon, 19 Apr 2010) - kjing - create Mango (6.1) based on windex
3036
3037
r51719 - 2009-10-22 10:18:00 -0700 (Thu, 22 Oct 2009) - mitani - Converted to Build 3  tags and updated the build system
3038
3039
r51634 - 2009-10-19 13:32:22 -0700 (Mon, 19 Oct 2009) - mitani - Windex is the branch for Sugar Sales 1.0 development
3040
3041
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.
3042
3043
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.
3044
3045
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:
3046
- Changing all ereg function to either preg or simple string based ones
3047
- No more references to magic quotes.
3048
- Change all the session_unregister() functions to just unset() the correct session variable instead.
3049
3050
r50375 - 2009-08-24 18:07:43 -0700 (Mon, 24 Aug 2009) - dwong - branch kobe2 from tokyo r50372
3051
3052
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
3053
3054
r45680 - 2009-03-30 14:34:35 -0700 (Mon, 30 Mar 2009) - Samir Gandhi - modifeid serializeSchema to generate WS-I compliant WSDL
3055
3056
r42807 - 2008-12-29 11:16:59 -0800 (Mon, 29 Dec 2008) - dwong - Branch from trunk/sugarcrm r42806 to branches/tokyo/sugarcrm
3057
3058
r42645 - 2008-12-18 13:41:08 -0800 (Thu, 18 Dec 2008) - awu - merging maint_5_2_0 rev41336:HEAD to trunk
3059
3060
r41647 - 2008-11-11 17:44:30 -0800 (Tue, 11 Nov 2008) - majed - Fixes a few bugs
3061
3062
r41596 - 2008-11-10 19:20:04 -0800 (Mon, 10 Nov 2008) - Samir Gandhi - modified to set $method in the code
3063
3064
r41558 - 2008-11-10 14:35:34 -0800 (Mon, 10 Nov 2008) - majed - changes nusoap to allow for registering classes
3065
3066
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.
3067
Touched:
3068
- data/SugarBean.php
3069
- include/domit/php_http_client_generic.php
3070
- include/domit/php_http_connector.php
3071
- include/domit/testing_domit.php
3072
- include/domit/xml_domit_getelementsbypath.php
3073
- include/domit/xml_domit_lite_parser.php
3074
- include/domit/xml_domit_nodemaps.php
3075
- include/domit/xml_domit_parser.php
3076
- include/domit/xml_domit_shared.php
3077
- include/generic/SugarWidgets/SugarWidgetField.php
3078
- include/generic/SugarWidgets/SugarWidgetReportField.php
3079
- include/ListView/ProcessView.php
3080
- include/nusoap/class.soapclient.php
3081
- include/nusoap/nusoap.php
3082
- include/nusoap/nusoapmime.php
3083
- include/Pear/HTML_Safe/Safe.php
3084
- include/Pear/XML_HTMLSax3/HTMLSax3.php
3085
- modules/Administration/RebuildWorkFlow.php
3086
- modules/Expressions/RelateSelector.php
3087
- modules/Reports/templates/templates_reports.php
3088
- modules/WorkFlow/Delete.php
3089
- modules/WorkFlow/Save.php
3090
- modules/WorkFlow/SaveSequence.php
3091
- modules/WorkFlow/WorkFlow.php
3092
- modules/WorkFlowActionShells/CreateStep1.php
3093
- modules/WorkFlowActionShells/CreateStep2.php
3094
- modules/WorkFlowActionShells/Save.php
3095
- modules/WorkFlowActionShells/WorkFlowActionShell.php
3096
- modules/WorkFlowAlerts/Save.php
3097
- modules/WorkFlowAlerts/WorkFlowAlert.php
3098
- modules/WorkFlowAlertShells/DetailView.php
3099
- modules/WorkFlowAlertShells/WorkFlowAlertShell.php
3100
- modules/WorkFlowTriggerShells/CreateStep1.php
3101
- modules/WorkFlowTriggerShells/CreateStepFilter.php
3102
- modules/WorkFlowTriggerShells/SaveFilter.php
3103
- modules/WorkFlowTriggerShells/WorkFlowTriggerShell.php
3104
- soap/SoapHelperFunctions.php
3105
- test/modules/DynamicFields/DynamicFields_Bug24095_test.php
3106
- test/simpletest/browser.php
3107
- test/simpletest/default_reporter.php
3108
- test/simpletest/detached.php
3109
- test/simpletest/eclipse.php
3110
- test/simpletest/expectation.php
3111
- test/simpletest/extensions/pear_test_case.php
3112
- test/simpletest/form.php
3113
- test/simpletest/http.php
3114
- test/simpletest/mock_objects.php
3115
- test/simpletest/page.php
3116
- test/simpletest/parser.php
3117
- test/simpletest/remote.php
3118
- test/simpletest/shell_tester.php
3119
- test/simpletest/simple_test.php
3120
- test/simpletest/simpletest.php
3121
- test/simpletest/test/acceptance_test.php
3122
- test/simpletest/test/adapter_test.php
3123
- test/simpletest/test/authentication_test.php
3124
- test/simpletest/test/browser_test.php
3125
- test/simpletest/test/collector_test.php
3126
- test/simpletest/test/compatibility_test.php
3127
- test/simpletest/test/detached_test.php
3128
- test/simpletest/test/eclipse_test.php
3129
- test/simpletest/test/encoding_test.php
3130
- test/simpletest/test/errors_test.php
3131
- test/simpletest/test/expectation_test.php
3132
- test/simpletest/test/form_test.php
3133
- test/simpletest/test/frames_test.php
3134
- test/simpletest/test/http_test.php
3135
- test/simpletest/test/live_test.php
3136
- test/simpletest/test/mock_objects_test.php
3137
- test/simpletest/test/page_test.php
3138
- test/simpletest/test/parse_error_test.php
3139
- test/simpletest/test/parser_test.php
3140
- test/simpletest/test/remote_test.php
3141
- test/simpletest/test/shell_test.php
3142
- test/simpletest/test/shell_tester_test.php
3143
- test/simpletest/test/simpletest_test.php
3144
- test/simpletest/test/site/page_request.php
3145
- test/simpletest/test/tag_test.php
3146
- test/simpletest/test/unit_tester_test.php
3147
- test/simpletest/test/user_agent_test.php
3148
- test/simpletest/test/visual_test.php
3149
- test/simpletest/test/xml_test.php
3150
- test/simpletest/test_case.php
3151
- test/simpletest/ui/array_reporter/test.php
3152
- test/simpletest/ui/recorder/test.php
3153
- test/simpletest/unit_tester.php
3154
- test/simpletest/url.php
3155
- test/simpletest/user_agent.php
3156
- test/simpletest/web_tester.php
3157
- test/spikephpcoverage/src/PEAR.php
3158
- test/spikephpcoverage/src/util/Utility.php
3159
- test/spikephpcoverage/src/XML/Parser.php
3160
- test/spikephpcoverage/src/XML/Parser/Simple.php
3161
- test/test_utilities/SugarTest_SimpleBrowser.php
3162
3163
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.
3164
3165
r38300 - 2008-07-25 13:33:43 -0700 (Fri, 25 Jul 2008) - Samir Gandhi - put the debug in parseresponse function
3166
3167
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
3168
3169
r36824 - 2008-06-18 09:26:11 -0700 (Wed, 18 Jun 2008) - roger - bug: 21832
3170
3171
r26422 - 2007-09-05 17:29:12 -0700 (Wed, 05 Sep 2007) - majed - migrate from beta 1 to trunk
3172
3173
r15787 - 2006-08-10 10:14:41 -0700 (Thu, 10 Aug 2006) - roger - RRS: bug 7961
3174
3175
r14701 - 2006-07-17 13:37:26 -0700 (Mon, 17 Jul 2006) - roger - RRS: bug 5801
3176
3177
r13782 - 2006-06-06 10:58:55 -0700 (Tue, 06 Jun 2006) - majed - changes entry point code
3178
3179
r11466 - 2006-02-01 15:49:47 -0800 (Wed, 01 Feb 2006) - jacob - Adding extra !empty check to get around a PHP warning.
3180
3181
r11115 - 2006-01-17 14:54:45 -0800 (Tue, 17 Jan 2006) - majed - add entry point validation
3182
3183
r10585 - 2005-12-13 14:42:26 -0800 (Tue, 13 Dec 2005) - majed - adds new license mechanisim
3184
3185
r10170 - 2005-12-05 18:37:46 -0800 (Mon, 05 Dec 2005) - majed - fixes various issues
3186
3187
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.
3188
3189
r8991 - 2005-11-03 19:07:25 -0800 (Thu, 03 Nov 2005) - majed - fixes nusoap issue
3190
3191
r8846 - 2005-10-31 11:01:12 -0800 (Mon, 31 Oct 2005) - majed - new version of nusoap
3192
3193
r7905 - 2005-09-21 19:12:57 -0700 (Wed, 21 Sep 2005) - majed - restores old nusoap pre & with a few fixes
3194
3195
r7861 - 2005-09-20 15:40:25 -0700 (Tue, 20 Sep 2005) - majed - & fix for 3.5.1
3196
3197
r7452 - 2005-08-17 11:32:34 -0700 (Wed, 17 Aug 2005) - majed - changes soap to nusoap
3198
3199
r5820 - 2005-06-21 14:22:24 -0700 (Tue, 21 Jun 2005) - majed - fixes issues with nusoap and with custom fields
3200
3201
r5462 - 2005-05-25 13:50:11 -0700 (Wed, 25 May 2005) - majed - upgraded nusoap to .6.9
3202
3203
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
3204
3205
r573 - 2004-09-04 13:03:32 -0700 (Sat, 04 Sep 2004) - sugarclint - undoing copyrights added in inadvertantly.  --clint
3206
3207
r546 - 2004-09-03 11:49:38 -0700 (Fri, 03 Sep 2004) - sugarmsi - removed echo count
3208
3209
r354 - 2004-08-02 23:00:37 -0700 (Mon, 02 Aug 2004) - sugarjacob - Adding Soap
3210
3211
3212
*/
3213
3214
3215
3216
3217
3218
/**
3219
* transport class for sending/receiving data via HTTP and HTTPS
3220
* NOTE: PHP must be compiled with the CURL extension for HTTPS support
3221
*
3222
* @author   Dietrich Ayala <[email protected]>
3223
* @author   Scott Nichol <[email protected]>
3224
3225
* @access public
3226
*/
3227
class soap_transport_http extends nusoap_base {
0 ignored issues
show
Comprehensibility Best Practice introduced by
The type soap_transport_http has been defined more than once; this definition is ignored, only the first definition in include/nusoap/class.soap_transport_http.php (L67-1356) is considered.

This check looks for classes that have been defined more than once.

If you can, we would recommend to use standard object-oriented programming techniques. For example, to avoid multiple types, it might make sense to create a common interface, and then multiple, different implementations for that interface.

This also has the side-effect of providing you with better IDE auto-completion, static analysis and also better OPCode caching from PHP.

Loading history...
Coding Style Compatibility introduced by
PSR1 recommends that each class should be in its own file to aid autoloaders.

Having each class in a dedicated file usually plays nice with PSR autoloaders and is therefore a well established practice. If you use other autoloaders, you might not want to follow this rule.

Loading history...
3228
3229
	var $url = '';
3230
	var $uri = '';
3231
	var $digest_uri = '';
3232
	var $scheme = '';
3233
	var $host = '';
3234
	var $port = '';
3235
	var $path = '';
3236
	var $request_method = 'POST';
3237
	var $protocol_version = '1.0';
3238
	var $encoding = '';
3239
	var $outgoing_headers = array();
3240
	var $incoming_headers = array();
3241
	var $incoming_cookies = array();
3242
	var $outgoing_payload = '';
3243
	var $incoming_payload = '';
3244
	var $response_status_line;	// HTTP response status line
3245
	var $useSOAPAction = true;
3246
	var $persistentConnection = false;
3247
	var $ch = false;	// cURL handle
3248
	var $ch_options = array();	// cURL custom options
3249
	var $use_curl = false;		// force cURL use
3250
	var $proxy = null;			// proxy information (associative array)
3251
	var $username = '';
3252
	var $password = '';
3253
	var $authtype = '';
3254
	var $digestRequest = array();
3255
	var $certRequest = array();	// keys must be cainfofile (optional), sslcertfile, sslkeyfile, passphrase, certpassword (optional), verifypeer (optional), verifyhost (optional)
3256
								// cainfofile: certificate authority file, e.g. '$pathToPemFiles/rootca.pem'
3257
								// sslcertfile: SSL certificate file, e.g. '$pathToPemFiles/mycert.pem'
3258
								// sslkeyfile: SSL key file, e.g. '$pathToPemFiles/mykey.pem'
3259
								// passphrase: SSL key password/passphrase
3260
								// certpassword: SSL certificate password
3261
								// verifypeer: default is 1
3262
								// verifyhost: default is 1
3263
3264
	/**
3265
	* constructor
3266
	*
3267
	* @param string $url The URL to which to connect
3268
	* @param array $curl_options User-specified cURL options
3269
	* @param boolean $use_curl Whether to try to force cURL use
3270
	* @access public
3271
	*/
3272
	function soap_transport_http($url, $curl_options = NULL, $use_curl = false){
3273
		parent::nusoap_base();
3274
		$this->debug("ctor url=$url use_curl=$use_curl curl_options:");
3275
		$this->appendDebug($this->varDump($curl_options));
3276
		$this->setURL($url);
3277
		if (is_array($curl_options)) {
3278
			$this->ch_options = $curl_options;
3279
		}
3280
		$this->use_curl = $use_curl;
3281
		preg_match('/\$Revisio' . 'n: ([^ ]+)/', $this->revision, $rev);
3282
		$this->setHeader('User-Agent', $this->title.'/'.$this->version.' ('.$rev[1].')');
3283
	}
3284
3285
	/**
3286
	* sets a cURL option
3287
	*
3288
	* @param	mixed $option The cURL option (always integer?)
3289
	* @param	mixed $value The cURL option value
3290
	* @access   private
3291
	*/
3292
	function setCurlOption($option, $value) {
3293
		$this->debug("setCurlOption option=$option, value=");
3294
		$this->appendDebug($this->varDump($value));
3295
		curl_setopt($this->ch, $option, $value);
3296
	}
3297
3298
	/**
3299
	* sets an HTTP header
3300
	*
3301
	* @param string $name The name of the header
3302
	* @param string $value The value of the header
3303
	* @access private
3304
	*/
3305
	function setHeader($name, $value) {
3306
		$this->outgoing_headers[$name] = $value;
3307
		$this->debug("set header $name: $value");
3308
	}
3309
3310
	/**
3311
	* unsets an HTTP header
3312
	*
3313
	* @param string $name The name of the header
3314
	* @access private
3315
	*/
3316
	function unsetHeader($name) {
3317
		if (isset($this->outgoing_headers[$name])) {
3318
			$this->debug("unset header $name");
3319
			unset($this->outgoing_headers[$name]);
3320
		}
3321
	}
3322
3323
	/**
3324
	* sets the URL to which to connect
3325
	*
3326
	* @param string $url The URL to which to connect
3327
	* @access private
3328
	*/
3329
	function setURL($url) {
3330
		$this->url = $url;
3331
3332
		$u = parse_url($url);
3333
		foreach($u as $k => $v){
0 ignored issues
show
The expression $u of type array<string,string>|false is not guaranteed to be traversable. How about adding an additional type check?

There are different options of fixing this problem.

  1. If you want to be on the safe side, you can add an additional type-check:

    $collection = json_decode($data, true);
    if ( ! is_array($collection)) {
        throw new \RuntimeException('$collection must be an array.');
    }
    
    foreach ($collection as $item) { /** ... */ }
    
  2. If you are sure that the expression is traversable, you might want to add a doc comment cast to improve IDE auto-completion and static analysis:

    /** @var array $collection */
    $collection = json_decode($data, true);
    
    foreach ($collection as $item) { /** .. */ }
    
  3. Mark the issue as a false-positive: Just hover the remove button, in the top-right corner of this issue for more options.

Loading history...
3334
			$this->debug("parsed URL $k = $v");
3335
			$this->$k = $v;
3336
		}
3337
3338
		// add any GET params to path
3339
		if(isset($u['query']) && $u['query'] != ''){
3340
            $this->path .= '?' . $u['query'];
3341
		}
3342
3343
		// set default port
3344
		if(!isset($u['port'])){
3345
			if($u['scheme'] == 'https'){
3346
				$this->port = 443;
0 ignored issues
show
Documentation Bug introduced by
The property $port was declared of type string, but 443 is of type integer. Maybe add a type cast?

This check looks for assignments to scalar types that may be of the wrong type.

To ensure the code behaves as expected, it may be a good idea to add an explicit type cast.

$answer = 42;

$correct = false;

$correct = (bool) $answer;
Loading history...
3347
			} else {
3348
				$this->port = 80;
0 ignored issues
show
Documentation Bug introduced by
The property $port was declared of type string, but 80 is of type integer. Maybe add a type cast?

This check looks for assignments to scalar types that may be of the wrong type.

To ensure the code behaves as expected, it may be a good idea to add an explicit type cast.

$answer = 42;

$correct = false;

$correct = (bool) $answer;
Loading history...
3349
			}
3350
		}
3351
3352
		$this->uri = $this->path;
3353
		$this->digest_uri = $this->uri;
3354
3355
		// build headers
3356
		if (!isset($u['port'])) {
3357
			$this->setHeader('Host', $this->host);
3358
		} else {
3359
			$this->setHeader('Host', $this->host.':'.$this->port);
3360
		}
3361
3362
		if (isset($u['user']) && $u['user'] != '') {
3363
			$this->setCredentials(urldecode($u['user']), isset($u['pass']) ? urldecode($u['pass']) : '');
3364
		}
3365
	}
3366
3367
	/**
3368
	* gets the I/O method to use
3369
	*
3370
	* @return	string	I/O method to use (socket|curl|unknown)
3371
	* @access	private
3372
	*/
3373
	function io_method() {
3374
		if ($this->use_curl || ($this->scheme == 'https') || ($this->scheme == 'http' && $this->authtype == 'ntlm') || ($this->scheme == 'http' && is_array($this->proxy) && $this->proxy['authtype'] == 'ntlm'))
3375
			return 'curl';
3376
		if (($this->scheme == 'http' || $this->scheme == 'ssl') && $this->authtype != 'ntlm' && (!is_array($this->proxy) || $this->proxy['authtype'] != 'ntlm'))
3377
			return 'socket';
3378
		return 'unknown';
3379
	}
3380
3381
	/**
3382
	* establish an HTTP connection
3383
	*
3384
	* @param    integer $timeout set connection timeout in seconds
0 ignored issues
show
There is no parameter named $timeout. Did you maybe mean $connection_timeout?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function. It has, however, found a similar but not annotated parameter which might be a good fit.

Consider the following example. The parameter $ireland is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $ireland
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was changed, but the annotation was not.

Loading history...
3385
	* @param	integer $response_timeout set response timeout in seconds
3386
	* @return	boolean true if connected, false if not
3387
	* @access   private
3388
	*/
3389
	function connect($connection_timeout=0,$response_timeout=30){
3390
	  	// For PHP 4.3 with OpenSSL, change https scheme to ssl, then treat like
3391
	  	// "regular" socket.
3392
	  	// TODO: disabled for now because OpenSSL must be *compiled* in (not just
3393
	  	//       loaded), and until PHP5 stream_get_wrappers is not available.
3394
//	  	if ($this->scheme == 'https') {
3395
//		  	if (version_compare(phpversion(), '4.3.0') >= 0) {
3396
//		  		if (extension_loaded('openssl')) {
3397
//		  			$this->scheme = 'ssl';
3398
//		  			$this->debug('Using SSL over OpenSSL');
3399
//		  		}
3400
//		  	}
3401
//		}
3402
		$this->debug("connect connection_timeout $connection_timeout, response_timeout $response_timeout, scheme $this->scheme, host $this->host, port $this->port");
3403
	  if ($this->io_method() == 'socket') {
3404
		if (!is_array($this->proxy)) {
3405
			$host = $this->host;
3406
			$port = $this->port;
3407
		} else {
3408
			$host = $this->proxy['host'];
3409
			$port = $this->proxy['port'];
3410
		}
3411
3412
		// use persistent connection
3413
		if($this->persistentConnection && isset($this->fp) && is_resource($this->fp)){
3414
			if (!feof($this->fp)) {
3415
				$this->debug('Re-use persistent connection');
3416
				return true;
3417
			}
3418
			fclose($this->fp);
3419
			$this->debug('Closed persistent connection at EOF');
3420
		}
3421
3422
		// munge host if using OpenSSL
3423
		if ($this->scheme == 'ssl') {
3424
			$host = 'ssl://' . $host;
3425
		}
3426
		$this->debug('calling fsockopen with host ' . $host . ' connection_timeout ' . $connection_timeout);
3427
3428
		// open socket
3429
		if($connection_timeout > 0){
3430
			$this->fp = @fsockopen( $host, $port, $this->errno, $this->error_str, $connection_timeout);
3431
		} else {
3432
			$this->fp = @fsockopen( $host, $port, $this->errno, $this->error_str);
3433
		}
3434
3435
		// test pointer
3436
		if(!$this->fp) {
3437
			$msg = 'Couldn\'t open socket connection to server ' . $this->url;
3438
			if ($this->errno) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $this->errno of type integer|null is loosely compared to true; this is ambiguous if the integer can be zero. You might want to explicitly use !== null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For integer values, zero is a special case, in particular the following results might be unexpected:

0   == false // true
0   == null  // true
123 == false // false
123 == null  // false

// It is often better to use strict comparison
0 === false // false
0 === null  // false
Loading history...
3439
				$msg .= ', Error ('.$this->errno.'): '.$this->error_str;
3440
			} else {
3441
				$msg .= ' prior to connect().  This is often a problem looking up the host name.';
3442
			}
3443
			$this->debug($msg);
3444
			$this->setError($msg);
3445
			return false;
3446
		}
3447
3448
		// set response timeout
3449
		$this->debug('set response timeout to ' . $response_timeout);
3450
		socket_set_timeout( $this->fp, $response_timeout);
3451
3452
		$this->debug('socket connected');
3453
		return true;
3454
	  } else if ($this->io_method() == 'curl') {
3455
		if (!extension_loaded('curl')) {
3456
//			$this->setError('cURL Extension, or OpenSSL extension w/ PHP version >= 4.3 is required for HTTPS');
3457
			$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.');
3458
			return false;
3459
		}
3460
		// Avoid warnings when PHP does not have these options
3461
		if (defined('CURLOPT_CONNECTIONTIMEOUT'))
3462
			$CURLOPT_CONNECTIONTIMEOUT = CURLOPT_CONNECTIONTIMEOUT;
3463
		else
3464
			$CURLOPT_CONNECTIONTIMEOUT = 78;
3465
		if (defined('CURLOPT_HTTPAUTH'))
3466
			$CURLOPT_HTTPAUTH = CURLOPT_HTTPAUTH;
3467
		else
3468
			$CURLOPT_HTTPAUTH = 107;
3469
		if (defined('CURLOPT_PROXYAUTH'))
3470
			$CURLOPT_PROXYAUTH = CURLOPT_PROXYAUTH;
3471
		else
3472
			$CURLOPT_PROXYAUTH = 111;
3473
		if (defined('CURLAUTH_BASIC'))
3474
			$CURLAUTH_BASIC = CURLAUTH_BASIC;
3475
		else
3476
			$CURLAUTH_BASIC = 1;
3477
		if (defined('CURLAUTH_DIGEST'))
3478
			$CURLAUTH_DIGEST = CURLAUTH_DIGEST;
3479
		else
3480
			$CURLAUTH_DIGEST = 2;
3481
		if (defined('CURLAUTH_NTLM'))
3482
			$CURLAUTH_NTLM = CURLAUTH_NTLM;
3483
		else
3484
			$CURLAUTH_NTLM = 8;
3485
3486
		$this->debug('connect using cURL');
3487
		// init CURL
3488
		$this->ch = curl_init();
3489
		// set url
3490
		$hostURL = ($this->port != '') ? "$this->scheme://$this->host:$this->port" : "$this->scheme://$this->host";
3491
		// add path
3492
		$hostURL .= $this->path;
3493
		$this->setCurlOption(CURLOPT_URL, $hostURL);
3494
		// follow location headers (re-directs)
3495
		if (ini_get('safe_mode') || ini_get('open_basedir')) {
3496
			$this->debug('safe_mode or open_basedir set, so do not set CURLOPT_FOLLOWLOCATION');
3497
			$this->debug('safe_mode = ');
3498
			$this->appendDebug($this->varDump(ini_get('safe_mode')));
3499
			$this->debug('open_basedir = ');
3500
			$this->appendDebug($this->varDump(ini_get('open_basedir')));
3501
		} else {
3502
			$this->setCurlOption(CURLOPT_FOLLOWLOCATION, 1);
3503
		}
3504
		// ask for headers in the response output
3505
		$this->setCurlOption(CURLOPT_HEADER, 1);
3506
		// ask for the response output as the return value
3507
		$this->setCurlOption(CURLOPT_RETURNTRANSFER, 1);
3508
		// encode
3509
		// We manage this ourselves through headers and encoding
3510
//		if(function_exists('gzuncompress')){
3511
//			$this->setCurlOption(CURLOPT_ENCODING, 'deflate');
3512
//		}
3513
		// persistent connection
3514
		if ($this->persistentConnection) {
3515
			// I believe the following comment is now bogus, having applied to
3516
			// the code when it used CURLOPT_CUSTOMREQUEST to send the request.
3517
			// The way we send data, we cannot use persistent connections, since
3518
			// there will be some "junk" at the end of our request.
3519
			//$this->setCurlOption(CURL_HTTP_VERSION_1_1, true);
3520
			$this->persistentConnection = false;
3521
			$this->setHeader('Connection', 'close');
3522
		}
3523
		// set timeouts
3524
		if ($connection_timeout != 0) {
3525
			$this->setCurlOption($CURLOPT_CONNECTIONTIMEOUT, $connection_timeout);
3526
		}
3527
		if ($response_timeout != 0) {
3528
			$this->setCurlOption(CURLOPT_TIMEOUT, $response_timeout);
3529
		}
3530
3531
		if ($this->scheme == 'https') {
3532
			$this->debug('set cURL SSL verify options');
3533
			// recent versions of cURL turn on peer/host checking by default,
3534
			// while PHP binaries are not compiled with a default location for the
3535
			// CA cert bundle, so disable peer/host checking.
3536
			//$this->setCurlOption(CURLOPT_CAINFO, 'f:\php-4.3.2-win32\extensions\curl-ca-bundle.crt');
3537
			$this->setCurlOption(CURLOPT_SSL_VERIFYPEER, 0);
3538
			$this->setCurlOption(CURLOPT_SSL_VERIFYHOST, 0);
3539
3540
			// support client certificates (thanks Tobias Boes, Doug Anarino, Eryan Ariobowo)
3541
			if ($this->authtype == 'certificate') {
3542
				$this->debug('set cURL certificate options');
3543
				if (isset($this->certRequest['cainfofile'])) {
3544
					$this->setCurlOption(CURLOPT_CAINFO, $this->certRequest['cainfofile']);
3545
				}
3546
				if (isset($this->certRequest['verifypeer'])) {
3547
					$this->setCurlOption(CURLOPT_SSL_VERIFYPEER, $this->certRequest['verifypeer']);
3548
				} else {
3549
					$this->setCurlOption(CURLOPT_SSL_VERIFYPEER, 1);
3550
				}
3551
				if (isset($this->certRequest['verifyhost'])) {
3552
					$this->setCurlOption(CURLOPT_SSL_VERIFYHOST, $this->certRequest['verifyhost']);
3553
				} else {
3554
					$this->setCurlOption(CURLOPT_SSL_VERIFYHOST, 1);
3555
				}
3556
				if (isset($this->certRequest['sslcertfile'])) {
3557
					$this->setCurlOption(CURLOPT_SSLCERT, $this->certRequest['sslcertfile']);
3558
				}
3559
				if (isset($this->certRequest['sslkeyfile'])) {
3560
					$this->setCurlOption(CURLOPT_SSLKEY, $this->certRequest['sslkeyfile']);
3561
				}
3562
				if (isset($this->certRequest['passphrase'])) {
3563
					$this->setCurlOption(CURLOPT_SSLKEYPASSWD, $this->certRequest['passphrase']);
3564
				}
3565
				if (isset($this->certRequest['certpassword'])) {
3566
					$this->setCurlOption(CURLOPT_SSLCERTPASSWD, $this->certRequest['certpassword']);
3567
				}
3568
			}
3569
		}
3570
		if ($this->authtype && ($this->authtype != 'certificate')) {
3571
			if ($this->username) {
3572
				$this->debug('set cURL username/password');
3573
				$this->setCurlOption(CURLOPT_USERPWD, "$this->username:$this->password");
3574
			}
3575
			if ($this->authtype == 'basic') {
3576
				$this->debug('set cURL for Basic authentication');
3577
				$this->setCurlOption($CURLOPT_HTTPAUTH, $CURLAUTH_BASIC);
3578
			}
3579
			if ($this->authtype == 'digest') {
3580
				$this->debug('set cURL for digest authentication');
3581
				$this->setCurlOption($CURLOPT_HTTPAUTH, $CURLAUTH_DIGEST);
3582
			}
3583
			if ($this->authtype == 'ntlm') {
3584
				$this->debug('set cURL for NTLM authentication');
3585
				$this->setCurlOption($CURLOPT_HTTPAUTH, $CURLAUTH_NTLM);
3586
			}
3587
		}
3588
		if (is_array($this->proxy)) {
3589
			$this->debug('set cURL proxy options');
3590
			if ($this->proxy['port'] != '') {
3591
				$this->setCurlOption(CURLOPT_PROXY, $this->proxy['host'].':'.$this->proxy['port']);
3592
			} else {
3593
				$this->setCurlOption(CURLOPT_PROXY, $this->proxy['host']);
3594
			}
3595
			if ($this->proxy['username'] || $this->proxy['password']) {
3596
				$this->debug('set cURL proxy authentication options');
3597
				$this->setCurlOption(CURLOPT_PROXYUSERPWD, $this->proxy['username'].':'.$this->proxy['password']);
3598
				if ($this->proxy['authtype'] == 'basic') {
3599
					$this->setCurlOption($CURLOPT_PROXYAUTH, $CURLAUTH_BASIC);
3600
				}
3601
				if ($this->proxy['authtype'] == 'ntlm') {
3602
					$this->setCurlOption($CURLOPT_PROXYAUTH, $CURLAUTH_NTLM);
3603
				}
3604
			}
3605
		}
3606
		$this->debug('cURL connection set up');
3607
		return true;
3608
	  } else {
3609
		$this->setError('Unknown scheme ' . $this->scheme);
3610
		$this->debug('Unknown scheme ' . $this->scheme);
3611
		return false;
3612
	  }
3613
	}
3614
3615
	/**
3616
	* sends the SOAP request and gets the SOAP response via HTTP[S]
3617
	*
3618
	* @param    string $data message data
3619
	* @param    integer $timeout set connection timeout in seconds
3620
	* @param	integer $response_timeout set response timeout in seconds
3621
	* @param	array $cookies cookies to send
3622
	* @return	string data
3623
	* @access   public
3624
	*/
3625
	function send($data, $timeout=0, $response_timeout=30, $cookies=NULL) {
3626
3627
		$this->debug('entered send() with data of length: '.strlen($data));
3628
3629
		$this->tryagain = true;
3630
		$tries = 0;
3631
		while ($this->tryagain) {
3632
			$this->tryagain = false;
3633
			if ($tries++ < 2) {
3634
				// make connnection
3635
				if (!$this->connect($timeout, $response_timeout)){
3636
					return false;
3637
				}
3638
3639
				// send request
3640
				if (!$this->sendRequest($data, $cookies)){
3641
					return false;
3642
				}
3643
3644
				// get response
3645
				$respdata = $this->getResponse();
3646
			} else {
3647
				$this->setError("Too many tries to get an OK response ($this->response_status_line)");
3648
			}
3649
		}
3650
		$this->debug('end of send()');
3651
		return $respdata;
3652
	}
3653
3654
3655
	/**
3656
	* sends the SOAP request and gets the SOAP response via HTTPS using CURL
3657
	*
3658
	* @param    string $data message data
3659
	* @param    integer $timeout set connection timeout in seconds
3660
	* @param	integer $response_timeout set response timeout in seconds
3661
	* @param	array $cookies cookies to send
3662
	* @return	string data
3663
	* @access   public
3664
	* @deprecated
3665
	*/
3666
	function sendHTTPS($data, $timeout=0, $response_timeout=30, $cookies) {
3667
		return $this->send($data, $timeout, $response_timeout, $cookies);
3668
	}
3669
3670
	/**
3671
	* if authenticating, set user credentials here
3672
	*
3673
	* @param    string $username
3674
	* @param    string $password
3675
	* @param	string $authtype (basic|digest|certificate|ntlm)
3676
	* @param	array $digestRequest (keys must be nonce, nc, realm, qop)
3677
	* @param	array $certRequest (keys must be cainfofile (optional), sslcertfile, sslkeyfile, passphrase, certpassword (optional), verifypeer (optional), verifyhost (optional): see corresponding options in cURL docs)
3678
	* @access   public
3679
	*/
3680
	function setCredentials($username, $password, $authtype = 'basic', $digestRequest = array(), $certRequest = array()) {
3681
		$this->debug("setCredentials username=$username authtype=$authtype digestRequest=");
3682
		$this->appendDebug($this->varDump($digestRequest));
3683
		$this->debug("certRequest=");
3684
		$this->appendDebug($this->varDump($certRequest));
3685
		// cf. RFC 2617
3686
		if ($authtype == 'basic') {
3687
			$this->setHeader('Authorization', 'Basic '.base64_encode(str_replace(':','',$username).':'.$password));
3688
		} elseif ($authtype == 'digest') {
3689
			if (isset($digestRequest['nonce'])) {
3690
				$digestRequest['nc'] = isset($digestRequest['nc']) ? $digestRequest['nc']++ : 1;
3691
3692
				// calculate the Digest hashes (calculate code based on digest implementation found at: http://www.rassoc.com/gregr/weblog/stories/2002/07/09/webServicesSecurityHttpDigestAuthenticationWithoutActiveDirectory.html)
3693
3694
				// A1 = unq(username-value) ":" unq(realm-value) ":" passwd
3695
				$A1 = $username. ':' . (isset($digestRequest['realm']) ? $digestRequest['realm'] : '') . ':' . $password;
3696
3697
				// H(A1) = MD5(A1)
3698
				$HA1 = md5($A1);
3699
3700
				// A2 = Method ":" digest-uri-value
3701
				$A2 = $this->request_method . ':' . $this->digest_uri;
3702
3703
				// H(A2)
3704
				$HA2 =  md5($A2);
3705
3706
				// KD(secret, data) = H(concat(secret, ":", data))
3707
				// if qop == auth:
3708
				// request-digest  = <"> < KD ( H(A1),     unq(nonce-value)
3709
				//                              ":" nc-value
3710
				//                              ":" unq(cnonce-value)
3711
				//                              ":" unq(qop-value)
3712
				//                              ":" H(A2)
3713
				//                            ) <">
3714
				// if qop is missing,
3715
				// request-digest  = <"> < KD ( H(A1), unq(nonce-value) ":" H(A2) ) > <">
3716
3717
				$unhashedDigest = '';
3718
				$nonce = isset($digestRequest['nonce']) ? $digestRequest['nonce'] : '';
3719
				$cnonce = $nonce;
3720
				if ($digestRequest['qop'] != '') {
3721
					$unhashedDigest = $HA1 . ':' . $nonce . ':' . sprintf("%08d", $digestRequest['nc']) . ':' . $cnonce . ':' . $digestRequest['qop'] . ':' . $HA2;
3722
				} else {
3723
					$unhashedDigest = $HA1 . ':' . $nonce . ':' . $HA2;
3724
				}
3725
3726
				$hashedDigest = md5($unhashedDigest);
3727
3728
				$opaque = '';
3729
				if (isset($digestRequest['opaque'])) {
3730
					$opaque = ', opaque="' . $digestRequest['opaque'] . '"';
3731
				}
3732
3733
				$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 . '"');
3734
			}
3735
		} elseif ($authtype == 'certificate') {
3736
			$this->certRequest = $certRequest;
3737
			$this->debug('Authorization header not set for certificate');
3738
		} elseif ($authtype == 'ntlm') {
3739
			// do nothing
3740
			$this->debug('Authorization header not set for ntlm');
3741
		}
3742
		$this->username = $username;
3743
		$this->password = $password;
3744
		$this->authtype = $authtype;
3745
		$this->digestRequest = $digestRequest;
3746
	}
3747
3748
	/**
3749
	* set the soapaction value
3750
	*
3751
	* @param    string $soapaction
3752
	* @access   public
3753
	*/
3754
	function setSOAPAction($soapaction) {
3755
		$this->setHeader('SOAPAction', '"' . $soapaction . '"');
3756
	}
3757
3758
	/**
3759
	* use http encoding
3760
	*
3761
	* @param    string $enc encoding style. supported values: gzip, deflate, or both
3762
	* @access   public
3763
	*/
3764
	function setEncoding($enc='gzip, deflate') {
3765
		if (function_exists('gzdeflate')) {
3766
			$this->protocol_version = '1.1';
3767
			$this->setHeader('Accept-Encoding', $enc);
3768
			if (!isset($this->outgoing_headers['Connection'])) {
3769
				$this->setHeader('Connection', 'close');
3770
				$this->persistentConnection = false;
3771
			}
3772
			// deprecated as of PHP 5.3.0
3773
			//set_magic_quotes_runtime(0);
3774
			$this->encoding = $enc;
3775
		}
3776
	}
3777
3778
	/**
3779
	* set proxy info here
3780
	*
3781
	* @param    string $proxyhost use an empty string to remove proxy
3782
	* @param    string $proxyport
3783
	* @param	string $proxyusername
3784
	* @param	string $proxypassword
3785
	* @param	string $proxyauthtype (basic|ntlm)
3786
	* @access   public
3787
	*/
3788
	function setProxy($proxyhost, $proxyport, $proxyusername = '', $proxypassword = '', $proxyauthtype = 'basic') {
3789
		if ($proxyhost) {
3790
			$this->proxy = array(
3791
				'host' => $proxyhost,
3792
				'port' => $proxyport,
3793
				'username' => $proxyusername,
3794
				'password' => $proxypassword,
3795
				'authtype' => $proxyauthtype
3796
			);
3797
			if ($proxyusername != '' && $proxypassword != '' && $proxyauthtype = 'basic') {
3798
				$this->setHeader('Proxy-Authorization', ' Basic '.base64_encode($proxyusername.':'.$proxypassword));
3799
			}
3800
		} else {
3801
			$this->debug('remove proxy');
3802
			$proxy = null;
3803
			unsetHeader('Proxy-Authorization');
3804
		}
3805
	}
3806
3807
3808
	/**
3809
	 * Test if the given string starts with a header that is to be skipped.
3810
	 * Skippable headers result from chunked transfer and proxy requests.
3811
	 *
3812
	 * @param	string $data The string to check.
3813
	 * @returns	boolean	Whether a skippable header was found.
3814
	 * @access	private
3815
	 */
3816
	function isSkippableCurlHeader(&$data) {
3817
		$skipHeaders = array(	'HTTP/1.1 100',
3818
								'HTTP/1.0 301',
3819
								'HTTP/1.1 301',
3820
								'HTTP/1.0 302',
3821
								'HTTP/1.1 302',
3822
								'HTTP/1.0 401',
3823
								'HTTP/1.1 401',
3824
								'HTTP/1.0 200 Connection established');
3825
		foreach ($skipHeaders as $hd) {
3826
			$prefix = substr($data, 0, strlen($hd));
3827
			if ($prefix == $hd) return true;
3828
		}
3829
3830
		return false;
3831
	}
3832
3833
	/**
3834
	* decode a string that is encoded w/ "chunked' transfer encoding
3835
 	* as defined in RFC2068 19.4.6
3836
	*
3837
	* @param    string $buffer
3838
	* @param    string $lb
3839
	* @returns	string
3840
	* @access   public
3841
	* @deprecated
3842
	*/
3843
	function decodeChunked($buffer, $lb){
3844
		// length := 0
3845
		$length = 0;
3846
		$new = '';
3847
3848
		// read chunk-size, chunk-extension (if any) and CRLF
3849
		// get the position of the linebreak
3850
		$chunkend = strpos($buffer, $lb);
3851
		if ($chunkend == FALSE) {
0 ignored issues
show
Bug Best Practice introduced by
It seems like you are loosely comparing $chunkend of type integer to the boolean FALSE. If you are specifically checking for 0, consider using something more explicit like === 0 instead.
Loading history...
3852
			$this->debug('no linebreak found in decodeChunked');
3853
			return $new;
3854
		}
3855
		$temp = substr($buffer,0,$chunkend);
3856
		$chunk_size = hexdec( trim($temp) );
3857
		$chunkstart = $chunkend + strlen($lb);
3858
		// while (chunk-size > 0) {
3859
		while ($chunk_size > 0) {
3860
			$this->debug("chunkstart: $chunkstart chunk_size: $chunk_size");
3861
			$chunkend = strpos( $buffer, $lb, $chunkstart + $chunk_size);
3862
3863
			// Just in case we got a broken connection
3864
		  	if ($chunkend == FALSE) {
0 ignored issues
show
Bug Best Practice introduced by
It seems like you are loosely comparing $chunkend of type integer to the boolean FALSE. If you are specifically checking for 0, consider using something more explicit like === 0 instead.
Loading history...
3865
		  	    $chunk = substr($buffer,$chunkstart);
3866
				// append chunk-data to entity-body
3867
		    	$new .= $chunk;
3868
		  	    $length += strlen($chunk);
3869
		  	    break;
3870
			}
3871
3872
		  	// read chunk-data and CRLF
3873
		  	$chunk = substr($buffer,$chunkstart,$chunkend-$chunkstart);
3874
		  	// append chunk-data to entity-body
3875
		  	$new .= $chunk;
3876
		  	// length := length + chunk-size
3877
		  	$length += strlen($chunk);
3878
		  	// read chunk-size and CRLF
3879
		  	$chunkstart = $chunkend + strlen($lb);
3880
3881
		  	$chunkend = strpos($buffer, $lb, $chunkstart) + strlen($lb);
3882
			if ($chunkend == FALSE) {
0 ignored issues
show
Bug Best Practice introduced by
It seems like you are loosely comparing $chunkend of type integer to the boolean FALSE. If you are specifically checking for 0, consider using something more explicit like === 0 instead.
Loading history...
3883
				break; //Just in case we got a broken connection
3884
			}
3885
			$temp = substr($buffer,$chunkstart,$chunkend-$chunkstart);
3886
			$chunk_size = hexdec( trim($temp) );
3887
			$chunkstart = $chunkend;
3888
		}
3889
		return $new;
3890
	}
3891
3892
	/**
3893
	 * Writes the payload, including HTTP headers, to $this->outgoing_payload.
3894
	 *
3895
	 * @param	string $data HTTP body
3896
	 * @param	string $cookie_str data for HTTP Cookie header
3897
	 * @return	void
3898
	 * @access	private
3899
	 */
3900
	function buildPayload($data, $cookie_str = '') {
3901
		// Note: for cURL connections, $this->outgoing_payload is ignored,
3902
		// as is the Content-Length header, but these are still created as
3903
		// debugging guides.
3904
3905
		// add content-length header
3906
		if ($this->request_method != 'GET') {
3907
			$this->setHeader('Content-Length', strlen($data));
3908
		}
3909
3910
		// start building outgoing payload:
3911
		if ($this->proxy) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $this->proxy of type array<string,string> is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
3912
			$uri = $this->url;
3913
		} else {
3914
			$uri = $this->uri;
3915
		}
3916
		$req = "$this->request_method $uri HTTP/$this->protocol_version";
3917
		$this->debug("HTTP request: $req");
3918
		$this->outgoing_payload = "$req\r\n";
3919
3920
		// loop thru headers, serializing
3921
		foreach($this->outgoing_headers as $k => $v){
3922
			$hdr = $k.': '.$v;
3923
			$this->debug("HTTP header: $hdr");
3924
			$this->outgoing_payload .= "$hdr\r\n";
3925
		}
3926
3927
		// add any cookies
3928
		if ($cookie_str != '') {
3929
			$hdr = 'Cookie: '.$cookie_str;
3930
			$this->debug("HTTP header: $hdr");
3931
			$this->outgoing_payload .= "$hdr\r\n";
3932
		}
3933
3934
		// header/body separator
3935
		$this->outgoing_payload .= "\r\n";
3936
3937
		// add data
3938
		$this->outgoing_payload .= $data;
3939
	}
3940
3941
	/**
3942
	* sends the SOAP request via HTTP[S]
3943
	*
3944
	* @param    string $data message data
3945
	* @param	array $cookies cookies to send
3946
	* @return	boolean	true if OK, false if problem
3947
	* @access   private
3948
	*/
3949
	function sendRequest($data, $cookies = NULL) {
3950
		// build cookie string
3951
		$cookie_str = $this->getCookiesForRequest($cookies, (($this->scheme == 'ssl') || ($this->scheme == 'https')));
0 ignored issues
show
It seems like $cookies defined by parameter $cookies on line 3949 can also be of type null; however, soap_transport_http::getCookiesForRequest() does only seem to accept array, maybe add an additional type check?

This check looks at variables that have been passed in as parameters and are passed out again to other methods.

If the outgoing method call has stricter type requirements than the method itself, an issue is raised.

An additional type check may prevent trouble.

Loading history...
3952
3953
		// build payload
3954
		$this->buildPayload($data, $cookie_str);
3955
3956
	  if ($this->io_method() == 'socket') {
3957
		// send payload
3958
		if(!fputs($this->fp, $this->outgoing_payload, strlen($this->outgoing_payload))) {
3959
			$this->setError('couldn\'t write message data to socket');
3960
			$this->debug('couldn\'t write message data to socket');
3961
			return false;
3962
		}
3963
		$this->debug('wrote data to socket, length = ' . strlen($this->outgoing_payload));
3964
		return true;
3965
	  } else if ($this->io_method() == 'curl') {
3966
		// set payload
3967
		// cURL does say this should only be the verb, and in fact it
3968
		// turns out that the URI and HTTP version are appended to this, which
3969
		// some servers refuse to work with (so we no longer use this method!)
3970
		//$this->setCurlOption(CURLOPT_CUSTOMREQUEST, $this->outgoing_payload);
3971
		$curl_headers = array();
3972
		foreach($this->outgoing_headers as $k => $v){
3973
			if ($k == 'Connection' || $k == 'Content-Length' || $k == 'Host' || $k == 'Authorization' || $k == 'Proxy-Authorization') {
3974
				$this->debug("Skip cURL header $k: $v");
3975
			} else {
3976
				$curl_headers[] = "$k: $v";
3977
			}
3978
		}
3979
		if ($cookie_str != '') {
3980
			$curl_headers[] = 'Cookie: ' . $cookie_str;
3981
		}
3982
		$this->setCurlOption(CURLOPT_HTTPHEADER, $curl_headers);
3983
		$this->debug('set cURL HTTP headers');
3984
		if ($this->request_method == "POST") {
3985
	  		$this->setCurlOption(CURLOPT_POST, 1);
3986
	  		$this->setCurlOption(CURLOPT_POSTFIELDS, $data);
3987
			$this->debug('set cURL POST data');
3988
	  	} else {
0 ignored issues
show
This else statement is empty and can be removed.

This check looks for the else branches of if statements that have no statements or where all statements have been commented out. This may be the result of changes for debugging or the code may simply be obsolete.

These else branches can be removed.

if (rand(1, 6) > 3) {
print "Check failed";
} else {
    //print "Check succeeded";
}

could be turned into

if (rand(1, 6) > 3) {
    print "Check failed";
}

This is much more concise to read.

Loading history...
3989
	  	}
3990
		// insert custom user-set cURL options
3991
		foreach ($this->ch_options as $key => $val) {
3992
			$this->setCurlOption($key, $val);
3993
		}
3994
3995
		$this->debug('set cURL payload');
3996
		return true;
3997
	  }
3998
	}
3999
4000
	/**
4001
	* gets the SOAP response via HTTP[S]
4002
	*
4003
	* @return	string the response (also sets member variables like incoming_payload)
4004
	* @access   private
4005
	*/
4006
	function getResponse(){
4007
		$this->incoming_payload = '';
4008
4009
	  if ($this->io_method() == 'socket') {
4010
	    // loop until headers have been retrieved
4011
	    $data = '';
4012
	    while (!isset($lb)){
4013
4014
			// We might EOF during header read.
4015
			if(feof($this->fp)) {
4016
				$this->incoming_payload = $data;
4017
				$this->debug('found no headers before EOF after length ' . strlen($data));
4018
				$this->debug("received before EOF:\n" . $data);
4019
				$this->setError('server failed to send headers');
4020
				return false;
4021
			}
4022
4023
			$tmp = fgets($this->fp, 256);
4024
			$tmplen = strlen($tmp);
4025
			$this->debug("read line of $tmplen bytes: " . trim($tmp));
4026
4027
			if ($tmplen == 0) {
4028
				$this->incoming_payload = $data;
4029
				$this->debug('socket read of headers timed out after length ' . strlen($data));
4030
				$this->debug("read before timeout: " . $data);
4031
				$this->setError('socket read of headers timed out');
4032
				return false;
4033
			}
4034
4035
			$data .= $tmp;
4036
			$pos = strpos($data,"\r\n\r\n");
4037
			if($pos > 1){
4038
				$lb = "\r\n";
4039
			} else {
4040
				$pos = strpos($data,"\n\n");
4041
				if($pos > 1){
4042
					$lb = "\n";
4043
				}
4044
			}
4045
			// remove 100 headers
4046
			if (isset($lb) && preg_match('/^HTTP\/1.1 100/',$data)) {
4047
				unset($lb);
4048
				$data = '';
4049
			}//
4050
		}
4051
		// store header data
4052
		$this->incoming_payload .= $data;
4053
		$this->debug('found end of headers after length ' . strlen($data));
4054
		// process headers
4055
		$header_data = trim(substr($data,0,$pos));
4056
		$header_array = explode($lb,$header_data);
4057
		$this->incoming_headers = array();
4058
		$this->incoming_cookies = array();
4059
		foreach($header_array as $header_line){
4060
			$arr = explode(':',$header_line, 2);
4061
			if(count($arr) > 1){
4062
				$header_name = strtolower(trim($arr[0]));
4063
				$this->incoming_headers[$header_name] = trim($arr[1]);
4064
				if ($header_name == 'set-cookie') {
4065
					// TODO: allow multiple cookies from parseCookie
4066
					$cookie = $this->parseCookie(trim($arr[1]));
4067
					if ($cookie) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $cookie of type array<string,string|boolean> is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
4068
						$this->incoming_cookies[] = $cookie;
4069
						$this->debug('found cookie: ' . $cookie['name'] . ' = ' . $cookie['value']);
4070
					} else {
4071
						$this->debug('did not find cookie in ' . trim($arr[1]));
4072
					}
4073
    			}
4074
			} else if (isset($header_name)) {
4075
				// append continuation line to previous header
4076
				$this->incoming_headers[$header_name] .= $lb . ' ' . $header_line;
4077
			}
4078
		}
4079
4080
		// loop until msg has been received
4081
		if (isset($this->incoming_headers['transfer-encoding']) && strtolower($this->incoming_headers['transfer-encoding']) == 'chunked') {
4082
			$content_length =  2147483647;	// ignore any content-length header
4083
			$chunked = true;
4084
			$this->debug("want to read chunked content");
4085
		} elseif (isset($this->incoming_headers['content-length'])) {
4086
			$content_length = $this->incoming_headers['content-length'];
4087
			$chunked = false;
4088
			$this->debug("want to read content of length $content_length");
4089
		} else {
4090
			$content_length =  2147483647;
4091
			$chunked = false;
4092
			$this->debug("want to read content to EOF");
4093
		}
4094
		$data = '';
4095
		do {
4096
			if ($chunked) {
4097
				$tmp = fgets($this->fp, 256);
4098
				$tmplen = strlen($tmp);
4099
				$this->debug("read chunk line of $tmplen bytes");
4100
				if ($tmplen == 0) {
4101
					$this->incoming_payload = $data;
4102
					$this->debug('socket read of chunk length timed out after length ' . strlen($data));
4103
					$this->debug("read before timeout:\n" . $data);
4104
					$this->setError('socket read of chunk length timed out');
4105
					return false;
4106
				}
4107
				$content_length = hexdec(trim($tmp));
4108
				$this->debug("chunk length $content_length");
4109
			}
4110
			$strlen = 0;
4111
		    while (($strlen < $content_length) && (!feof($this->fp))) {
4112
		    	$readlen = min(8192, $content_length - $strlen);
4113
				$tmp = fread($this->fp, $readlen);
4114
				$tmplen = strlen($tmp);
4115
				$this->debug("read buffer of $tmplen bytes");
4116
				if (($tmplen == 0) && (!feof($this->fp))) {
4117
					$this->incoming_payload = $data;
4118
					$this->debug('socket read of body timed out after length ' . strlen($data));
4119
					$this->debug("read before timeout:\n" . $data);
4120
					$this->setError('socket read of body timed out');
4121
					return false;
4122
				}
4123
				$strlen += $tmplen;
4124
				$data .= $tmp;
4125
			}
4126
			if ($chunked && ($content_length > 0)) {
4127
				$tmp = fgets($this->fp, 256);
4128
				$tmplen = strlen($tmp);
4129
				$this->debug("read chunk terminator of $tmplen bytes");
4130
				if ($tmplen == 0) {
4131
					$this->incoming_payload = $data;
4132
					$this->debug('socket read of chunk terminator timed out after length ' . strlen($data));
4133
					$this->debug("read before timeout:\n" . $data);
4134
					$this->setError('socket read of chunk terminator timed out');
4135
					return false;
4136
				}
4137
			}
4138
		} while ($chunked && ($content_length > 0) && (!feof($this->fp)));
4139
		if (feof($this->fp)) {
4140
			$this->debug('read to EOF');
4141
		}
4142
		$this->debug('read body of length ' . strlen($data));
4143
		$this->incoming_payload .= $data;
4144
		$this->debug('received a total of '.strlen($this->incoming_payload).' bytes of data from server');
4145
4146
		// close filepointer
4147
		if(
4148
			(isset($this->incoming_headers['connection']) && strtolower($this->incoming_headers['connection']) == 'close') ||
4149
			(! $this->persistentConnection) || feof($this->fp)){
4150
			fclose($this->fp);
4151
			$this->fp = false;
4152
			$this->debug('closed socket');
4153
		}
4154
4155
		// connection was closed unexpectedly
4156
		if($this->incoming_payload == ''){
4157
			$this->setError('no response from server');
4158
			return false;
4159
		}
4160
4161
		// decode transfer-encoding
4162
//		if(isset($this->incoming_headers['transfer-encoding']) && strtolower($this->incoming_headers['transfer-encoding']) == 'chunked'){
4163
//			if(!$data = $this->decodeChunked($data, $lb)){
4164
//				$this->setError('Decoding of chunked data failed');
4165
//				return false;
4166
//			}
4167
			//print "<pre>\nde-chunked:\n---------------\n$data\n\n---------------\n</pre>";
4168
			// set decoded payload
4169
//			$this->incoming_payload = $header_data.$lb.$lb.$data;
4170
//		}
4171
4172
	  } else if ($this->io_method() == 'curl') {
4173
		// send and receive
4174
		$this->debug('send and receive with cURL');
4175
		$this->incoming_payload = curl_exec($this->ch);
4176
		$data = $this->incoming_payload;
4177
4178
        $cErr = curl_error($this->ch);
4179
		if ($cErr != '') {
4180
        	$err = 'cURL ERROR: '.curl_errno($this->ch).': '.$cErr.'<br>';
4181
        	// TODO: there is a PHP bug that can cause this to SEGV for CURLINFO_CONTENT_TYPE
4182
			foreach(curl_getinfo($this->ch) as $k => $v){
4183
				$err .= "$k: $v<br>";
4184
			}
4185
			$this->debug($err);
4186
			$this->setError($err);
4187
			curl_close($this->ch);
4188
	    	return false;
4189
		} else {
0 ignored issues
show
This else statement is empty and can be removed.

This check looks for the else branches of if statements that have no statements or where all statements have been commented out. This may be the result of changes for debugging or the code may simply be obsolete.

These else branches can be removed.

if (rand(1, 6) > 3) {
print "Check failed";
} else {
    //print "Check succeeded";
}

could be turned into

if (rand(1, 6) > 3) {
    print "Check failed";
}

This is much more concise to read.

Loading history...
4190
			//echo '<pre>';
4191
			//var_dump(curl_getinfo($this->ch));
4192
			//echo '</pre>';
4193
		}
4194
		// close curl
4195
		$this->debug('No cURL error, closing cURL');
4196
		curl_close($this->ch);
4197
4198
		// try removing skippable headers
4199
		$savedata = $data;
4200
		while ($this->isSkippableCurlHeader($data)) {
4201
			$this->debug("Found HTTP header to skip");
4202
			if ($pos = strpos($data,"\r\n\r\n")) {
4203
				$data = ltrim(substr($data,$pos));
4204
			} elseif($pos = strpos($data,"\n\n") ) {
4205
				$data = ltrim(substr($data,$pos));
4206
			}
4207
		}
4208
4209
		if ($data == '') {
4210
			// have nothing left; just remove 100 header(s)
4211
			$data = $savedata;
4212
			while (preg_match('/^HTTP\/1.1 100/',$data)) {
4213
				if ($pos = strpos($data,"\r\n\r\n")) {
4214
					$data = ltrim(substr($data,$pos));
4215
				} elseif($pos = strpos($data,"\n\n") ) {
4216
					$data = ltrim(substr($data,$pos));
4217
				}
4218
			}
4219
		}
4220
4221
		// separate content from HTTP headers
4222
		if ($pos = strpos($data,"\r\n\r\n")) {
4223
			$lb = "\r\n";
4224
		} elseif( $pos = strpos($data,"\n\n")) {
4225
			$lb = "\n";
4226
		} else {
4227
			$this->debug('no proper separation of headers and document');
4228
			$this->setError('no proper separation of headers and document');
4229
			return false;
4230
		}
4231
		$header_data = trim(substr($data,0,$pos));
4232
		$header_array = explode($lb,$header_data);
4233
		$data = ltrim(substr($data,$pos));
4234
		$this->debug('found proper separation of headers and document');
4235
		$this->debug('cleaned data, stringlen: '.strlen($data));
4236
		// clean headers
4237
		foreach ($header_array as $header_line) {
4238
			$arr = explode(':',$header_line,2);
4239
			if(count($arr) > 1){
4240
				$header_name = strtolower(trim($arr[0]));
4241
				$this->incoming_headers[$header_name] = trim($arr[1]);
4242
				if ($header_name == 'set-cookie') {
4243
					// TODO: allow multiple cookies from parseCookie
4244
					$cookie = $this->parseCookie(trim($arr[1]));
4245
					if ($cookie) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $cookie of type array<string,string|boolean> is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
4246
						$this->incoming_cookies[] = $cookie;
4247
						$this->debug('found cookie: ' . $cookie['name'] . ' = ' . $cookie['value']);
4248
					} else {
4249
						$this->debug('did not find cookie in ' . trim($arr[1]));
4250
					}
4251
    			}
4252
			} else if (isset($header_name)) {
4253
				// append continuation line to previous header
4254
				$this->incoming_headers[$header_name] .= $lb . ' ' . $header_line;
4255
			}
4256
		}
4257
	  }
4258
4259
		$this->response_status_line = $header_array[0];
4260
		$arr = explode(' ', $this->response_status_line, 3);
4261
		$http_version = $arr[0];
4262
		$http_status = intval($arr[1]);
4263
		$http_reason = count($arr) > 2 ? $arr[2] : '';
4264
4265
 		// see if we need to resend the request with http digest authentication
4266
 		if (isset($this->incoming_headers['location']) && ($http_status == 301 || $http_status == 302)) {
4267
 			$this->debug("Got $http_status $http_reason with Location: " . $this->incoming_headers['location']);
4268
 			$this->setURL($this->incoming_headers['location']);
4269
			$this->tryagain = true;
4270
			return false;
4271
		}
4272
4273
 		// see if we need to resend the request with http digest authentication
4274
 		if (isset($this->incoming_headers['www-authenticate']) && $http_status == 401) {
4275
 			$this->debug("Got 401 $http_reason with WWW-Authenticate: " . $this->incoming_headers['www-authenticate']);
4276
 			if (strstr($this->incoming_headers['www-authenticate'], "Digest ")) {
4277
 				$this->debug('Server wants digest authentication');
4278
 				// remove "Digest " from our elements
4279
 				$digestString = str_replace('Digest ', '', $this->incoming_headers['www-authenticate']);
4280
4281
 				// parse elements into array
4282
 				$digestElements = explode(',', $digestString);
4283
 				foreach ($digestElements as $val) {
4284
 					$tempElement = explode('=', trim($val), 2);
4285
 					$digestRequest[$tempElement[0]] = str_replace("\"", '', $tempElement[1]);
4286
 				}
4287
4288
				// should have (at least) qop, realm, nonce
4289
 				if (isset($digestRequest['nonce'])) {
4290
 					$this->setCredentials($this->username, $this->password, 'digest', $digestRequest);
4291
 					$this->tryagain = true;
4292
 					return false;
4293
 				}
4294
 			}
4295
			$this->debug('HTTP authentication failed');
4296
			$this->setError('HTTP authentication failed');
4297
			return false;
4298
 		}
4299
4300
		if (
4301
			($http_status >= 300 && $http_status <= 307) ||
4302
			($http_status >= 400 && $http_status <= 417) ||
4303
			($http_status >= 501 && $http_status <= 505)
4304
		   ) {
4305
			$this->setError("Unsupported HTTP response status $http_status $http_reason (soapclient->response has contents of the response)");
4306
			return false;
4307
		}
4308
4309
		// decode content-encoding
4310
		if(isset($this->incoming_headers['content-encoding']) && $this->incoming_headers['content-encoding'] != ''){
4311
			if(strtolower($this->incoming_headers['content-encoding']) == 'deflate' || strtolower($this->incoming_headers['content-encoding']) == 'gzip'){
4312
    			// if decoding works, use it. else assume data wasn't gzencoded
4313
    			if(function_exists('gzinflate')){
4314
					//$timer->setMarker('starting decoding of gzip/deflated content');
4315
					// IIS 5 requires gzinflate instead of gzuncompress (similar to IE 5 and gzdeflate v. gzcompress)
4316
					// this means there are no Zlib headers, although there should be
4317
					$this->debug('The gzinflate function exists');
4318
					$datalen = strlen($data);
4319
					if ($this->incoming_headers['content-encoding'] == 'deflate') {
4320
						if ($degzdata = @gzinflate($data)) {
4321
	    					$data = $degzdata;
4322
	    					$this->debug('The payload has been inflated to ' . strlen($data) . ' bytes');
4323
	    					if (strlen($data) < $datalen) {
4324
	    						// test for the case that the payload has been compressed twice
4325
		    					$this->debug('The inflated payload is smaller than the gzipped one; try again');
4326
								if ($degzdata = @gzinflate($data)) {
4327
			    					$data = $degzdata;
4328
			    					$this->debug('The payload has been inflated again to ' . strlen($data) . ' bytes');
4329
								}
4330
	    					}
4331
	    				} else {
4332
	    					$this->debug('Error using gzinflate to inflate the payload');
4333
	    					$this->setError('Error using gzinflate to inflate the payload');
4334
	    				}
4335
					} elseif ($this->incoming_headers['content-encoding'] == 'gzip') {
4336
						if ($degzdata = @gzinflate(substr($data, 10))) {	// do our best
4337
							$data = $degzdata;
4338
	    					$this->debug('The payload has been un-gzipped to ' . strlen($data) . ' bytes');
4339
	    					if (strlen($data) < $datalen) {
4340
	    						// test for the case that the payload has been compressed twice
4341
		    					$this->debug('The un-gzipped payload is smaller than the gzipped one; try again');
4342
								if ($degzdata = @gzinflate(substr($data, 10))) {
4343
			    					$data = $degzdata;
4344
			    					$this->debug('The payload has been un-gzipped again to ' . strlen($data) . ' bytes');
4345
								}
4346
	    					}
4347
	    				} else {
4348
	    					$this->debug('Error using gzinflate to un-gzip the payload');
4349
							$this->setError('Error using gzinflate to un-gzip the payload');
4350
	    				}
4351
					}
4352
					//$timer->setMarker('finished decoding of gzip/deflated content');
4353
					//print "<xmp>\nde-inflated:\n---------------\n$data\n-------------\n</xmp>";
4354
					// set decoded payload
4355
					$this->incoming_payload = $header_data.$lb.$lb.$data;
4356
    			} else {
4357
					$this->debug('The server sent compressed data. Your php install must have the Zlib extension compiled in to support this.');
4358
					$this->setError('The server sent compressed data. Your php install must have the Zlib extension compiled in to support this.');
4359
				}
4360
			} else {
4361
				$this->debug('Unsupported Content-Encoding ' . $this->incoming_headers['content-encoding']);
4362
				$this->setError('Unsupported Content-Encoding ' . $this->incoming_headers['content-encoding']);
4363
			}
4364
		} else {
4365
			$this->debug('No Content-Encoding header');
4366
		}
4367
4368
		if(strlen($data) == 0){
4369
			$this->debug('no data after headers!');
4370
			$this->setError('no data present after HTTP headers');
4371
			return false;
4372
		}
4373
4374
		return $data;
4375
	}
4376
4377
	/**
4378
	 * sets the content-type for the SOAP message to be sent
4379
	 *
4380
	 * @param	string $type the content type, MIME style
4381
	 * @param	mixed $charset character set used for encoding (or false)
4382
	 * @access	public
4383
	 */
4384
	function setContentType($type, $charset = false) {
4385
		$this->setHeader('Content-Type', $type . ($charset ? '; charset=' . $charset : ''));
4386
	}
4387
4388
	/**
4389
	 * specifies that an HTTP persistent connection should be used
4390
	 *
4391
	 * @return	boolean whether the request was honored by this method.
4392
	 * @access	public
4393
	 */
4394
	function usePersistentConnection(){
4395
		if (isset($this->outgoing_headers['Accept-Encoding'])) {
4396
			return false;
4397
		}
4398
		$this->protocol_version = '1.1';
4399
		$this->persistentConnection = true;
4400
		$this->setHeader('Connection', 'Keep-Alive');
4401
		return true;
4402
	}
4403
4404
	/**
4405
	 * parse an incoming Cookie into it's parts
4406
	 *
4407
	 * @param	string $cookie_str content of cookie
4408
	 * @return	array with data of that cookie
4409
	 * @access	private
4410
	 */
4411
	/*
4412
	 * TODO: allow a Set-Cookie string to be parsed into multiple cookies
4413
	 */
4414
	function parseCookie($cookie_str) {
4415
		$cookie_str = str_replace('; ', ';', $cookie_str) . ';';
4416
		$data = preg_split('/;/', $cookie_str);
4417
		$value_str = $data[0];
4418
4419
		$cookie_param = 'domain=';
4420
		$start = strpos($cookie_str, $cookie_param);
4421
		if ($start > 0) {
4422
			$domain = substr($cookie_str, $start + strlen($cookie_param));
4423
			$domain = substr($domain, 0, strpos($domain, ';'));
4424
		} else {
4425
			$domain = '';
4426
		}
4427
4428
		$cookie_param = 'expires=';
4429
		$start = strpos($cookie_str, $cookie_param);
4430
		if ($start > 0) {
4431
			$expires = substr($cookie_str, $start + strlen($cookie_param));
4432
			$expires = substr($expires, 0, strpos($expires, ';'));
4433
		} else {
4434
			$expires = '';
4435
		}
4436
4437
		$cookie_param = 'path=';
4438
		$start = strpos($cookie_str, $cookie_param);
4439
		if ( $start > 0 ) {
4440
			$path = substr($cookie_str, $start + strlen($cookie_param));
4441
			$path = substr($path, 0, strpos($path, ';'));
4442
		} else {
4443
			$path = '/';
4444
		}
4445
4446
		$cookie_param = ';secure;';
4447
		if (strpos($cookie_str, $cookie_param) !== FALSE) {
4448
			$secure = true;
4449
		} else {
4450
			$secure = false;
4451
		}
4452
4453
		$sep_pos = strpos($value_str, '=');
4454
4455
		if ($sep_pos) {
4456
			$name = substr($value_str, 0, $sep_pos);
4457
			$value = substr($value_str, $sep_pos + 1);
4458
			$cookie= array(	'name' => $name,
4459
			                'value' => $value,
4460
							'domain' => $domain,
4461
							'path' => $path,
4462
							'expires' => $expires,
4463
							'secure' => $secure
4464
							);
4465
			return $cookie;
4466
		}
4467
		return false;
4468
	}
4469
4470
	/**
4471
	 * sort out cookies for the current request
4472
	 *
4473
	 * @param	array $cookies array with all cookies
4474
	 * @param	boolean $secure is the send-content secure or not?
4475
	 * @return	string for Cookie-HTTP-Header
4476
	 * @access	private
4477
	 */
4478
	function getCookiesForRequest($cookies, $secure=false) {
4479
		$cookie_str = '';
4480
		if ((! is_null($cookies)) && (is_array($cookies))) {
4481
			foreach ($cookies as $cookie) {
4482
				if (! is_array($cookie)) {
4483
					continue;
4484
				}
4485
	    		$this->debug("check cookie for validity: ".$cookie['name'].'='.$cookie['value']);
4486
				if ((isset($cookie['expires'])) && (! empty($cookie['expires']))) {
4487
					if (strtotime($cookie['expires']) <= time()) {
4488
						$this->debug('cookie has expired');
4489
						continue;
4490
					}
4491
				}
4492
				if ((isset($cookie['domain'])) && (! empty($cookie['domain']))) {
4493
					$domain = preg_quote($cookie['domain']);
4494
					if (! preg_match("'.*$domain$'i", $this->host)) {
4495
						$this->debug('cookie has different domain');
4496
						continue;
4497
					}
4498
				}
4499
				if ((isset($cookie['path'])) && (! empty($cookie['path']))) {
4500
					$path = preg_quote($cookie['path']);
4501
					if (! preg_match("'^$path.*'i", $this->path)) {
4502
						$this->debug('cookie is for a different path');
4503
						continue;
4504
					}
4505
				}
4506
				if ((! $secure) && (isset($cookie['secure'])) && ($cookie['secure'])) {
4507
					$this->debug('cookie is secure, transport is not');
4508
					continue;
4509
				}
4510
				$cookie_str .= $cookie['name'] . '=' . $cookie['value'] . '; ';
4511
	    		$this->debug('add cookie to Cookie-String: ' . $cookie['name'] . '=' . $cookie['value']);
4512
			}
4513
		}
4514
		return $cookie_str;
4515
  }
4516
}
4517
4518
?><?php
4519
4520
/*
4521
4522
Modification information for LGPL compliance
4523
4524
r58622 - 2010-10-22 18:18:59 -0700 (Fri, 22 Oct 2010) - engsvnbuild - Author: lam <[email protected]>
4525
    bug 40066
4526
4527
r58361 - 2010-09-29 16:59:02 -0700 (Wed, 29 Sep 2010) - kjing - Author: Jenny Gonsalves <[email protected]>
4528
    Merging with maint_6_0_1 (svn merge -r 58250:58342)
4529
4530
r57813 - 2010-08-19 10:34:44 -0700 (Thu, 19 Aug 2010) - kjing - Author: John Mertic <[email protected]>
4531
    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.
4532
4533
r57707 - 2010-08-10 12:26:13 -0700 (Tue, 10 Aug 2010) - kjing - Author: Stanislav Malyshev <[email protected]>
4534
    fix SOAP calls with no parameters
4535
4536
r56990 - 2010-06-16 13:05:36 -0700 (Wed, 16 Jun 2010) - kjing - snapshot "Mango" svn branch to a new one for GitHub sync
4537
4538
r56989 - 2010-06-16 13:01:33 -0700 (Wed, 16 Jun 2010) - kjing - defunt "Mango" svn dev branch before github cutover
4539
4540
r55980 - 2010-04-19 13:31:28 -0700 (Mon, 19 Apr 2010) - kjing - create Mango (6.1) based on windex
4541
4542
r51719 - 2009-10-22 10:18:00 -0700 (Thu, 22 Oct 2009) - mitani - Converted to Build 3  tags and updated the build system
4543
4544
r51634 - 2009-10-19 13:32:22 -0700 (Mon, 19 Oct 2009) - mitani - Windex is the branch for Sugar Sales 1.0 development
4545
4546
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.
4547
4548
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.
4549
4550
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:
4551
- Changing all ereg function to either preg or simple string based ones
4552
- No more references to magic quotes.
4553
- Change all the session_unregister() functions to just unset() the correct session variable instead.
4554
4555
r50375 - 2009-08-24 18:07:43 -0700 (Mon, 24 Aug 2009) - dwong - branch kobe2 from tokyo r50372
4556
4557
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
4558
4559
r45680 - 2009-03-30 14:34:35 -0700 (Mon, 30 Mar 2009) - Samir Gandhi - modifeid serializeSchema to generate WS-I compliant WSDL
4560
4561
r42807 - 2008-12-29 11:16:59 -0800 (Mon, 29 Dec 2008) - dwong - Branch from trunk/sugarcrm r42806 to branches/tokyo/sugarcrm
4562
4563
r42645 - 2008-12-18 13:41:08 -0800 (Thu, 18 Dec 2008) - awu - merging maint_5_2_0 rev41336:HEAD to trunk
4564
4565
r41647 - 2008-11-11 17:44:30 -0800 (Tue, 11 Nov 2008) - majed - Fixes a few bugs
4566
4567
r41596 - 2008-11-10 19:20:04 -0800 (Mon, 10 Nov 2008) - Samir Gandhi - modified to set $method in the code
4568
4569
r41558 - 2008-11-10 14:35:34 -0800 (Mon, 10 Nov 2008) - majed - changes nusoap to allow for registering classes
4570
4571
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.
4572
Touched:
4573
- data/SugarBean.php
4574
- include/domit/php_http_client_generic.php
4575
- include/domit/php_http_connector.php
4576
- include/domit/testing_domit.php
4577
- include/domit/xml_domit_getelementsbypath.php
4578
- include/domit/xml_domit_lite_parser.php
4579
- include/domit/xml_domit_nodemaps.php
4580
- include/domit/xml_domit_parser.php
4581
- include/domit/xml_domit_shared.php
4582
- include/generic/SugarWidgets/SugarWidgetField.php
4583
- include/generic/SugarWidgets/SugarWidgetReportField.php
4584
- include/ListView/ProcessView.php
4585
- include/nusoap/class.soapclient.php
4586
- include/nusoap/nusoap.php
4587
- include/nusoap/nusoapmime.php
4588
- include/Pear/HTML_Safe/Safe.php
4589
- include/Pear/XML_HTMLSax3/HTMLSax3.php
4590
- modules/Administration/RebuildWorkFlow.php
4591
- modules/Expressions/RelateSelector.php
4592
- modules/Reports/templates/templates_reports.php
4593
- modules/WorkFlow/Delete.php
4594
- modules/WorkFlow/Save.php
4595
- modules/WorkFlow/SaveSequence.php
4596
- modules/WorkFlow/WorkFlow.php
4597
- modules/WorkFlowActionShells/CreateStep1.php
4598
- modules/WorkFlowActionShells/CreateStep2.php
4599
- modules/WorkFlowActionShells/Save.php
4600
- modules/WorkFlowActionShells/WorkFlowActionShell.php
4601
- modules/WorkFlowAlerts/Save.php
4602
- modules/WorkFlowAlerts/WorkFlowAlert.php
4603
- modules/WorkFlowAlertShells/DetailView.php
4604
- modules/WorkFlowAlertShells/WorkFlowAlertShell.php
4605
- modules/WorkFlowTriggerShells/CreateStep1.php
4606
- modules/WorkFlowTriggerShells/CreateStepFilter.php
4607
- modules/WorkFlowTriggerShells/SaveFilter.php
4608
- modules/WorkFlowTriggerShells/WorkFlowTriggerShell.php
4609
- soap/SoapHelperFunctions.php
4610
- test/modules/DynamicFields/DynamicFields_Bug24095_test.php
4611
- test/simpletest/browser.php
4612
- test/simpletest/default_reporter.php
4613
- test/simpletest/detached.php
4614
- test/simpletest/eclipse.php
4615
- test/simpletest/expectation.php
4616
- test/simpletest/extensions/pear_test_case.php
4617
- test/simpletest/form.php
4618
- test/simpletest/http.php
4619
- test/simpletest/mock_objects.php
4620
- test/simpletest/page.php
4621
- test/simpletest/parser.php
4622
- test/simpletest/remote.php
4623
- test/simpletest/shell_tester.php
4624
- test/simpletest/simple_test.php
4625
- test/simpletest/simpletest.php
4626
- test/simpletest/test/acceptance_test.php
4627
- test/simpletest/test/adapter_test.php
4628
- test/simpletest/test/authentication_test.php
4629
- test/simpletest/test/browser_test.php
4630
- test/simpletest/test/collector_test.php
4631
- test/simpletest/test/compatibility_test.php
4632
- test/simpletest/test/detached_test.php
4633
- test/simpletest/test/eclipse_test.php
4634
- test/simpletest/test/encoding_test.php
4635
- test/simpletest/test/errors_test.php
4636
- test/simpletest/test/expectation_test.php
4637
- test/simpletest/test/form_test.php
4638
- test/simpletest/test/frames_test.php
4639
- test/simpletest/test/http_test.php
4640
- test/simpletest/test/live_test.php
4641
- test/simpletest/test/mock_objects_test.php
4642
- test/simpletest/test/page_test.php
4643
- test/simpletest/test/parse_error_test.php
4644
- test/simpletest/test/parser_test.php
4645
- test/simpletest/test/remote_test.php
4646
- test/simpletest/test/shell_test.php
4647
- test/simpletest/test/shell_tester_test.php
4648
- test/simpletest/test/simpletest_test.php
4649
- test/simpletest/test/site/page_request.php
4650
- test/simpletest/test/tag_test.php
4651
- test/simpletest/test/unit_tester_test.php
4652
- test/simpletest/test/user_agent_test.php
4653
- test/simpletest/test/visual_test.php
4654
- test/simpletest/test/xml_test.php
4655
- test/simpletest/test_case.php
4656
- test/simpletest/ui/array_reporter/test.php
4657
- test/simpletest/ui/recorder/test.php
4658
- test/simpletest/unit_tester.php
4659
- test/simpletest/url.php
4660
- test/simpletest/user_agent.php
4661
- test/simpletest/web_tester.php
4662
- test/spikephpcoverage/src/PEAR.php
4663
- test/spikephpcoverage/src/util/Utility.php
4664
- test/spikephpcoverage/src/XML/Parser.php
4665
- test/spikephpcoverage/src/XML/Parser/Simple.php
4666
- test/test_utilities/SugarTest_SimpleBrowser.php
4667
4668
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.
4669
4670
r38300 - 2008-07-25 13:33:43 -0700 (Fri, 25 Jul 2008) - Samir Gandhi - put the debug in parseresponse function
4671
4672
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
4673
4674
r36824 - 2008-06-18 09:26:11 -0700 (Wed, 18 Jun 2008) - roger - bug: 21832
4675
4676
r26422 - 2007-09-05 17:29:12 -0700 (Wed, 05 Sep 2007) - majed - migrate from beta 1 to trunk
4677
4678
r15787 - 2006-08-10 10:14:41 -0700 (Thu, 10 Aug 2006) - roger - RRS: bug 7961
4679
4680
r14701 - 2006-07-17 13:37:26 -0700 (Mon, 17 Jul 2006) - roger - RRS: bug 5801
4681
4682
r13782 - 2006-06-06 10:58:55 -0700 (Tue, 06 Jun 2006) - majed - changes entry point code
4683
4684
r11466 - 2006-02-01 15:49:47 -0800 (Wed, 01 Feb 2006) - jacob - Adding extra !empty check to get around a PHP warning.
4685
4686
r11115 - 2006-01-17 14:54:45 -0800 (Tue, 17 Jan 2006) - majed - add entry point validation
4687
4688
r10585 - 2005-12-13 14:42:26 -0800 (Tue, 13 Dec 2005) - majed - adds new license mechanisim
4689
4690
r10170 - 2005-12-05 18:37:46 -0800 (Mon, 05 Dec 2005) - majed - fixes various issues
4691
4692
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.
4693
4694
r8991 - 2005-11-03 19:07:25 -0800 (Thu, 03 Nov 2005) - majed - fixes nusoap issue
4695
4696
r8846 - 2005-10-31 11:01:12 -0800 (Mon, 31 Oct 2005) - majed - new version of nusoap
4697
4698
r7905 - 2005-09-21 19:12:57 -0700 (Wed, 21 Sep 2005) - majed - restores old nusoap pre & with a few fixes
4699
4700
r7861 - 2005-09-20 15:40:25 -0700 (Tue, 20 Sep 2005) - majed - & fix for 3.5.1
4701
4702
r7452 - 2005-08-17 11:32:34 -0700 (Wed, 17 Aug 2005) - majed - changes soap to nusoap
4703
4704
r5820 - 2005-06-21 14:22:24 -0700 (Tue, 21 Jun 2005) - majed - fixes issues with nusoap and with custom fields
4705
4706
r5462 - 2005-05-25 13:50:11 -0700 (Wed, 25 May 2005) - majed - upgraded nusoap to .6.9
4707
4708
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
4709
4710
r573 - 2004-09-04 13:03:32 -0700 (Sat, 04 Sep 2004) - sugarclint - undoing copyrights added in inadvertantly.  --clint
4711
4712
r546 - 2004-09-03 11:49:38 -0700 (Fri, 03 Sep 2004) - sugarmsi - removed echo count
4713
4714
r354 - 2004-08-02 23:00:37 -0700 (Mon, 02 Aug 2004) - sugarjacob - Adding Soap
4715
4716
4717
*/
4718
4719
4720
4721
4722
4723
/**
4724
*
4725
* nusoap_server allows the user to create a SOAP server
4726
* that is capable of receiving messages and returning responses
4727
*
4728
* @author   Dietrich Ayala <[email protected]>
4729
* @author   Scott Nichol <[email protected]>
4730
4731
* @access   public
4732
*/
4733
class nusoap_server extends nusoap_base {
0 ignored issues
show
Comprehensibility Best Practice introduced by
The type nusoap_server has been defined more than once; this definition is ignored, only the first definition in include/nusoap/class.soap_server.php (L66-1168) is considered.

This check looks for classes that have been defined more than once.

If you can, we would recommend to use standard object-oriented programming techniques. For example, to avoid multiple types, it might make sense to create a common interface, and then multiple, different implementations for that interface.

This also has the side-effect of providing you with better IDE auto-completion, static analysis and also better OPCode caching from PHP.

Loading history...
Coding Style Compatibility introduced by
PSR1 recommends that each class should be in its own file to aid autoloaders.

Having each class in a dedicated file usually plays nice with PSR autoloaders and is therefore a well established practice. If you use other autoloaders, you might not want to follow this rule.

Loading history...
4734
	/**
4735
	 * HTTP headers of request
4736
	 * @var array
4737
	 * @access private
4738
	 */
4739
	var $headers = array();
4740
	/**
4741
	 * HTTP request
4742
	 * @var string
4743
	 * @access private
4744
	 */
4745
	var $request = '';
4746
	/**
4747
	 * SOAP headers from request (incomplete namespace resolution; special characters not escaped) (text)
4748
	 * @var string
4749
	 * @access public
4750
	 */
4751
	var $requestHeaders = '';
4752
	/**
4753
	 * SOAP Headers from request (parsed)
4754
	 * @var mixed
4755
	 * @access public
4756
	 */
4757
	var $requestHeader = NULL;
4758
	/**
4759
	 * SOAP body request portion (incomplete namespace resolution; special characters not escaped) (text)
4760
	 * @var string
4761
	 * @access public
4762
	 */
4763
	var $document = '';
4764
	/**
4765
	 * SOAP payload for request (text)
4766
	 * @var string
4767
	 * @access public
4768
	 */
4769
	var $requestSOAP = '';
4770
	/**
4771
	 * requested method namespace URI
4772
	 * @var string
4773
	 * @access private
4774
	 */
4775
	var $methodURI = '';
4776
	/**
4777
	 * name of method requested
4778
	 * @var string
4779
	 * @access private
4780
	 */
4781
	var $methodname = '';
4782
	/**
4783
	 * method parameters from request
4784
	 * @var array
4785
	 * @access private
4786
	 */
4787
	var $methodparams = array();
4788
	/**
4789
	 * SOAP Action from request
4790
	 * @var string
4791
	 * @access private
4792
	 */
4793
	var $SOAPAction = '';
4794
	/**
4795
	 * character set encoding of incoming (request) messages
4796
	 * @var string
4797
	 * @access public
4798
	 */
4799
	var $xml_encoding = '';
4800
	/**
4801
	 * toggles whether the parser decodes element content w/ utf8_decode()
4802
	 * @var boolean
4803
	 * @access public
4804
	 */
4805
    var $decode_utf8 = false;
4806
4807
	/**
4808
	 * HTTP headers of response
4809
	 * @var array
4810
	 * @access public
4811
	 */
4812
	var $outgoing_headers = array();
4813
	/**
4814
	 * HTTP response
4815
	 * @var string
4816
	 * @access private
4817
	 */
4818
	var $response = '';
4819
	/**
4820
	 * SOAP headers for response (text or array of soapval or associative array)
4821
	 * @var mixed
4822
	 * @access public
4823
	 */
4824
	var $responseHeaders = '';
4825
	/**
4826
	 * SOAP payload for response (text)
4827
	 * @var string
4828
	 * @access private
4829
	 */
4830
	var $responseSOAP = '';
4831
	/**
4832
	 * method return value to place in response
4833
	 * @var mixed
4834
	 * @access private
4835
	 */
4836
	var $methodreturn = false;
4837
	/**
4838
	 * whether $methodreturn is a string of literal XML
4839
	 * @var boolean
4840
	 * @access public
4841
	 */
4842
	var $methodreturnisliteralxml = false;
4843
	/**
4844
	 * SOAP fault for response (or false)
4845
	 * @var mixed
4846
	 * @access private
4847
	 */
4848
	var $fault = false;
4849
	/**
4850
	 * text indication of result (for debugging)
4851
	 * @var string
4852
	 * @access private
4853
	 */
4854
	var $result = 'successful';
4855
4856
	/**
4857
	 * assoc array of operations => opData; operations are added by the register()
4858
	 * method or by parsing an external WSDL definition
4859
	 * @var array
4860
	 * @access private
4861
	 */
4862
	var $operations = array();
4863
	/**
4864
	 * wsdl instance (if one)
4865
	 * @var mixed
4866
	 * @access private
4867
	 */
4868
	var $wsdl = false;
4869
	/**
4870
	 * URL for WSDL (if one)
4871
	 * @var mixed
4872
	 * @access private
4873
	 */
4874
	var $externalWSDLURL = false;
4875
	/**
4876
	 * whether to append debug to response as XML comment
4877
	 * @var boolean
4878
	 * @access public
4879
	 */
4880
	var $debug_flag = false;
4881
4882
4883
	/**
4884
	* constructor
4885
    * the optional parameter is a path to a WSDL file that you'd like to bind the server instance to.
4886
	*
4887
    * @param mixed $wsdl file path or URL (string), or wsdl instance (object)
4888
	* @access   public
4889
	*/
4890
	function nusoap_server($wsdl=false){
4891
		parent::nusoap_base();
4892
		// turn on debugging?
4893
		global $debug;
4894
		global $HTTP_SERVER_VARS;
4895
4896
		if (isset($_SERVER)) {
4897
			$this->debug("_SERVER is defined:");
4898
			$this->appendDebug($this->varDump($_SERVER));
4899
		} elseif (isset($HTTP_SERVER_VARS)) {
4900
			$this->debug("HTTP_SERVER_VARS is defined:");
4901
			$this->appendDebug($this->varDump($HTTP_SERVER_VARS));
4902
		} else {
4903
			$this->debug("Neither _SERVER nor HTTP_SERVER_VARS is defined.");
4904
		}
4905
4906
		if (isset($debug)) {
4907
			$this->debug("In nusoap_server, set debug_flag=$debug based on global flag");
4908
			$this->debug_flag = $debug;
4909
		} elseif (isset($_SERVER['QUERY_STRING'])) {
4910
			$qs = explode('&', $_SERVER['QUERY_STRING']);
4911
			foreach ($qs as $v) {
4912
				if (substr($v, 0, 6) == 'debug=') {
4913
					$this->debug("In nusoap_server, set debug_flag=" . substr($v, 6) . " based on query string #1");
4914
					$this->debug_flag = substr($v, 6);
0 ignored issues
show
Documentation Bug introduced by
The property $debug_flag was declared of type boolean, but substr($v, 6) is of type string. Maybe add a type cast?

This check looks for assignments to scalar types that may be of the wrong type.

To ensure the code behaves as expected, it may be a good idea to add an explicit type cast.

$answer = 42;

$correct = false;

$correct = (bool) $answer;
Loading history...
4915
				}
4916
			}
4917
		} elseif (isset($HTTP_SERVER_VARS['QUERY_STRING'])) {
4918
			$qs = explode('&', $HTTP_SERVER_VARS['QUERY_STRING']);
4919
			foreach ($qs as $v) {
4920
				if (substr($v, 0, 6) == 'debug=') {
4921
					$this->debug("In nusoap_server, set debug_flag=" . substr($v, 6) . " based on query string #2");
4922
					$this->debug_flag = substr($v, 6);
4923
				}
4924
			}
4925
		}
4926
4927
		// wsdl
4928
		if($wsdl){
4929
			$this->debug("In nusoap_server, WSDL is specified");
4930
			if (is_object($wsdl) && (get_class($wsdl) == 'wsdl')) {
4931
				$this->wsdl = $wsdl;
4932
				$this->externalWSDLURL = $this->wsdl->wsdl;
4933
				$this->debug('Use existing wsdl instance from ' . $this->externalWSDLURL);
4934
			} else {
4935
				$this->debug('Create wsdl from ' . $wsdl);
4936
				$this->wsdl = new wsdl($wsdl);
4937
				$this->externalWSDLURL = $wsdl;
4938
			}
4939
			$this->appendDebug($this->wsdl->getDebug());
4940
			$this->wsdl->clearDebug();
4941
			if($err = $this->wsdl->getError()){
4942
				die('WSDL ERROR: '.$err);
4943
			}
4944
		}
4945
	}
4946
4947
	/**
4948
	* processes request and returns response
4949
	*
4950
	* @param    string $data usually is the value of $HTTP_RAW_POST_DATA
4951
	* @access   public
4952
	*/
4953
	function service($data){
4954
		global $HTTP_SERVER_VARS;
4955
4956
		if (isset($_SERVER['REQUEST_METHOD'])) {
4957
			$rm = $_SERVER['REQUEST_METHOD'];
4958
		} elseif (isset($HTTP_SERVER_VARS['REQUEST_METHOD'])) {
4959
			$rm = $HTTP_SERVER_VARS['REQUEST_METHOD'];
4960
		} else {
4961
			$rm = '';
4962
		}
4963
4964
		if (isset($_SERVER['QUERY_STRING'])) {
4965
			$qs = $_SERVER['QUERY_STRING'];
4966
		} elseif (isset($HTTP_SERVER_VARS['QUERY_STRING'])) {
4967
			$qs = $HTTP_SERVER_VARS['QUERY_STRING'];
4968
		} else {
4969
			$qs = '';
4970
		}
4971
		$this->debug("In service, request method=$rm query string=$qs strlen(\$data)=" . strlen($data));
4972
4973
		if ($rm == 'POST') {
4974
			$this->debug("In service, invoke the request");
4975
			$this->parse_request($data);
4976
			if (! $this->fault) {
4977
				$this->invoke_method();
4978
			}
4979
			if (! $this->fault) {
4980
				$this->serialize_return();
4981
			}
4982
			$this->send_response();
4983
		} elseif (preg_match('/wsdl/', $qs) ){
4984
			$this->debug("In service, this is a request for WSDL");
4985
			if ($this->externalWSDLURL){
4986
              if (strpos($this->externalWSDLURL, "http://") !== false) { // assume URL
4987
				$this->debug("In service, re-direct for WSDL");
4988
				header('Location: '.$this->externalWSDLURL);
4989
              } else { // assume file
4990
				$this->debug("In service, use file passthru for WSDL");
4991
                header("Content-Type: text/xml\r\n");
4992
				$pos = strpos($this->externalWSDLURL, "file://");
4993
				if ($pos === false) {
4994
					$filename = $this->externalWSDLURL;
4995
				} else {
4996
					$filename = substr($this->externalWSDLURL, $pos + 7);
4997
				}
4998
                $fp = fopen($this->externalWSDLURL, 'r');
4999
                fpassthru($fp);
5000
              }
5001
			} elseif ($this->wsdl) {
5002
				$this->debug("In service, serialize WSDL");
5003
				header("Content-Type: text/xml; charset=ISO-8859-1\r\n");
5004
				print $this->wsdl->serialize($this->debug_flag);
5005
				if ($this->debug_flag) {
5006
					$this->debug('wsdl:');
5007
					$this->appendDebug($this->varDump($this->wsdl));
5008
					print $this->getDebugAsXMLComment();
5009
				}
5010
			} else {
5011
				$this->debug("In service, there is no WSDL");
5012
				header("Content-Type: text/html; charset=ISO-8859-1\r\n");
5013
				print "This service does not provide WSDL";
5014
			}
5015
		} elseif ($this->wsdl) {
5016
			$this->debug("In service, return Web description");
5017
			print $this->wsdl->webDescription();
5018
		} else {
5019
			$this->debug("In service, no Web description");
5020
			header("Content-Type: text/html; charset=ISO-8859-1\r\n");
5021
			print "This service does not provide a Web description";
5022
		}
5023
	}
5024
5025
	/**
5026
	* parses HTTP request headers.
5027
	*
5028
	* The following fields are set by this function (when successful)
5029
	*
5030
	* headers
5031
	* request
5032
	* xml_encoding
5033
	* SOAPAction
5034
	*
5035
	* @access   private
5036
	*/
5037
	function parse_http_headers() {
5038
		global $HTTP_SERVER_VARS;
5039
5040
		$this->request = '';
5041
		$this->SOAPAction = '';
5042
		if(function_exists('getallheaders')){
5043
			$this->debug("In parse_http_headers, use getallheaders");
5044
			$headers = getallheaders();
5045
			foreach($headers as $k=>$v){
5046
				$k = strtolower($k);
5047
				$this->headers[$k] = $v;
5048
				$this->request .= "$k: $v\r\n";
5049
				$this->debug("$k: $v");
5050
			}
5051
			// get SOAPAction header
5052
			if(isset($this->headers['soapaction'])){
5053
				$this->SOAPAction = str_replace('"','',$this->headers['soapaction']);
5054
			}
5055
			// get the character encoding of the incoming request
5056
			if(isset($this->headers['content-type']) && strpos($this->headers['content-type'],'=')){
5057
				$enc = str_replace('"','',substr(strstr($this->headers["content-type"],'='),1));
5058
				if(preg_match('/^(ISO-8859-1|US-ASCII|UTF-8)$/i',$enc)){
5059
					$this->xml_encoding = strtoupper($enc);
5060
				} else {
5061
					$this->xml_encoding = 'US-ASCII';
5062
				}
5063
			} else {
5064
				// should be US-ASCII for HTTP 1.0 or ISO-8859-1 for HTTP 1.1
5065
				$this->xml_encoding = 'ISO-8859-1';
5066
			}
5067
		} elseif(isset($_SERVER) && is_array($_SERVER)){
5068
			$this->debug("In parse_http_headers, use _SERVER");
5069
			foreach ($_SERVER as $k => $v) {
5070
				if (substr($k, 0, 5) == 'HTTP_') {
5071
					$k = str_replace(' ', '-', strtolower(str_replace('_', ' ', substr($k, 5))));
5072
				} else {
5073
					$k = str_replace(' ', '-', strtolower(str_replace('_', ' ', $k)));
5074
				}
5075
				if ($k == 'soapaction') {
5076
					// get SOAPAction header
5077
					$k = 'SOAPAction';
5078
					$v = str_replace('"', '', $v);
5079
					$v = str_replace('\\', '', $v);
5080
					$this->SOAPAction = $v;
5081
				} else if ($k == 'content-type') {
5082
					// get the character encoding of the incoming request
5083
					if (strpos($v, '=')) {
5084
						$enc = substr(strstr($v, '='), 1);
5085
						$enc = str_replace('"', '', $enc);
5086
						$enc = str_replace('\\', '', $enc);
5087
						if (preg_match('/^(ISO-8859-1|US-ASCII|UTF-8)$/i',$enc)) {
5088
							$this->xml_encoding = strtoupper($enc);
5089
						} else {
5090
							$this->xml_encoding = 'US-ASCII';
5091
						}
5092
					} else {
5093
						// should be US-ASCII for HTTP 1.0 or ISO-8859-1 for HTTP 1.1
5094
						$this->xml_encoding = 'ISO-8859-1';
5095
					}
5096
				}
5097
				$this->headers[$k] = $v;
5098
				$this->request .= "$k: $v\r\n";
5099
				$this->debug("$k: $v");
5100
			}
5101
		} elseif (is_array($HTTP_SERVER_VARS)) {
5102
			$this->debug("In parse_http_headers, use HTTP_SERVER_VARS");
5103
			foreach ($HTTP_SERVER_VARS as $k => $v) {
5104
				if (substr($k, 0, 5) == 'HTTP_') {
5105
					$k = str_replace(' ', '-', strtolower(str_replace('_', ' ', substr($k, 5)))); 	                                         $k = strtolower(substr($k, 5));
5106
				} else {
5107
					$k = str_replace(' ', '-', strtolower(str_replace('_', ' ', $k))); 	                                         $k = strtolower($k);
5108
				}
5109
				if ($k == 'soapaction') {
5110
					// get SOAPAction header
5111
					$k = 'SOAPAction';
5112
					$v = str_replace('"', '', $v);
5113
					$v = str_replace('\\', '', $v);
5114
					$this->SOAPAction = $v;
5115
				} else if ($k == 'content-type') {
5116
					// get the character encoding of the incoming request
5117
					if (strpos($v, '=')) {
5118
						$enc = substr(strstr($v, '='), 1);
5119
						$enc = str_replace('"', '', $enc);
5120
						$enc = str_replace('\\', '', $enc);
5121
						if (preg_match('/^(ISO-8859-1|US-ASCII|UTF-8)$/i',$enc)) {
5122
							$this->xml_encoding = strtoupper($enc);
5123
						} else {
5124
							$this->xml_encoding = 'US-ASCII';
5125
						}
5126
					} else {
5127
						// should be US-ASCII for HTTP 1.0 or ISO-8859-1 for HTTP 1.1
5128
						$this->xml_encoding = 'ISO-8859-1';
5129
					}
5130
				}
5131
				$this->headers[$k] = $v;
5132
				$this->request .= "$k: $v\r\n";
5133
				$this->debug("$k: $v");
5134
			}
5135
		} else {
5136
			$this->debug("In parse_http_headers, HTTP headers not accessible");
5137
			$this->setError("HTTP headers not accessible");
5138
		}
5139
	}
5140
5141
	/**
5142
	* parses a request
5143
	*
5144
	* The following fields are set by this function (when successful)
5145
	*
5146
	* headers
5147
	* request
5148
	* xml_encoding
5149
	* SOAPAction
5150
	* request
5151
	* requestSOAP
5152
	* methodURI
5153
	* methodname
5154
	* methodparams
5155
	* requestHeaders
5156
	* document
5157
	*
5158
	* This sets the fault field on error
5159
	*
5160
	* @param    string $data XML string
5161
	* @access   private
5162
	*/
5163
	function parse_request($data='') {
5164
		$this->debug('entering parse_request()');
5165
		$this->parse_http_headers();
5166
		$this->debug('got character encoding: '.$this->xml_encoding);
5167
		// uncompress if necessary
5168
		if (isset($this->headers['content-encoding']) && $this->headers['content-encoding'] != '') {
5169
			$this->debug('got content encoding: ' . $this->headers['content-encoding']);
5170
			if ($this->headers['content-encoding'] == 'deflate' || $this->headers['content-encoding'] == 'gzip') {
5171
		    	// if decoding works, use it. else assume data wasn't gzencoded
5172
				if (function_exists('gzuncompress')) {
5173
					if ($this->headers['content-encoding'] == 'deflate' && $degzdata = @gzuncompress($data)) {
5174
						$data = $degzdata;
5175
					} elseif ($this->headers['content-encoding'] == 'gzip' && $degzdata = gzinflate(substr($data, 10))) {
5176
						$data = $degzdata;
5177
					} else {
5178
						$this->fault('SOAP-ENV:Client', 'Errors occurred when trying to decode the data');
5179
						return;
5180
					}
5181
				} else {
5182
					$this->fault('SOAP-ENV:Client', 'This Server does not support compressed data');
5183
					return;
5184
				}
5185
			}
5186
		}
5187
		$this->request .= "\r\n".$data;
5188
		$data = $this->parseRequest($this->headers, $data);
5189
		$this->requestSOAP = $data;
0 ignored issues
show
Documentation Bug introduced by
It seems like $data can also be of type false. However, the property $requestSOAP is declared as type string. Maybe add an additional type check?

Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a mixed type is assigned to a property that is type hinted more strictly.

For example, imagine you have a variable $accountId that can either hold an Id object or false (if there is no account id yet). Your code now assigns that value to the id property of an instance of the Account class. This class holds a proper account, so the id value must no longer be false.

Either this assignment is in error or a type check should be added for that assignment.

class Id
{
    public $id;

    public function __construct($id)
    {
        $this->id = $id;
    }

}

class Account
{
    /** @var  Id $id */
    public $id;
}

$account_id = false;

if (starsAreRight()) {
    $account_id = new Id(42);
}

$account = new Account();
if ($account instanceof Id)
{
    $account->id = $account_id;
}
Loading history...
5190
		$this->debug('leaving parse_request');
5191
	}
5192
5193
	function register_class($classname){
5194
		$this->registeredClass = $classname;
5195
	}
5196
	/**
5197
	* invokes a PHP function for the requested SOAP method
5198
	*
5199
	* The following fields are set by this function (when successful)
5200
	*
5201
	* methodreturn
5202
	*
5203
	* Note that the PHP function that is called may also set the following
5204
	* fields to affect the response sent to the client
5205
	*
5206
	* responseHeaders
5207
	* outgoing_headers
5208
	*
5209
	* This sets the fault field on error
5210
	*
5211
	* @access   private
5212
	*/
5213
	function invoke_method() {
5214
		$this->debug('in invoke_method, methodname=' . $this->methodname . ' methodURI=' . $this->methodURI . ' SOAPAction=' . $this->SOAPAction);
5215
5216
		//
5217
		// if you are debugging in this area of the code, your service uses a class to implement methods,
5218
		// you use SOAP RPC, and the client is .NET, please be aware of the following...
5219
		// when the .NET wsdl.exe utility generates a proxy, it will remove the '.' or '..' from the
5220
		// method name.  that is fine for naming the .NET methods.  it is not fine for properly constructing
5221
		// the XML request and reading the XML response.  you need to add the RequestElementName and
5222
		// ResponseElementName to the System.Web.Services.Protocols.SoapRpcMethodAttribute that wsdl.exe
5223
		// generates for the method.  these parameters are used to specify the correct XML element names
5224
		// for .NET to use, i.e. the names with the '.' in them.
5225
		//
5226
		$orig_methodname = $this->methodname;
5227
		if ($this->wsdl) {
5228
			if ($this->opData = $this->wsdl->getOperationData($this->methodname)) {
5229
				$this->debug('in invoke_method, found WSDL operation=' . $this->methodname);
5230
				$this->appendDebug('opData=' . $this->varDump($this->opData));
5231
			} elseif ($this->opData = $this->wsdl->getOperationDataForSoapAction($this->SOAPAction)) {
5232
				// Note: hopefully this case will only be used for doc/lit, since rpc services should have wrapper element
5233
				$this->debug('in invoke_method, found WSDL soapAction=' . $this->SOAPAction . ' for operation=' . $this->opData['name']);
5234
				$this->appendDebug('opData=' . $this->varDump($this->opData));
5235
				$this->methodname = $this->opData['name'];
5236
			} else {
5237
				$this->debug('in invoke_method, no WSDL for operation=' . $this->methodname);
5238
				$this->fault('SOAP-ENV:Client', "Operation '" . $this->methodname . "' is not defined in the WSDL for this service");
5239
				return;
5240
			}
5241
		} else {
5242
			$this->debug('in invoke_method, no WSDL to validate method');
5243
		}
5244
5245
		// if a . is present in $this->methodname, we see if there is a class in scope,
5246
		// which could be referred to. We will also distinguish between two deliminators,
5247
		// to allow methods to be called a the class or an instance
5248
		if (strpos($this->methodname, '..') > 0) {
5249
			$delim = '..';
5250
		} else if (strpos($this->methodname, '.') > 0) {
5251
			$delim = '.';
5252
		} else {
5253
			$delim = '';
5254
		}
5255
		$this->debug("in invoke_method, delim=$delim");
5256
5257
		$class = '';
5258
		$method = '';
5259
		if (strlen($delim) > 0 && substr_count($this->methodname, $delim) == 1) {
5260
			$try_class = substr($this->methodname, 0, strpos($this->methodname, $delim));
5261
			if (class_exists($try_class)) {
5262
				// get the class and method name
5263
				$class = $try_class;
5264
				$method = substr($this->methodname, strpos($this->methodname, $delim) + strlen($delim));
5265
				$this->debug("in invoke_method, class=$class method=$method delim=$delim");
5266
			} else {
5267
				$this->debug("in invoke_method, class=$try_class not found");
5268
			}
5269
		} else {
5270
			$try_class = '';
5271
			$this->debug("in invoke_method, no class to try");
5272
		}
5273
		if(empty($delim) && isset($this->registeredClass)){
5274
			$class  = $this->registeredClass;
5275
			$delim = '..';
5276
			$method = $this->methodname;
5277
		}
5278
5279
		// does method exist?
5280
		if ($class == '') {
5281
			if (!function_exists($this->methodname)) {
5282
				$this->debug("in invoke_method, function '$this->methodname' not found!");
5283
				$this->result = 'fault: method not found';
5284
				$this->fault('SOAP-ENV:Client',"method '$this->methodname'('$orig_methodname') not defined in service('$try_class' '$delim')");
5285
				return;
5286
			}
5287
		} else {
5288
			$method_to_compare = (substr(phpversion(), 0, 2) == '4.') ? strtolower($method) : $method;
5289
			if (!in_array($method_to_compare, get_class_methods($class))) {
5290
				$this->debug("in invoke_method, method '$this->methodname' not found in class '$class'!");
5291
				$this->result = 'fault: method not found';
5292
				$this->fault('SOAP-ENV:Client',"method '$this->methodname'/'$method_to_compare'('$orig_methodname') not defined in service/'$class'('$try_class' '$delim')");
5293
				return;
5294
			}
5295
		}
5296
5297
		// evaluate message, getting back parameters
5298
		// verify that request parameters match the method's signature
5299
		if(! $this->verify_method($this->methodname,$this->methodparams)){
5300
			// debug
5301
			$this->debug('ERROR: request not verified against method signature');
5302
			$this->result = 'fault: request failed validation against method signature';
5303
			// return fault
5304
			$this->fault('SOAP-ENV:Client',"Operation '$this->methodname' not defined in service.");
5305
			return;
5306
		}
5307
5308
		// if there are parameters to pass
5309
		$this->debug('in invoke_method, params:');
5310
		$this->appendDebug($this->varDump($this->methodparams));
5311
		$this->debug("in invoke_method, calling '$this->methodname'");
5312
		if (!function_exists('call_user_func_array')) {
5313
			if ($class == '') {
5314
				$this->debug('in invoke_method, calling function using eval()');
5315
				$funcCall = "\$this->methodreturn = $this->methodname(";
5316
			} else {
5317
				if ($delim == '..') {
5318
					$this->debug('in invoke_method, calling class method using eval()');
5319
					$funcCall = "\$this->methodreturn = ".$class."::".$method."(";
5320
				} else {
5321
					$this->debug('in invoke_method, calling instance method using eval()');
5322
					// generate unique instance name
5323
					$instname = "\$inst_".time();
5324
					$funcCall = $instname." = new ".$class."(); ";
5325
					$funcCall .= "\$this->methodreturn = ".$instname."->".$method."(";
5326
				}
5327
			}
5328
			if ($this->methodparams) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $this->methodparams of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
5329
				foreach ($this->methodparams as $param) {
5330
					if (is_array($param) || is_object($param)) {
5331
						$this->fault('SOAP-ENV:Client', 'NuSOAP does not handle complexType parameters correctly when using eval; call_user_func_array must be available');
5332
						return;
5333
					}
5334
					$funcCall .= "\"$param\",";
5335
				}
5336
				$funcCall = substr($funcCall, 0, -1);
5337
			}
5338
			$funcCall .= ');';
5339
			$this->debug('in invoke_method, function call: '.$funcCall);
5340
			@eval($funcCall);
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
It is generally not recommended to use eval unless absolutely required.

On one hand, eval might be exploited by malicious users if they somehow manage to inject dynamic content. On the other hand, with the emergence of faster PHP runtimes like the HHVM, eval prevents some optimization that they perform.

Loading history...
5341
		} else {
5342
			if ($class == '') {
5343
				$this->debug('in invoke_method, calling function using call_user_func_array()');
5344
				$call_arg = "$this->methodname";	// straight assignment changes $this->methodname to lower case after call_user_func_array()
5345
			} elseif ($delim == '..') {
5346
				$this->debug('in invoke_method, calling class method using call_user_func_array()');
5347
				$call_arg = array ($class, $method);
5348
			} else {
5349
				$this->debug('in invoke_method, calling instance method using call_user_func_array()');
5350
				$instance = new $class ();
5351
				$call_arg = array(&$instance, $method);
5352
			}
5353
			if (is_array($this->methodparams)) {
5354
				$this->methodreturn = call_user_func_array($call_arg, array_values($this->methodparams));
5355
			} else {
5356
				$this->methodreturn = call_user_func_array($call_arg, array());
5357
			}
5358
		}
5359
        $this->debug('in invoke_method, methodreturn:');
5360
        $this->appendDebug($this->varDump($this->methodreturn));
5361
		$this->debug("in invoke_method, called method $this->methodname, received data of type ".gettype($this->methodreturn));
5362
	}
5363
5364
	/**
5365
	* serializes the return value from a PHP function into a full SOAP Envelope
5366
	*
5367
	* The following fields are set by this function (when successful)
5368
	*
5369
	* responseSOAP
5370
	*
5371
	* This sets the fault field on error
5372
	*
5373
	* @access   private
5374
	*/
5375
	function serialize_return() {
5376
		$this->debug('Entering serialize_return methodname: ' . $this->methodname . ' methodURI: ' . $this->methodURI);
5377
		// if fault
5378
		if (isset($this->methodreturn) && is_object($this->methodreturn) && ((get_class($this->methodreturn) == 'soap_fault') || (get_class($this->methodreturn) == 'nusoap_fault'))) {
5379
			$this->debug('got a fault object from method');
5380
			$this->fault = $this->methodreturn;
5381
			return;
5382
		} elseif ($this->methodreturnisliteralxml) {
5383
			$return_val = $this->methodreturn;
5384
		// returned value(s)
5385
		} else {
5386
			$this->debug('got a(n) '.gettype($this->methodreturn).' from method');
5387
			$this->debug('serializing return value');
5388
			if($this->wsdl){
5389
				if (sizeof($this->opData['output']['parts']) > 1) {
5390
					$this->debug('more than one output part, so use the method return unchanged');
5391
			    	$opParams = $this->methodreturn;
5392
			    } elseif (sizeof($this->opData['output']['parts']) == 1) {
5393
					$this->debug('exactly one output part, so wrap the method return in a simple array');
5394
					// TODO: verify that it is not already wrapped!
5395
			    	//foreach ($this->opData['output']['parts'] as $name => $type) {
5396
					//	$this->debug('wrap in element named ' . $name);
5397
			    	//}
5398
			    	$opParams = array($this->methodreturn);
5399
			    }
5400
			    $return_val = $this->wsdl->serializeRPCParameters($this->methodname,'output',$opParams);
5401
			    $this->appendDebug($this->wsdl->getDebug());
5402
			    $this->wsdl->clearDebug();
5403
				if($errstr = $this->wsdl->getError()){
5404
					$this->debug('got wsdl error: '.$errstr);
5405
					$this->fault('SOAP-ENV:Server', 'unable to serialize result');
5406
					return;
5407
				}
5408
			} else {
5409
				if (isset($this->methodreturn)) {
5410
					$return_val = $this->serialize_val($this->methodreturn, 'return');
5411
				} else {
5412
					$return_val = '';
5413
					$this->debug('in absence of WSDL, assume void return for backward compatibility');
5414
				}
5415
			}
5416
		}
5417
		$this->debug('return value:');
5418
		$this->appendDebug($this->varDump($return_val));
5419
5420
		$this->debug('serializing response');
5421
		if ($this->wsdl) {
5422
			$this->debug('have WSDL for serialization: style is ' . $this->opData['style']);
5423
			if ($this->opData['style'] == 'rpc') {
5424
				$this->debug('style is rpc for serialization: use is ' . $this->opData['output']['use']);
5425
				if ($this->opData['output']['use'] == 'literal') {
5426
					// 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
5427
					if ($this->methodURI) {
5428
						$payload = '<ns1:'.$this->methodname.'Response xmlns:ns1="'.$this->methodURI.'">'.$return_val.'</ns1:'.$this->methodname."Response>";
5429
					} else {
5430
						$payload = '<'.$this->methodname.'Response>'.$return_val.'</'.$this->methodname.'Response>';
5431
					}
5432
				} else {
5433
					if ($this->methodURI) {
5434
						$payload = '<ns1:'.$this->methodname.'Response xmlns:ns1="'.$this->methodURI.'">'.$return_val.'</ns1:'.$this->methodname."Response>";
5435
					} else {
5436
						$payload = '<'.$this->methodname.'Response>'.$return_val.'</'.$this->methodname.'Response>';
5437
					}
5438
				}
5439
			} else {
5440
				$this->debug('style is not rpc for serialization: assume document');
5441
				$payload = $return_val;
5442
			}
5443
		} else {
5444
			$this->debug('do not have WSDL for serialization: assume rpc/encoded');
5445
			$payload = '<ns1:'.$this->methodname.'Response xmlns:ns1="'.$this->methodURI.'">'.$return_val.'</ns1:'.$this->methodname."Response>";
5446
		}
5447
		$this->result = 'successful';
5448
		if($this->wsdl){
5449
			//if($this->debug_flag){
5450
            	$this->appendDebug($this->wsdl->getDebug());
5451
            //	}
5452
			if (isset($this->opData['output']['encodingStyle'])) {
5453
				$encodingStyle = $this->opData['output']['encodingStyle'];
5454
			} else {
5455
				$encodingStyle = '';
5456
			}
5457
			// Added: In case we use a WSDL, return a serialized env. WITH the usedNamespaces.
5458
			$this->responseSOAP = $this->serializeEnvelope($payload,$this->responseHeaders,$this->wsdl->usedNamespaces,$this->opData['style'],$this->opData['output']['use'],$encodingStyle);
5459
		} else {
5460
			$this->responseSOAP = $this->serializeEnvelope($payload,$this->responseHeaders);
5461
		}
5462
		$this->debug("Leaving serialize_return");
5463
	}
5464
5465
	/**
5466
	* sends an HTTP response
5467
	*
5468
	* The following fields are set by this function (when successful)
5469
	*
5470
	* outgoing_headers
5471
	* response
5472
	*
5473
	* @access   private
5474
	*/
5475
	function send_response() {
5476
		$this->debug('Enter send_response');
5477
		if ($this->fault) {
5478
			$payload = $this->fault->serialize();
5479
			$this->outgoing_headers[] = "HTTP/1.0 500 Internal Server Error";
5480
			$this->outgoing_headers[] = "Status: 500 Internal Server Error";
5481
		} else {
5482
			$payload = $this->responseSOAP;
5483
			// Some combinations of PHP+Web server allow the Status
5484
			// to come through as a header.  Since OK is the default
5485
			// just do nothing.
5486
			// $this->outgoing_headers[] = "HTTP/1.0 200 OK";
5487
			// $this->outgoing_headers[] = "Status: 200 OK";
5488
		}
5489
        // add debug data if in debug mode
5490
		if(isset($this->debug_flag) && $this->debug_flag){
5491
        	$payload .= $this->getDebugAsXMLComment();
5492
        }
5493
		$this->outgoing_headers[] = "Server: $this->title Server v$this->version";
5494
		preg_match('/\$Revisio' . 'n: ([^ ]+)/', $this->revision, $rev);
5495
		$this->outgoing_headers[] = "X-SOAP-Server: $this->title/$this->version (".$rev[1].")";
5496
		// Let the Web server decide about this
5497
		//$this->outgoing_headers[] = "Connection: Close\r\n";
5498
		$payload = $this->getHTTPBody($payload);
5499
		$type = $this->getHTTPContentType();
5500
		$charset = $this->getHTTPContentTypeCharset();
5501
		$this->outgoing_headers[] = "Content-Type: $type" . ($charset ? '; charset=' . $charset : '');
5502
		//begin code to compress payload - by John
5503
		// NOTE: there is no way to know whether the Web server will also compress
5504
		// this data.
5505
		if (strlen($payload) > 1024 && isset($this->headers) && isset($this->headers['accept-encoding'])) {
5506
			if (strstr($this->headers['accept-encoding'], 'gzip')) {
5507
				if (function_exists('gzencode')) {
5508
					if (isset($this->debug_flag) && $this->debug_flag) {
5509
						$payload .= "<!-- Content being gzipped -->";
5510
					}
5511
					$this->outgoing_headers[] = "Content-Encoding: gzip";
5512
					$payload = gzencode($payload);
5513
				} else {
5514
					if (isset($this->debug_flag) && $this->debug_flag) {
5515
						$payload .= "<!-- Content will not be gzipped: no gzencode -->";
5516
					}
5517
				}
5518
			} elseif (strstr($this->headers['accept-encoding'], 'deflate')) {
5519
				// Note: MSIE requires gzdeflate output (no Zlib header and checksum),
5520
				// instead of gzcompress output,
5521
				// which conflicts with HTTP 1.1 spec (http://www.w3.org/Protocols/rfc2616/rfc2616-sec3.html#sec3.5)
5522
				if (function_exists('gzdeflate')) {
5523
					if (isset($this->debug_flag) && $this->debug_flag) {
5524
						$payload .= "<!-- Content being deflated -->";
5525
					}
5526
					$this->outgoing_headers[] = "Content-Encoding: deflate";
5527
					$payload = gzdeflate($payload);
5528
				} else {
5529
					if (isset($this->debug_flag) && $this->debug_flag) {
5530
						$payload .= "<!-- Content will not be deflated: no gzcompress -->";
5531
					}
5532
				}
5533
			}
5534
		}
5535
		//end code
5536
		ob_end_clean();
5537
		ob_start();
5538
		$this->outgoing_headers[] = "Content-Length: ".strlen($payload);
5539
		reset($this->outgoing_headers);
5540
		foreach($this->outgoing_headers as $hdr){
5541
			header($hdr, false);
5542
		}
5543
		print $payload;
5544
		ob_flush();
5545
5546
		$this->response = join("\r\n",$this->outgoing_headers)."\r\n\r\n".$payload;
5547
	}
5548
5549
	/**
5550
	* takes the value that was created by parsing the request
5551
	* and compares to the method's signature, if available.
5552
	*
5553
	* @param	string	$operation	The operation to be invoked
5554
	* @param	array	$request	The array of parameter values
5555
	* @return	boolean	Whether the operation was found
5556
	* @access   private
5557
	*/
5558
	function verify_method($operation,$request){
5559
		if(isset($this->wsdl) && is_object($this->wsdl)){
5560
			if($this->wsdl->getOperationData($operation)){
5561
				return true;
5562
			}
5563
	    } elseif(isset($this->operations[$operation])){
5564
			return true;
5565
		}
5566
		return false;
5567
	}
5568
5569
	/**
5570
	* processes SOAP message received from client
5571
	*
5572
	* @param	array	$headers	The HTTP headers
5573
	* @param	string	$data		unprocessed request data from client
5574
	* @return	mixed	value of the message, decoded into a PHP type
5575
	* @access   private
5576
	*/
5577
    function parseRequest($headers, $data) {
5578
		$this->debug('Entering parseRequest() for data of length ' . strlen($data) . ' headers:');
5579
		$this->appendDebug($this->varDump($headers));
5580
    	if (!isset($headers['content-type'])) {
5581
			$this->setError('Request not of type text/xml (no content-type header)');
5582
			return false;
5583
    	}
5584
		if (!strstr($headers['content-type'], 'text/xml')) {
5585
			$this->setError('Request not of type text/xml');
5586
			return false;
5587
		}
5588
		if (strpos($headers['content-type'], '=')) {
5589
			$enc = str_replace('"', '', substr(strstr($headers["content-type"], '='), 1));
5590
			$this->debug('Got response encoding: ' . $enc);
5591
			if(preg_match('/^(ISO-8859-1|US-ASCII|UTF-8)$/i',$enc)){
5592
				$this->xml_encoding = strtoupper($enc);
5593
			} else {
5594
				$this->xml_encoding = 'US-ASCII';
5595
			}
5596
		} else {
5597
			// should be US-ASCII for HTTP 1.0 or ISO-8859-1 for HTTP 1.1
5598
			$this->xml_encoding = 'ISO-8859-1';
5599
		}
5600
		$this->debug('Use encoding: ' . $this->xml_encoding . ' when creating nusoap_parser');
5601
		// parse response, get soap parser obj
5602
		$parser = new nusoap_parser($data,$this->xml_encoding,'',$this->decode_utf8);
5603
		// parser debug
5604
		$this->debug("parser debug: \n".$parser->getDebug());
5605
		// if fault occurred during message parsing
5606
		if($err = $parser->getError()){
5607
			$this->result = 'fault: error in msg parsing: '.$err;
5608
			$this->fault('SOAP-ENV:Client',"error in msg parsing:\n".$err);
5609
		// else successfully parsed request into soapval object
5610
		} else {
5611
			// get/set methodname
5612
			$this->methodURI = $parser->root_struct_namespace;
5613
			$this->methodname = $parser->root_struct_name;
5614
			$this->debug('methodname: '.$this->methodname.' methodURI: '.$this->methodURI);
5615
			$this->debug('calling parser->get_soapbody()');
5616
			$this->methodparams = $parser->get_soapbody();
5617
			// get SOAP headers
5618
			$this->requestHeaders = $parser->getHeaders();
5619
			// get SOAP Header
5620
			$this->requestHeader = $parser->get_soapheader();
5621
            // add document for doclit support
5622
            $this->document = $parser->document;
5623
		}
5624
	 }
5625
5626
	/**
5627
	* gets the HTTP body for the current response.
5628
	*
5629
	* @param string $soapmsg The SOAP payload
5630
	* @return string The HTTP body, which includes the SOAP payload
5631
	* @access private
5632
	*/
5633
	function getHTTPBody($soapmsg) {
5634
		return $soapmsg;
5635
	}
5636
5637
	/**
5638
	* gets the HTTP content type for the current response.
5639
	*
5640
	* Note: getHTTPBody must be called before this.
5641
	*
5642
	* @return string the HTTP content type for the current response.
5643
	* @access private
5644
	*/
5645
	function getHTTPContentType() {
5646
		return 'text/xml';
5647
	}
5648
5649
	/**
5650
	* gets the HTTP content type charset for the current response.
5651
	* returns false for non-text content types.
5652
	*
5653
	* Note: getHTTPBody must be called before this.
5654
	*
5655
	* @return string the HTTP content type charset for the current response.
5656
	* @access private
5657
	*/
5658
	function getHTTPContentTypeCharset() {
5659
		return $this->soap_defencoding;
5660
	}
5661
5662
	/**
5663
	* add a method to the dispatch map (this has been replaced by the register method)
5664
	*
5665
	* @param    string $methodname
5666
	* @param    string $in array of input values
5667
	* @param    string $out array of output values
5668
	* @access   public
5669
	* @deprecated
5670
	*/
5671
	function add_to_map($methodname,$in,$out){
5672
			$this->operations[$methodname] = array('name' => $methodname,'in' => $in,'out' => $out);
5673
	}
5674
5675
	/**
5676
	* register a service function with the server
5677
	*
5678
	* @param    string $name the name of the PHP function, class.method or class..method
5679
	* @param    array $in assoc array of input values: key = param name, value = param type
5680
	* @param    array $out assoc array of output values: key = param name, value = param type
5681
	* @param	mixed $namespace the element namespace for the method or false
5682
	* @param	mixed $soapaction the soapaction for the method or false
5683
	* @param	mixed $style optional (rpc|document) or false Note: when 'document' is specified, parameter and return wrappers are created for you automatically
5684
	* @param	mixed $use optional (encoded|literal) or false
5685
	* @param	string $documentation optional Description to include in WSDL
5686
	* @param	string $encodingStyle optional (usually 'http://schemas.xmlsoap.org/soap/encoding/' for encoded)
5687
	* @access   public
5688
	*/
5689
	function register($name,$in=array(),$out=array(),$namespace=false,$soapaction=false,$style=false,$use=false,$documentation='',$encodingStyle=''){
5690
		global $HTTP_SERVER_VARS;
5691
5692
		if($this->externalWSDLURL){
5693
			die('You cannot bind to an external WSDL file, and register methods outside of it! Please choose either WSDL or no WSDL.');
5694
		}
5695
		if (! $name) {
5696
			die('You must specify a name when you register an operation');
5697
		}
5698
		if (!is_array($in)) {
5699
			die('You must provide an array for operation inputs');
5700
		}
5701
		if (!is_array($out)) {
5702
			die('You must provide an array for operation outputs');
5703
		}
5704
		if(false == $namespace) {
0 ignored issues
show
This if statement is empty and can be removed.

This check looks for the bodies of if statements that have no statements or where all statements have been commented out. This may be the result of changes for debugging or the code may simply be obsolete.

These if bodies can be removed. If you have an empty if but statements in the else branch, consider inverting the condition.

if (rand(1, 6) > 3) {
//print "Check failed";
} else {
    print "Check succeeded";
}

could be turned into

if (rand(1, 6) <= 3) {
    print "Check succeeded";
}

This is much more concise to read.

Loading history...
5705
		}
5706
		if(false == $soapaction) {
5707
			if (isset($_SERVER)) {
5708
				$SERVER_NAME = $_SERVER['SERVER_NAME'];
5709
				$SCRIPT_NAME = isset($_SERVER['PHP_SELF']) ? $_SERVER['PHP_SELF'] : $_SERVER['SCRIPT_NAME'];
5710
				$HTTPS = isset($_SERVER['HTTPS']) ? $_SERVER['HTTPS'] : (isset($HTTP_SERVER_VARS['HTTPS']) ? $HTTP_SERVER_VARS['HTTPS'] : 'off');
5711
			} elseif (isset($HTTP_SERVER_VARS)) {
5712
				$SERVER_NAME = $HTTP_SERVER_VARS['SERVER_NAME'];
5713
				$SCRIPT_NAME = isset($HTTP_SERVER_VARS['PHP_SELF']) ? $HTTP_SERVER_VARS['PHP_SELF'] : $HTTP_SERVER_VARS['SCRIPT_NAME'];
5714
				$HTTPS = isset($HTTP_SERVER_VARS['HTTPS']) ? $HTTP_SERVER_VARS['HTTPS'] : 'off';
5715
			} else {
5716
				$this->setError("Neither _SERVER nor HTTP_SERVER_VARS is available");
5717
			}
5718
        	if ($HTTPS == '1' || $HTTPS == 'on') {
5719
        		$SCHEME = 'https';
5720
        	} else {
5721
        		$SCHEME = 'http';
5722
        	}
5723
			$soapaction = "$SCHEME://$SERVER_NAME$SCRIPT_NAME/$name";
5724
		}
5725
		if(false == $style) {
5726
			$style = "rpc";
5727
		}
5728
		if(false == $use) {
5729
			$use = "encoded";
5730
		}
5731
		if ($use == 'encoded' && $encodingStyle == '') {
5732
			$encodingStyle = 'http://schemas.xmlsoap.org/soap/encoding/';
5733
		}
5734
5735
		$this->operations[$name] = array(
5736
	    'name' => $name,
5737
	    'in' => $in,
5738
	    'out' => $out,
5739
	    'namespace' => $namespace,
5740
	    'soapaction' => $soapaction,
5741
	    'style' => $style);
5742
        if($this->wsdl){
5743
        	$this->wsdl->addOperation($name,$in,$out,$namespace,$soapaction,$style,$use,$documentation,$encodingStyle);
5744
	    }
5745
		return true;
5746
	}
5747
5748
	/**
5749
	* Specify a fault to be returned to the client.
5750
	* This also acts as a flag to the server that a fault has occured.
5751
	*
5752
	* @param	string $faultcode
5753
	* @param	string $faultstring
5754
	* @param	string $faultactor
5755
	* @param	string $faultdetail
5756
	* @access   public
5757
	*/
5758
	function fault($faultcode,$faultstring,$faultactor='',$faultdetail=''){
5759
		if ($faultdetail == '' && $this->debug_flag) {
5760
			$faultdetail = $this->getDebug();
5761
		}
5762
		$this->fault = new nusoap_fault($faultcode,$faultactor,$faultstring,$faultdetail);
5763
		$this->fault->soap_defencoding = $this->soap_defencoding;
5764
	}
5765
5766
    /**
5767
    * Sets up wsdl object.
5768
    * Acts as a flag to enable internal WSDL generation
5769
    *
5770
    * @param string $serviceName, name of the service
0 ignored issues
show
There is no parameter named $serviceName,. Did you maybe mean $serviceName?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function. It has, however, found a similar but not annotated parameter which might be a good fit.

Consider the following example. The parameter $ireland is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $ireland
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was changed, but the annotation was not.

Loading history...
5771
    * @param mixed $namespace optional 'tns' service namespace or false
5772
    * @param mixed $endpoint optional URL of service endpoint or false
5773
    * @param string $style optional (rpc|document) WSDL style (also specified by operation)
5774
    * @param string $transport optional SOAP transport
5775
    * @param mixed $schemaTargetNamespace optional 'types' targetNamespace for service schema or false
5776
    */
5777
    function configureWSDL($serviceName,$namespace = false,$endpoint = false,$style='rpc', $transport = 'http://schemas.xmlsoap.org/soap/http', $schemaTargetNamespace = false)
5778
    {
5779
    	global $HTTP_SERVER_VARS;
5780
5781
		if (isset($_SERVER)) {
5782
			$SERVER_NAME = $_SERVER['SERVER_NAME'];
5783
			$SERVER_PORT = $_SERVER['SERVER_PORT'];
5784
			$SCRIPT_NAME = isset($_SERVER['PHP_SELF']) ? $_SERVER['PHP_SELF'] : $_SERVER['SCRIPT_NAME'];
5785
			$HTTPS = isset($_SERVER['HTTPS']) ? $_SERVER['HTTPS'] : (isset($HTTP_SERVER_VARS['HTTPS']) ? $HTTP_SERVER_VARS['HTTPS'] : 'off');
5786
		} elseif (isset($HTTP_SERVER_VARS)) {
5787
			$SERVER_NAME = $HTTP_SERVER_VARS['SERVER_NAME'];
5788
			$SERVER_PORT = $HTTP_SERVER_VARS['SERVER_PORT'];
5789
			$SCRIPT_NAME = isset($HTTP_SERVER_VARS['PHP_SELF']) ? $HTTP_SERVER_VARS['PHP_SELF'] : $HTTP_SERVER_VARS['SCRIPT_NAME'];
5790
			$HTTPS = isset($HTTP_SERVER_VARS['HTTPS']) ? $HTTP_SERVER_VARS['HTTPS'] : 'off';
5791
		} else {
5792
			$this->setError("Neither _SERVER nor HTTP_SERVER_VARS is available");
5793
		}
5794
		// If server name has port number attached then strip it (else port number gets duplicated in WSDL output) (occurred using lighttpd and FastCGI)
5795
		$colon = strpos($SERVER_NAME,":");
5796
		if ($colon) {
5797
		    $SERVER_NAME = substr($SERVER_NAME, 0, $colon);
5798
		}
5799
		if ($SERVER_PORT == 80) {
5800
			$SERVER_PORT = '';
5801
		} else {
5802
			$SERVER_PORT = ':' . $SERVER_PORT;
5803
		}
5804
        if(false == $namespace) {
5805
            $namespace = "http://$SERVER_NAME/soap/$serviceName";
5806
        }
5807
5808
        if(false == $endpoint) {
5809
        	if ($HTTPS == '1' || $HTTPS == 'on') {
5810
        		$SCHEME = 'https';
5811
        	} else {
5812
        		$SCHEME = 'http';
5813
        	}
5814
            $endpoint = "$SCHEME://$SERVER_NAME$SERVER_PORT$SCRIPT_NAME";
5815
        }
5816
5817
        if(false == $schemaTargetNamespace) {
5818
            $schemaTargetNamespace = $namespace;
5819
        }
5820
5821
		$this->wsdl = new wsdl;
5822
		$this->wsdl->serviceName = $serviceName;
5823
        $this->wsdl->endpoint = $endpoint;
5824
		$this->wsdl->namespaces['tns'] = $namespace;
5825
		$this->wsdl->namespaces['soap'] = 'http://schemas.xmlsoap.org/wsdl/soap/';
5826
		$this->wsdl->namespaces['wsdl'] = 'http://schemas.xmlsoap.org/wsdl/';
5827
		if ($schemaTargetNamespace != $namespace) {
5828
			$this->wsdl->namespaces['types'] = $schemaTargetNamespace;
5829
		}
5830
        $this->wsdl->schemas[$schemaTargetNamespace][0] = new nusoap_xmlschema('', '', $this->wsdl->namespaces);
5831
        if ($style == 'document') {
5832
	        $this->wsdl->schemas[$schemaTargetNamespace][0]->schemaInfo['elementFormDefault'] = 'qualified';
5833
        }
5834
        $this->wsdl->schemas[$schemaTargetNamespace][0]->schemaTargetNamespace = $schemaTargetNamespace;
5835
        $this->wsdl->schemas[$schemaTargetNamespace][0]->imports['http://schemas.xmlsoap.org/soap/encoding/'][0] = array('location' => '', 'loaded' => true);
5836
        $this->wsdl->schemas[$schemaTargetNamespace][0]->imports['http://schemas.xmlsoap.org/wsdl/'][0] = array('location' => '', 'loaded' => true);
5837
        $this->wsdl->bindings[$serviceName.'Binding'] = array(
5838
        	'name'=>$serviceName.'Binding',
5839
            'style'=>$style,
5840
            'transport'=>$transport,
5841
            'portType'=>$serviceName.'PortType');
5842
        $this->wsdl->ports[$serviceName.'Port'] = array(
5843
        	'binding'=>$serviceName.'Binding',
5844
            'location'=>$endpoint,
5845
            'bindingType'=>'http://schemas.xmlsoap.org/wsdl/soap/');
5846
    }
5847
}
5848
5849
/**
5850
 * Backward compatibility
5851
 */
5852
class soap_server extends nusoap_server {
0 ignored issues
show
Comprehensibility Best Practice introduced by
The type soap_server has been defined more than once; this definition is ignored, only the first definition in include/nusoap/class.soap_server.php (L1173-1174) is considered.

This check looks for classes that have been defined more than once.

If you can, we would recommend to use standard object-oriented programming techniques. For example, to avoid multiple types, it might make sense to create a common interface, and then multiple, different implementations for that interface.

This also has the side-effect of providing you with better IDE auto-completion, static analysis and also better OPCode caching from PHP.

Loading history...
Coding Style Compatibility introduced by
PSR1 recommends that each class should be in its own file to aid autoloaders.

Having each class in a dedicated file usually plays nice with PSR autoloaders and is therefore a well established practice. If you use other autoloaders, you might not want to follow this rule.

Loading history...
5853
}
5854
5855
?><?php
5856
5857
/*
5858
5859
Modification information for LGPL compliance
5860
5861
r58622 - 2010-10-22 18:18:59 -0700 (Fri, 22 Oct 2010) - engsvnbuild - Author: lam <[email protected]>
5862
    bug 40066
5863
5864
r58361 - 2010-09-29 16:59:02 -0700 (Wed, 29 Sep 2010) - kjing - Author: Jenny Gonsalves <[email protected]>
5865
    Merging with maint_6_0_1 (svn merge -r 58250:58342)
5866
5867
r57813 - 2010-08-19 10:34:44 -0700 (Thu, 19 Aug 2010) - kjing - Author: John Mertic <[email protected]>
5868
    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.
5869
5870
r57707 - 2010-08-10 12:26:13 -0700 (Tue, 10 Aug 2010) - kjing - Author: Stanislav Malyshev <[email protected]>
5871
    fix SOAP calls with no parameters
5872
5873
r56990 - 2010-06-16 13:05:36 -0700 (Wed, 16 Jun 2010) - kjing - snapshot "Mango" svn branch to a new one for GitHub sync
5874
5875
r56989 - 2010-06-16 13:01:33 -0700 (Wed, 16 Jun 2010) - kjing - defunt "Mango" svn dev branch before github cutover
5876
5877
r55980 - 2010-04-19 13:31:28 -0700 (Mon, 19 Apr 2010) - kjing - create Mango (6.1) based on windex
5878
5879
r51719 - 2009-10-22 10:18:00 -0700 (Thu, 22 Oct 2009) - mitani - Converted to Build 3  tags and updated the build system
5880
5881
r51634 - 2009-10-19 13:32:22 -0700 (Mon, 19 Oct 2009) - mitani - Windex is the branch for Sugar Sales 1.0 development
5882
5883
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.
5884
5885
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.
5886
5887
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:
5888
- Changing all ereg function to either preg or simple string based ones
5889
- No more references to magic quotes.
5890
- Change all the session_unregister() functions to just unset() the correct session variable instead.
5891
5892
r50375 - 2009-08-24 18:07:43 -0700 (Mon, 24 Aug 2009) - dwong - branch kobe2 from tokyo r50372
5893
5894
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
5895
5896
r45680 - 2009-03-30 14:34:35 -0700 (Mon, 30 Mar 2009) - Samir Gandhi - modifeid serializeSchema to generate WS-I compliant WSDL
5897
5898
r42807 - 2008-12-29 11:16:59 -0800 (Mon, 29 Dec 2008) - dwong - Branch from trunk/sugarcrm r42806 to branches/tokyo/sugarcrm
5899
5900
r42645 - 2008-12-18 13:41:08 -0800 (Thu, 18 Dec 2008) - awu - merging maint_5_2_0 rev41336:HEAD to trunk
5901
5902
r41647 - 2008-11-11 17:44:30 -0800 (Tue, 11 Nov 2008) - majed - Fixes a few bugs
5903
5904
r41596 - 2008-11-10 19:20:04 -0800 (Mon, 10 Nov 2008) - Samir Gandhi - modified to set $method in the code
5905
5906
r41558 - 2008-11-10 14:35:34 -0800 (Mon, 10 Nov 2008) - majed - changes nusoap to allow for registering classes
5907
5908
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.
5909
Touched:
5910
- data/SugarBean.php
5911
- include/domit/php_http_client_generic.php
5912
- include/domit/php_http_connector.php
5913
- include/domit/testing_domit.php
5914
- include/domit/xml_domit_getelementsbypath.php
5915
- include/domit/xml_domit_lite_parser.php
5916
- include/domit/xml_domit_nodemaps.php
5917
- include/domit/xml_domit_parser.php
5918
- include/domit/xml_domit_shared.php
5919
- include/generic/SugarWidgets/SugarWidgetField.php
5920
- include/generic/SugarWidgets/SugarWidgetReportField.php
5921
- include/ListView/ProcessView.php
5922
- include/nusoap/class.soapclient.php
5923
- include/nusoap/nusoap.php
5924
- include/nusoap/nusoapmime.php
5925
- include/Pear/HTML_Safe/Safe.php
5926
- include/Pear/XML_HTMLSax3/HTMLSax3.php
5927
- modules/Administration/RebuildWorkFlow.php
5928
- modules/Expressions/RelateSelector.php
5929
- modules/Reports/templates/templates_reports.php
5930
- modules/WorkFlow/Delete.php
5931
- modules/WorkFlow/Save.php
5932
- modules/WorkFlow/SaveSequence.php
5933
- modules/WorkFlow/WorkFlow.php
5934
- modules/WorkFlowActionShells/CreateStep1.php
5935
- modules/WorkFlowActionShells/CreateStep2.php
5936
- modules/WorkFlowActionShells/Save.php
5937
- modules/WorkFlowActionShells/WorkFlowActionShell.php
5938
- modules/WorkFlowAlerts/Save.php
5939
- modules/WorkFlowAlerts/WorkFlowAlert.php
5940
- modules/WorkFlowAlertShells/DetailView.php
5941
- modules/WorkFlowAlertShells/WorkFlowAlertShell.php
5942
- modules/WorkFlowTriggerShells/CreateStep1.php
5943
- modules/WorkFlowTriggerShells/CreateStepFilter.php
5944
- modules/WorkFlowTriggerShells/SaveFilter.php
5945
- modules/WorkFlowTriggerShells/WorkFlowTriggerShell.php
5946
- soap/SoapHelperFunctions.php
5947
- test/modules/DynamicFields/DynamicFields_Bug24095_test.php
5948
- test/simpletest/browser.php
5949
- test/simpletest/default_reporter.php
5950
- test/simpletest/detached.php
5951
- test/simpletest/eclipse.php
5952
- test/simpletest/expectation.php
5953
- test/simpletest/extensions/pear_test_case.php
5954
- test/simpletest/form.php
5955
- test/simpletest/http.php
5956
- test/simpletest/mock_objects.php
5957
- test/simpletest/page.php
5958
- test/simpletest/parser.php
5959
- test/simpletest/remote.php
5960
- test/simpletest/shell_tester.php
5961
- test/simpletest/simple_test.php
5962
- test/simpletest/simpletest.php
5963
- test/simpletest/test/acceptance_test.php
5964
- test/simpletest/test/adapter_test.php
5965
- test/simpletest/test/authentication_test.php
5966
- test/simpletest/test/browser_test.php
5967
- test/simpletest/test/collector_test.php
5968
- test/simpletest/test/compatibility_test.php
5969
- test/simpletest/test/detached_test.php
5970
- test/simpletest/test/eclipse_test.php
5971
- test/simpletest/test/encoding_test.php
5972
- test/simpletest/test/errors_test.php
5973
- test/simpletest/test/expectation_test.php
5974
- test/simpletest/test/form_test.php
5975
- test/simpletest/test/frames_test.php
5976
- test/simpletest/test/http_test.php
5977
- test/simpletest/test/live_test.php
5978
- test/simpletest/test/mock_objects_test.php
5979
- test/simpletest/test/page_test.php
5980
- test/simpletest/test/parse_error_test.php
5981
- test/simpletest/test/parser_test.php
5982
- test/simpletest/test/remote_test.php
5983
- test/simpletest/test/shell_test.php
5984
- test/simpletest/test/shell_tester_test.php
5985
- test/simpletest/test/simpletest_test.php
5986
- test/simpletest/test/site/page_request.php
5987
- test/simpletest/test/tag_test.php
5988
- test/simpletest/test/unit_tester_test.php
5989
- test/simpletest/test/user_agent_test.php
5990
- test/simpletest/test/visual_test.php
5991
- test/simpletest/test/xml_test.php
5992
- test/simpletest/test_case.php
5993
- test/simpletest/ui/array_reporter/test.php
5994
- test/simpletest/ui/recorder/test.php
5995
- test/simpletest/unit_tester.php
5996
- test/simpletest/url.php
5997
- test/simpletest/user_agent.php
5998
- test/simpletest/web_tester.php
5999
- test/spikephpcoverage/src/PEAR.php
6000
- test/spikephpcoverage/src/util/Utility.php
6001
- test/spikephpcoverage/src/XML/Parser.php
6002
- test/spikephpcoverage/src/XML/Parser/Simple.php
6003
- test/test_utilities/SugarTest_SimpleBrowser.php
6004
6005
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.
6006
6007
r38300 - 2008-07-25 13:33:43 -0700 (Fri, 25 Jul 2008) - Samir Gandhi - put the debug in parseresponse function
6008
6009
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
6010
6011
r36824 - 2008-06-18 09:26:11 -0700 (Wed, 18 Jun 2008) - roger - bug: 21832
6012
6013
r26422 - 2007-09-05 17:29:12 -0700 (Wed, 05 Sep 2007) - majed - migrate from beta 1 to trunk
6014
6015
r15787 - 2006-08-10 10:14:41 -0700 (Thu, 10 Aug 2006) - roger - RRS: bug 7961
6016
6017
r14701 - 2006-07-17 13:37:26 -0700 (Mon, 17 Jul 2006) - roger - RRS: bug 5801
6018
6019
r13782 - 2006-06-06 10:58:55 -0700 (Tue, 06 Jun 2006) - majed - changes entry point code
6020
6021
r11466 - 2006-02-01 15:49:47 -0800 (Wed, 01 Feb 2006) - jacob - Adding extra !empty check to get around a PHP warning.
6022
6023
r11115 - 2006-01-17 14:54:45 -0800 (Tue, 17 Jan 2006) - majed - add entry point validation
6024
6025
r10585 - 2005-12-13 14:42:26 -0800 (Tue, 13 Dec 2005) - majed - adds new license mechanisim
6026
6027
r10170 - 2005-12-05 18:37:46 -0800 (Mon, 05 Dec 2005) - majed - fixes various issues
6028
6029
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.
6030
6031
r8991 - 2005-11-03 19:07:25 -0800 (Thu, 03 Nov 2005) - majed - fixes nusoap issue
6032
6033
r8846 - 2005-10-31 11:01:12 -0800 (Mon, 31 Oct 2005) - majed - new version of nusoap
6034
6035
r7905 - 2005-09-21 19:12:57 -0700 (Wed, 21 Sep 2005) - majed - restores old nusoap pre & with a few fixes
6036
6037
r7861 - 2005-09-20 15:40:25 -0700 (Tue, 20 Sep 2005) - majed - & fix for 3.5.1
6038
6039
r7452 - 2005-08-17 11:32:34 -0700 (Wed, 17 Aug 2005) - majed - changes soap to nusoap
6040
6041
r5820 - 2005-06-21 14:22:24 -0700 (Tue, 21 Jun 2005) - majed - fixes issues with nusoap and with custom fields
6042
6043
r5462 - 2005-05-25 13:50:11 -0700 (Wed, 25 May 2005) - majed - upgraded nusoap to .6.9
6044
6045
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
6046
6047
r573 - 2004-09-04 13:03:32 -0700 (Sat, 04 Sep 2004) - sugarclint - undoing copyrights added in inadvertantly.  --clint
6048
6049
r546 - 2004-09-03 11:49:38 -0700 (Fri, 03 Sep 2004) - sugarmsi - removed echo count
6050
6051
r354 - 2004-08-02 23:00:37 -0700 (Mon, 02 Aug 2004) - sugarjacob - Adding Soap
6052
6053
6054
*/
6055
6056
6057
6058
6059
6060
/**
6061
* parses a WSDL file, allows access to it's data, other utility methods.
6062
* also builds WSDL structures programmatically.
6063
*
6064
* @author   Dietrich Ayala <[email protected]>
6065
* @author   Scott Nichol <[email protected]>
6066
6067
* @access public
6068
*/
6069
class wsdl extends nusoap_base {
0 ignored issues
show
Comprehensibility Best Practice introduced by
The type wsdl has been defined more than once; this definition is ignored, only the first definition in include/nusoap/class.wsdl.php (L65-1981) is considered.

This check looks for classes that have been defined more than once.

If you can, we would recommend to use standard object-oriented programming techniques. For example, to avoid multiple types, it might make sense to create a common interface, and then multiple, different implementations for that interface.

This also has the side-effect of providing you with better IDE auto-completion, static analysis and also better OPCode caching from PHP.

Loading history...
Coding Style Compatibility introduced by
PSR1 recommends that each class should be in its own file to aid autoloaders.

Having each class in a dedicated file usually plays nice with PSR autoloaders and is therefore a well established practice. If you use other autoloaders, you might not want to follow this rule.

Loading history...
6070
	// URL or filename of the root of this WSDL
6071
    var $wsdl;
6072
    // define internal arrays of bindings, ports, operations, messages, etc.
6073
    var $schemas = array();
6074
    var $currentSchema;
6075
    var $message = array();
6076
    var $complexTypes = array();
6077
    var $messages = array();
6078
    var $currentMessage;
6079
    var $currentOperation;
6080
    var $portTypes = array();
6081
    var $currentPortType;
6082
    var $bindings = array();
6083
    var $currentBinding;
6084
    var $ports = array();
6085
    var $currentPort;
6086
    var $opData = array();
6087
    var $status = '';
6088
    var $documentation = false;
6089
    var $endpoint = '';
6090
    // array of wsdl docs to import
6091
    var $import = array();
6092
    // parser vars
6093
    var $parser;
6094
    var $position = 0;
6095
    var $depth = 0;
6096
    var $depth_array = array();
6097
	// for getting wsdl
6098
	var $proxyhost = '';
6099
    var $proxyport = '';
6100
	var $proxyusername = '';
6101
	var $proxypassword = '';
6102
	var $timeout = 0;
6103
	var $response_timeout = 30;
6104
	var $curl_options = array();	// User-specified cURL options
6105
	var $use_curl = false;			// whether to always try to use cURL
6106
	// for HTTP authentication
6107
	var $username = '';				// Username for HTTP authentication
6108
	var $password = '';				// Password for HTTP authentication
6109
	var $authtype = '';				// Type of HTTP authentication
6110
	var $certRequest = array();		// Certificate for HTTP SSL authentication
6111
6112
    /**
6113
     * constructor
6114
     *
6115
     * @param string $wsdl WSDL document URL
6116
	 * @param string $proxyhost
6117
	 * @param string $proxyport
6118
	 * @param string $proxyusername
6119
	 * @param string $proxypassword
6120
	 * @param integer $timeout set the connection timeout
6121
	 * @param integer $response_timeout set the response timeout
6122
	 * @param array $curl_options user-specified cURL options
6123
	 * @param boolean $use_curl try to use cURL
6124
     * @access public
6125
     */
6126
    function wsdl($wsdl = '',$proxyhost=false,$proxyport=false,$proxyusername=false,$proxypassword=false,$timeout=0,$response_timeout=30,$curl_options=null,$use_curl=false){
6127
		parent::nusoap_base();
6128
		$this->debug("ctor wsdl=$wsdl timeout=$timeout response_timeout=$response_timeout");
6129
        $this->proxyhost = $proxyhost;
0 ignored issues
show
Documentation Bug introduced by
It seems like $proxyhost can also be of type false. However, the property $proxyhost is declared as type string. Maybe add an additional type check?

Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a mixed type is assigned to a property that is type hinted more strictly.

For example, imagine you have a variable $accountId that can either hold an Id object or false (if there is no account id yet). Your code now assigns that value to the id property of an instance of the Account class. This class holds a proper account, so the id value must no longer be false.

Either this assignment is in error or a type check should be added for that assignment.

class Id
{
    public $id;

    public function __construct($id)
    {
        $this->id = $id;
    }

}

class Account
{
    /** @var  Id $id */
    public $id;
}

$account_id = false;

if (starsAreRight()) {
    $account_id = new Id(42);
}

$account = new Account();
if ($account instanceof Id)
{
    $account->id = $account_id;
}
Loading history...
6130
        $this->proxyport = $proxyport;
0 ignored issues
show
Documentation Bug introduced by
It seems like $proxyport can also be of type false. However, the property $proxyport is declared as type string. Maybe add an additional type check?

Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a mixed type is assigned to a property that is type hinted more strictly.

For example, imagine you have a variable $accountId that can either hold an Id object or false (if there is no account id yet). Your code now assigns that value to the id property of an instance of the Account class. This class holds a proper account, so the id value must no longer be false.

Either this assignment is in error or a type check should be added for that assignment.

class Id
{
    public $id;

    public function __construct($id)
    {
        $this->id = $id;
    }

}

class Account
{
    /** @var  Id $id */
    public $id;
}

$account_id = false;

if (starsAreRight()) {
    $account_id = new Id(42);
}

$account = new Account();
if ($account instanceof Id)
{
    $account->id = $account_id;
}
Loading history...
6131
		$this->proxyusername = $proxyusername;
0 ignored issues
show
Documentation Bug introduced by
It seems like $proxyusername can also be of type false. However, the property $proxyusername is declared as type string. Maybe add an additional type check?

Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a mixed type is assigned to a property that is type hinted more strictly.

For example, imagine you have a variable $accountId that can either hold an Id object or false (if there is no account id yet). Your code now assigns that value to the id property of an instance of the Account class. This class holds a proper account, so the id value must no longer be false.

Either this assignment is in error or a type check should be added for that assignment.

class Id
{
    public $id;

    public function __construct($id)
    {
        $this->id = $id;
    }

}

class Account
{
    /** @var  Id $id */
    public $id;
}

$account_id = false;

if (starsAreRight()) {
    $account_id = new Id(42);
}

$account = new Account();
if ($account instanceof Id)
{
    $account->id = $account_id;
}
Loading history...
6132
		$this->proxypassword = $proxypassword;
0 ignored issues
show
Documentation Bug introduced by
It seems like $proxypassword can also be of type false. However, the property $proxypassword is declared as type string. Maybe add an additional type check?

Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a mixed type is assigned to a property that is type hinted more strictly.

For example, imagine you have a variable $accountId that can either hold an Id object or false (if there is no account id yet). Your code now assigns that value to the id property of an instance of the Account class. This class holds a proper account, so the id value must no longer be false.

Either this assignment is in error or a type check should be added for that assignment.

class Id
{
    public $id;

    public function __construct($id)
    {
        $this->id = $id;
    }

}

class Account
{
    /** @var  Id $id */
    public $id;
}

$account_id = false;

if (starsAreRight()) {
    $account_id = new Id(42);
}

$account = new Account();
if ($account instanceof Id)
{
    $account->id = $account_id;
}
Loading history...
6133
		$this->timeout = $timeout;
6134
		$this->response_timeout = $response_timeout;
6135
		if (is_array($curl_options))
6136
			$this->curl_options = $curl_options;
6137
		$this->use_curl = $use_curl;
6138
		$this->fetchWSDL($wsdl);
6139
    }
6140
6141
	/**
6142
	 * fetches the WSDL document and parses it
6143
	 *
6144
	 * @access public
6145
	 */
6146
	function fetchWSDL($wsdl) {
6147
		$this->debug("parse and process WSDL path=$wsdl");
6148
		$this->wsdl = $wsdl;
6149
        // parse wsdl file
6150
        if ($this->wsdl != "") {
6151
            $this->parseWSDL($this->wsdl);
6152
        }
6153
        // imports
6154
        // TODO: handle imports more properly, grabbing them in-line and nesting them
6155
    	$imported_urls = array();
6156
    	$imported = 1;
6157
    	while ($imported > 0) {
6158
    		$imported = 0;
6159
    		// Schema imports
6160
    		foreach ($this->schemas as $ns => $list) {
6161
    			foreach ($list as $xs) {
6162
					$wsdlparts = parse_url($this->wsdl);	// this is bogusly simple!
6163
		            foreach ($xs->imports as $ns2 => $list2) {
6164
		                for ($ii = 0; $ii < count($list2); $ii++) {
0 ignored issues
show
Performance Best Practice introduced by
It seems like you are calling the size function count() as part of the test condition. You might want to compute the size beforehand, and not on each iteration.

If the size of the collection does not change during the iteration, it is generally a good practice to compute it beforehand, and not on each iteration:

for ($i=0; $i<count($array); $i++) { // calls count() on each iteration
}

// Better
for ($i=0, $c=count($array); $i<$c; $i++) { // calls count() just once
}
Loading history...
6165
		                	if (! $list2[$ii]['loaded']) {
6166
		                		$this->schemas[$ns]->imports[$ns2][$ii]['loaded'] = true;
6167
		                		$url = $list2[$ii]['location'];
6168
								if ($url != '') {
6169
									$urlparts = parse_url($url);
6170
									if (!isset($urlparts['host'])) {
6171
										$url = $wsdlparts['scheme'] . '://' . $wsdlparts['host'] . (isset($wsdlparts['port']) ? ':' .$wsdlparts['port'] : '') .
6172
												substr($wsdlparts['path'],0,strrpos($wsdlparts['path'],'/') + 1) .$urlparts['path'];
6173
									}
6174
									if (! in_array($url, $imported_urls)) {
6175
					                	$this->parseWSDL($url);
6176
				                		$imported++;
6177
				                		$imported_urls[] = $url;
6178
				                	}
6179
								} else {
6180
									$this->debug("Unexpected scenario: empty URL for unloaded import");
6181
								}
6182
							}
6183
						}
6184
		            }
6185
    			}
6186
    		}
6187
    		// WSDL imports
6188
			$wsdlparts = parse_url($this->wsdl);	// this is bogusly simple!
6189
            foreach ($this->import as $ns => $list) {
6190
                for ($ii = 0; $ii < count($list); $ii++) {
0 ignored issues
show
Performance Best Practice introduced by
It seems like you are calling the size function count() as part of the test condition. You might want to compute the size beforehand, and not on each iteration.

If the size of the collection does not change during the iteration, it is generally a good practice to compute it beforehand, and not on each iteration:

for ($i=0; $i<count($array); $i++) { // calls count() on each iteration
}

// Better
for ($i=0, $c=count($array); $i<$c; $i++) { // calls count() just once
}
Loading history...
6191
                	if (! $list[$ii]['loaded']) {
6192
                		$this->import[$ns][$ii]['loaded'] = true;
6193
                		$url = $list[$ii]['location'];
6194
						if ($url != '') {
6195
							$urlparts = parse_url($url);
6196
							if (!isset($urlparts['host'])) {
6197
								$url = $wsdlparts['scheme'] . '://' . $wsdlparts['host'] . (isset($wsdlparts['port']) ? ':' . $wsdlparts['port'] : '') .
6198
										substr($wsdlparts['path'],0,strrpos($wsdlparts['path'],'/') + 1) .$urlparts['path'];
6199
							}
6200
							if (! in_array($url, $imported_urls)) {
6201
			                	$this->parseWSDL($url);
6202
		                		$imported++;
6203
		                		$imported_urls[] = $url;
6204
		                	}
6205
						} else {
6206
							$this->debug("Unexpected scenario: empty URL for unloaded import");
6207
						}
6208
					}
6209
				}
6210
            }
6211
		}
6212
        // add new data to operation data
6213
        foreach($this->bindings as $binding => $bindingData) {
6214
            if (isset($bindingData['operations']) && is_array($bindingData['operations'])) {
6215
                foreach($bindingData['operations'] as $operation => $data) {
6216
                    $this->debug('post-parse data gathering for ' . $operation);
6217
                    $this->bindings[$binding]['operations'][$operation]['input'] =
6218
						isset($this->bindings[$binding]['operations'][$operation]['input']) ?
6219
						array_merge($this->bindings[$binding]['operations'][$operation]['input'], $this->portTypes[ $bindingData['portType'] ][$operation]['input']) :
6220
						$this->portTypes[ $bindingData['portType'] ][$operation]['input'];
6221
                    $this->bindings[$binding]['operations'][$operation]['output'] =
6222
						isset($this->bindings[$binding]['operations'][$operation]['output']) ?
6223
						array_merge($this->bindings[$binding]['operations'][$operation]['output'], $this->portTypes[ $bindingData['portType'] ][$operation]['output']) :
6224
						$this->portTypes[ $bindingData['portType'] ][$operation]['output'];
6225
                    if(isset($this->messages[ $this->bindings[$binding]['operations'][$operation]['input']['message'] ])){
6226
						$this->bindings[$binding]['operations'][$operation]['input']['parts'] = $this->messages[ $this->bindings[$binding]['operations'][$operation]['input']['message'] ];
6227
					}
6228
					if(isset($this->messages[ $this->bindings[$binding]['operations'][$operation]['output']['message'] ])){
6229
                   		$this->bindings[$binding]['operations'][$operation]['output']['parts'] = $this->messages[ $this->bindings[$binding]['operations'][$operation]['output']['message'] ];
6230
                    }
6231
                    // Set operation style if necessary, but do not override one already provided
6232
					if (isset($bindingData['style']) && !isset($this->bindings[$binding]['operations'][$operation]['style'])) {
6233
                        $this->bindings[$binding]['operations'][$operation]['style'] = $bindingData['style'];
6234
                    }
6235
                    $this->bindings[$binding]['operations'][$operation]['transport'] = isset($bindingData['transport']) ? $bindingData['transport'] : '';
6236
                    $this->bindings[$binding]['operations'][$operation]['documentation'] = isset($this->portTypes[ $bindingData['portType'] ][$operation]['documentation']) ? $this->portTypes[ $bindingData['portType'] ][$operation]['documentation'] : '';
6237
                    $this->bindings[$binding]['operations'][$operation]['endpoint'] = isset($bindingData['endpoint']) ? $bindingData['endpoint'] : '';
6238
                }
6239
            }
6240
        }
6241
	}
6242
6243
    /**
6244
     * parses the wsdl document
6245
     *
6246
     * @param string $wsdl path or URL
6247
     * @access private
6248
     */
6249
    function parseWSDL($wsdl = '') {
6250
		$this->debug("parse WSDL at path=$wsdl");
6251
6252
        if ($wsdl == '') {
6253
            $this->debug('no wsdl passed to parseWSDL()!!');
6254
            $this->setError('no wsdl passed to parseWSDL()!!');
6255
            return false;
6256
        }
6257
6258
        // parse $wsdl for url format
6259
        $wsdl_props = parse_url($wsdl);
6260
6261
        if (isset($wsdl_props['scheme']) && ($wsdl_props['scheme'] == 'http' || $wsdl_props['scheme'] == 'https')) {
6262
            $this->debug('getting WSDL http(s) URL ' . $wsdl);
6263
        	// get wsdl
6264
	        $tr = new soap_transport_http($wsdl, $this->curl_options, $this->use_curl);
6265
			$tr->request_method = 'GET';
6266
			$tr->useSOAPAction = false;
6267
			if($this->proxyhost && $this->proxyport){
6268
				$tr->setProxy($this->proxyhost,$this->proxyport,$this->proxyusername,$this->proxypassword);
6269
			}
6270
			if ($this->authtype != '') {
6271
				$tr->setCredentials($this->username, $this->password, $this->authtype, array(), $this->certRequest);
6272
			}
6273
			$tr->setEncoding('gzip, deflate');
6274
			$wsdl_string = $tr->send('', $this->timeout, $this->response_timeout);
6275
			//$this->debug("WSDL request\n" . $tr->outgoing_payload);
6276
			//$this->debug("WSDL response\n" . $tr->incoming_payload);
6277
			$this->appendDebug($tr->getDebug());
6278
			// catch errors
6279
			if($err = $tr->getError() ){
6280
				$errstr = 'Getting ' . $wsdl . ' - HTTP ERROR: '.$err;
6281
				$this->debug($errstr);
6282
	            $this->setError($errstr);
6283
				unset($tr);
6284
	            return false;
6285
			}
6286
			unset($tr);
6287
			$this->debug("got WSDL URL");
6288
        } else {
6289
            // $wsdl is not http(s), so treat it as a file URL or plain file path
6290
        	if (isset($wsdl_props['scheme']) && ($wsdl_props['scheme'] == 'file') && isset($wsdl_props['path'])) {
6291
        		$path = isset($wsdl_props['host']) ? ($wsdl_props['host'] . ':' . $wsdl_props['path']) : $wsdl_props['path'];
6292
        	} else {
6293
        		$path = $wsdl;
6294
        	}
6295
            $this->debug('getting WSDL file ' . $path);
6296
            if ($fp = @fopen($path, 'r')) {
6297
                $wsdl_string = '';
6298
                while ($data = fread($fp, 32768)) {
6299
                    $wsdl_string .= $data;
6300
                }
6301
                fclose($fp);
6302
            } else {
6303
            	$errstr = "Bad path to WSDL file $path";
6304
            	$this->debug($errstr);
6305
                $this->setError($errstr);
6306
                return false;
6307
            }
6308
        }
6309
        $this->debug('Parse WSDL');
6310
        // end new code added
6311
        // Create an XML parser.
6312
        $this->parser = xml_parser_create();
6313
        // Set the options for parsing the XML data.
6314
        // xml_parser_set_option($parser, XML_OPTION_SKIP_WHITE, 1);
6315
        xml_parser_set_option($this->parser, XML_OPTION_CASE_FOLDING, 0);
6316
        // Set the object for the parser.
6317
        xml_set_object($this->parser, $this);
6318
        // Set the element handlers for the parser.
6319
        xml_set_element_handler($this->parser, 'start_element', 'end_element');
6320
        xml_set_character_data_handler($this->parser, 'character_data');
6321
        // Parse the XML file.
6322
        if (!xml_parse($this->parser, $wsdl_string, true)) {
6323
            // Display an error message.
6324
            $errstr = sprintf(
6325
				'XML error parsing WSDL from %s on line %d: %s',
6326
				$wsdl,
6327
                xml_get_current_line_number($this->parser),
6328
                xml_error_string(xml_get_error_code($this->parser))
6329
                );
6330
            $this->debug($errstr);
6331
			$this->debug("XML payload:\n" . $wsdl_string);
6332
            $this->setError($errstr);
6333
            return false;
6334
        }
6335
		// free the parser
6336
        xml_parser_free($this->parser);
6337
        $this->debug('Parsing WSDL done');
6338
		// catch wsdl parse errors
6339
		if($this->getError()){
6340
			return false;
6341
		}
6342
        return true;
6343
    }
6344
6345
    /**
6346
     * start-element handler
6347
     *
6348
     * @param string $parser XML parser object
6349
     * @param string $name element name
6350
     * @param string $attrs associative array of attributes
6351
     * @access private
6352
     */
6353
    function start_element($parser, $name, $attrs)
6354
    {
6355
        if ($this->status == 'schema') {
6356
            $this->currentSchema->schemaStartElement($parser, $name, $attrs);
6357
            $this->appendDebug($this->currentSchema->getDebug());
6358
            $this->currentSchema->clearDebug();
6359
        } elseif (preg_match('/schema$/', $name)) {
6360
        	$this->debug('Parsing WSDL schema');
6361
            // $this->debug("startElement for $name ($attrs[name]). status = $this->status (".$this->getLocalPart($name).")");
6362
            $this->status = 'schema';
6363
            $this->currentSchema = new nusoap_xmlschema('', '', $this->namespaces);
6364
            $this->currentSchema->schemaStartElement($parser, $name, $attrs);
6365
            $this->appendDebug($this->currentSchema->getDebug());
6366
            $this->currentSchema->clearDebug();
6367
        } else {
6368
            // position in the total number of elements, starting from 0
6369
            $pos = $this->position++;
6370
            $depth = $this->depth++;
6371
            // set self as current value for this depth
6372
            $this->depth_array[$depth] = $pos;
6373
            $this->message[$pos] = array('cdata' => '');
6374
            // process attributes
6375
            if (count($attrs) > 0) {
6376
				// register namespace declarations
6377
                foreach($attrs as $k => $v) {
0 ignored issues
show
The expression $attrs of type string is not traversable.
Loading history...
6378
                    if (preg_match('/^xmlns/',$k)) {
6379
                        if ($ns_prefix = substr(strrchr($k, ':'), 1)) {
6380
                            $this->namespaces[$ns_prefix] = $v;
6381
                        } else {
6382
                            $this->namespaces['ns' . (count($this->namespaces) + 1)] = $v;
6383
                        }
6384
                        if ($v == 'http://www.w3.org/2001/XMLSchema' || $v == 'http://www.w3.org/1999/XMLSchema' || $v == 'http://www.w3.org/2000/10/XMLSchema') {
6385
                            $this->XMLSchemaVersion = $v;
6386
                            $this->namespaces['xsi'] = $v . '-instance';
6387
                        }
6388
                    }
6389
                }
6390
                // expand each attribute prefix to its namespace
6391
                foreach($attrs as $k => $v) {
0 ignored issues
show
The expression $attrs of type string is not traversable.
Loading history...
6392
                    $k = strpos($k, ':') ? $this->expandQname($k) : $k;
6393
                    if ($k != 'location' && $k != 'soapAction' && $k != 'namespace') {
6394
                        $v = strpos($v, ':') ? $this->expandQname($v) : $v;
6395
                    }
6396
                    $eAttrs[$k] = $v;
6397
                }
6398
                $attrs = $eAttrs;
6399
            } else {
6400
                $attrs = array();
6401
            }
6402
            // get element prefix, namespace and name
6403
            if (preg_match('/:/', $name)) {
6404
                // get ns prefix
6405
                $prefix = substr($name, 0, strpos($name, ':'));
6406
                // get ns
6407
                $namespace = isset($this->namespaces[$prefix]) ? $this->namespaces[$prefix] : '';
6408
                // get unqualified name
6409
                $name = substr(strstr($name, ':'), 1);
6410
            }
6411
			// process attributes, expanding any prefixes to namespaces
6412
            // find status, register data
6413
            switch ($this->status) {
6414
                case 'message':
6415
                    if ($name == 'part') {
6416
			            if (isset($attrs['type'])) {
6417
		                    $this->debug("msg " . $this->currentMessage . ": found part (with type) $attrs[name]: " . implode(',', $attrs));
6418
		                    $this->messages[$this->currentMessage][$attrs['name']] = $attrs['type'];
6419
            			}
6420
			            if (isset($attrs['element'])) {
6421
		                    $this->debug("msg " . $this->currentMessage . ": found part (with element) $attrs[name]: " . implode(',', $attrs));
6422
			                $this->messages[$this->currentMessage][$attrs['name']] = $attrs['element'] . '^';
6423
			            }
6424
        			}
6425
        			break;
6426
			    case 'portType':
6427
			        switch ($name) {
6428
			            case 'operation':
6429
			                $this->currentPortOperation = $attrs['name'];
6430
			                $this->debug("portType $this->currentPortType operation: $this->currentPortOperation");
6431
			                if (isset($attrs['parameterOrder'])) {
6432
			                	$this->portTypes[$this->currentPortType][$attrs['name']]['parameterOrder'] = $attrs['parameterOrder'];
6433
			        		}
6434
			        		break;
6435
					    case 'documentation':
6436
					        $this->documentation = true;
6437
					        break;
6438
					    // merge input/output data
6439
					    default:
6440
					        $m = isset($attrs['message']) ? $this->getLocalPart($attrs['message']) : '';
6441
					        $this->portTypes[$this->currentPortType][$this->currentPortOperation][$name]['message'] = $m;
6442
					        break;
6443
					}
6444
			    	break;
6445
				case 'binding':
6446
				    switch ($name) {
6447
				        case 'binding':
6448
				            // get ns prefix
6449
				            if (isset($attrs['style'])) {
6450
				            $this->bindings[$this->currentBinding]['prefix'] = $prefix;
6451
					    	}
6452
					    	$this->bindings[$this->currentBinding] = array_merge($this->bindings[$this->currentBinding], $attrs);
6453
					    	break;
6454
						case 'header':
6455
						    $this->bindings[$this->currentBinding]['operations'][$this->currentOperation][$this->opStatus]['headers'][] = $attrs;
6456
						    break;
6457
						case 'operation':
6458
						    if (isset($attrs['soapAction'])) {
6459
						        $this->bindings[$this->currentBinding]['operations'][$this->currentOperation]['soapAction'] = $attrs['soapAction'];
6460
						    }
6461
						    if (isset($attrs['style'])) {
6462
						        $this->bindings[$this->currentBinding]['operations'][$this->currentOperation]['style'] = $attrs['style'];
6463
						    }
6464
						    if (isset($attrs['name'])) {
6465
						        $this->currentOperation = $attrs['name'];
6466
						        $this->debug("current binding operation: $this->currentOperation");
6467
						        $this->bindings[$this->currentBinding]['operations'][$this->currentOperation]['name'] = $attrs['name'];
6468
						        $this->bindings[$this->currentBinding]['operations'][$this->currentOperation]['binding'] = $this->currentBinding;
6469
						        $this->bindings[$this->currentBinding]['operations'][$this->currentOperation]['endpoint'] = isset($this->bindings[$this->currentBinding]['endpoint']) ? $this->bindings[$this->currentBinding]['endpoint'] : '';
6470
						    }
6471
						    break;
6472
						case 'input':
6473
						    $this->opStatus = 'input';
6474
						    break;
6475
						case 'output':
6476
						    $this->opStatus = 'output';
6477
						    break;
6478
						case 'body':
6479
						    if (isset($this->bindings[$this->currentBinding]['operations'][$this->currentOperation][$this->opStatus])) {
6480
						        $this->bindings[$this->currentBinding]['operations'][$this->currentOperation][$this->opStatus] = array_merge($this->bindings[$this->currentBinding]['operations'][$this->currentOperation][$this->opStatus], $attrs);
6481
						    } else {
6482
						        $this->bindings[$this->currentBinding]['operations'][$this->currentOperation][$this->opStatus] = $attrs;
6483
						    }
6484
						    break;
6485
					}
6486
					break;
6487
				case 'service':
6488
					switch ($name) {
6489
					    case 'port':
6490
					        $this->currentPort = $attrs['name'];
6491
					        $this->debug('current port: ' . $this->currentPort);
6492
					        $this->ports[$this->currentPort]['binding'] = $this->getLocalPart($attrs['binding']);
6493
6494
					        break;
6495
					    case 'address':
6496
					        $this->ports[$this->currentPort]['location'] = $attrs['location'];
6497
					        $this->ports[$this->currentPort]['bindingType'] = $namespace;
6498
					        $this->bindings[ $this->ports[$this->currentPort]['binding'] ]['bindingType'] = $namespace;
6499
					        $this->bindings[ $this->ports[$this->currentPort]['binding'] ]['endpoint'] = $attrs['location'];
6500
					        break;
6501
					}
6502
					break;
6503
			}
6504
		// set status
6505
		switch ($name) {
6506
			case 'import':
6507
			    if (isset($attrs['location'])) {
6508
                    $this->import[$attrs['namespace']][] = array('location' => $attrs['location'], 'loaded' => false);
6509
                    $this->debug('parsing import ' . $attrs['namespace']. ' - ' . $attrs['location'] . ' (' . count($this->import[$attrs['namespace']]).')');
6510
				} else {
6511
                    $this->import[$attrs['namespace']][] = array('location' => '', 'loaded' => true);
6512
					if (! $this->getPrefixFromNamespace($attrs['namespace'])) {
6513
						$this->namespaces['ns'.(count($this->namespaces)+1)] = $attrs['namespace'];
6514
					}
6515
                    $this->debug('parsing import ' . $attrs['namespace']. ' - [no location] (' . count($this->import[$attrs['namespace']]).')');
6516
				}
6517
				break;
6518
			//wait for schema
6519
			//case 'types':
6520
			//	$this->status = 'schema';
6521
			//	break;
6522
			case 'message':
6523
				$this->status = 'message';
6524
				$this->messages[$attrs['name']] = array();
6525
				$this->currentMessage = $attrs['name'];
6526
				break;
6527
			case 'portType':
6528
				$this->status = 'portType';
6529
				$this->portTypes[$attrs['name']] = array();
6530
				$this->currentPortType = $attrs['name'];
6531
				break;
6532
			case "binding":
6533
				if (isset($attrs['name'])) {
6534
				// get binding name
6535
					if (strpos($attrs['name'], ':')) {
6536
			    		$this->currentBinding = $this->getLocalPart($attrs['name']);
6537
					} else {
6538
			    		$this->currentBinding = $attrs['name'];
6539
					}
6540
					$this->status = 'binding';
6541
					$this->bindings[$this->currentBinding]['portType'] = $this->getLocalPart($attrs['type']);
6542
					$this->debug("current binding: $this->currentBinding of portType: " . $attrs['type']);
6543
				}
6544
				break;
6545
			case 'service':
6546
				$this->serviceName = $attrs['name'];
6547
				$this->status = 'service';
6548
				$this->debug('current service: ' . $this->serviceName);
6549
				break;
6550
			case 'definitions':
6551
				foreach ($attrs as $name => $value) {
6552
					$this->wsdl_info[$name] = $value;
6553
				}
6554
				break;
6555
			}
6556
		}
6557
	}
6558
6559
	/**
6560
	* end-element handler
6561
	*
6562
	* @param string $parser XML parser object
6563
	* @param string $name element name
6564
	* @access private
6565
	*/
6566
	function end_element($parser, $name){
6567
		// unset schema status
6568
		if (/*preg_match('/types$/', $name) ||*/ preg_match('/schema$/', $name)) {
6569
			$this->status = "";
6570
            $this->appendDebug($this->currentSchema->getDebug());
6571
            $this->currentSchema->clearDebug();
6572
			$this->schemas[$this->currentSchema->schemaTargetNamespace][] = $this->currentSchema;
6573
        	$this->debug('Parsing WSDL schema done');
6574
		}
6575
		if ($this->status == 'schema') {
6576
			$this->currentSchema->schemaEndElement($parser, $name);
6577
		} else {
6578
			// bring depth down a notch
6579
			$this->depth--;
6580
		}
6581
		// end documentation
6582
		if ($this->documentation) {
6583
			//TODO: track the node to which documentation should be assigned; it can be a part, message, etc.
6584
			//$this->portTypes[$this->currentPortType][$this->currentPortOperation]['documentation'] = $this->documentation;
6585
			$this->documentation = false;
6586
		}
6587
	}
6588
6589
	/**
6590
	 * element content handler
6591
	 *
6592
	 * @param string $parser XML parser object
6593
	 * @param string $data element content
6594
	 * @access private
6595
	 */
6596
	function character_data($parser, $data)
6597
	{
6598
		$pos = isset($this->depth_array[$this->depth]) ? $this->depth_array[$this->depth] : 0;
6599
		if (isset($this->message[$pos]['cdata'])) {
6600
			$this->message[$pos]['cdata'] .= $data;
6601
		}
6602
		if ($this->documentation) {
6603
			$this->documentation .= $data;
6604
		}
6605
	}
6606
6607
	/**
6608
	* if authenticating, set user credentials here
6609
	*
6610
	* @param    string $username
6611
	* @param    string $password
6612
	* @param	string $authtype (basic|digest|certificate|ntlm)
6613
	* @param	array $certRequest (keys must be cainfofile (optional), sslcertfile, sslkeyfile, passphrase, certpassword (optional), verifypeer (optional), verifyhost (optional): see corresponding options in cURL docs)
6614
	* @access   public
6615
	*/
6616
	function setCredentials($username, $password, $authtype = 'basic', $certRequest = array()) {
6617
		$this->debug("setCredentials username=$username authtype=$authtype certRequest=");
6618
		$this->appendDebug($this->varDump($certRequest));
6619
		$this->username = $username;
6620
		$this->password = $password;
6621
		$this->authtype = $authtype;
6622
		$this->certRequest = $certRequest;
6623
	}
6624
6625
	function getBindingData($binding)
6626
	{
6627
		if (is_array($this->bindings[$binding])) {
6628
			return $this->bindings[$binding];
6629
		}
6630
	}
6631
6632
	/**
6633
	 * returns an assoc array of operation names => operation data
6634
	 *
6635
	 * @param string $portName WSDL port name
6636
	 * @param string $bindingType eg: soap, smtp, dime (only soap and soap12 are currently supported)
6637
	 * @return array
6638
	 * @access public
6639
	 */
6640
	function getOperations($portName = '', $bindingType = 'soap') {
6641
		$ops = array();
6642
		if ($bindingType == 'soap') {
6643
			$bindingType = 'http://schemas.xmlsoap.org/wsdl/soap/';
6644
		} elseif ($bindingType == 'soap12') {
6645
			$bindingType = 'http://schemas.xmlsoap.org/wsdl/soap12/';
6646
		} else {
6647
			$this->debug("getOperations bindingType $bindingType may not be supported");
6648
		}
6649
		$this->debug("getOperations for port '$portName' bindingType $bindingType");
6650
		// loop thru ports
6651
		foreach($this->ports as $port => $portData) {
6652
			$this->debug("getOperations checking port $port bindingType " . $portData['bindingType']);
6653
			if ($portName == '' || $port == $portName) {
6654
				// binding type of port matches parameter
6655
				if ($portData['bindingType'] == $bindingType) {
6656
					$this->debug("getOperations found port $port bindingType $bindingType");
6657
					//$this->debug("port data: " . $this->varDump($portData));
6658
					//$this->debug("bindings: " . $this->varDump($this->bindings[ $portData['binding'] ]));
6659
					// merge bindings
6660
					if (isset($this->bindings[ $portData['binding'] ]['operations'])) {
6661
						$ops = array_merge ($ops, $this->bindings[ $portData['binding'] ]['operations']);
6662
					}
6663
				}
6664
			}
6665
		}
6666
		if (count($ops) == 0) {
6667
			$this->debug("getOperations found no operations for port '$portName' bindingType $bindingType");
6668
		}
6669
		return $ops;
6670
	}
6671
6672
	/**
6673
	 * returns an associative array of data necessary for calling an operation
6674
	 *
6675
	 * @param string $operation name of operation
6676
	 * @param string $bindingType type of binding eg: soap, soap12
6677
	 * @return array
6678
	 * @access public
6679
	 */
6680
	function getOperationData($operation, $bindingType = 'soap')
6681
	{
6682
		if ($bindingType == 'soap') {
6683
			$bindingType = 'http://schemas.xmlsoap.org/wsdl/soap/';
6684
		} elseif ($bindingType == 'soap12') {
6685
			$bindingType = 'http://schemas.xmlsoap.org/wsdl/soap12/';
6686
		}
6687
		// loop thru ports
6688
		foreach($this->ports as $port => $portData) {
6689
			// binding type of port matches parameter
6690
			if ($portData['bindingType'] == $bindingType) {
6691
				// get binding
6692
				//foreach($this->bindings[ $portData['binding'] ]['operations'] as $bOperation => $opData) {
6693
				foreach(array_keys($this->bindings[ $portData['binding'] ]['operations']) as $bOperation) {
6694
					// note that we could/should also check the namespace here
6695
					if ($operation == $bOperation) {
6696
						$opData = $this->bindings[ $portData['binding'] ]['operations'][$operation];
6697
					    return $opData;
6698
					}
6699
				}
6700
			}
6701
		}
6702
	}
6703
6704
	/**
6705
	 * returns an associative array of data necessary for calling an operation
6706
	 *
6707
	 * @param string $soapAction soapAction for operation
6708
	 * @param string $bindingType type of binding eg: soap, soap12
6709
	 * @return array
6710
	 * @access public
6711
	 */
6712
	function getOperationDataForSoapAction($soapAction, $bindingType = 'soap') {
6713
		if ($bindingType == 'soap') {
6714
			$bindingType = 'http://schemas.xmlsoap.org/wsdl/soap/';
6715
		} elseif ($bindingType == 'soap12') {
6716
			$bindingType = 'http://schemas.xmlsoap.org/wsdl/soap12/';
6717
		}
6718
		// loop thru ports
6719
		foreach($this->ports as $port => $portData) {
6720
			// binding type of port matches parameter
6721
			if ($portData['bindingType'] == $bindingType) {
6722
				// loop through operations for the binding
6723
				foreach ($this->bindings[ $portData['binding'] ]['operations'] as $bOperation => $opData) {
6724
					if ($opData['soapAction'] == $soapAction) {
6725
					    return $opData;
6726
					}
6727
				}
6728
			}
6729
		}
6730
	}
6731
6732
	/**
6733
    * returns an array of information about a given type
6734
    * returns false if no type exists by the given name
6735
    *
6736
	*	 typeDef = array(
6737
	*	 'elements' => array(), // refs to elements array
6738
	*	'restrictionBase' => '',
6739
	*	'phpType' => '',
6740
	*	'order' => '(sequence|all)',
6741
	*	'attrs' => array() // refs to attributes array
6742
	*	)
6743
    *
6744
    * @param string $type the type
6745
    * @param string $ns namespace (not prefix) of the type
6746
    * @return mixed
6747
    * @access public
6748
    * @see nusoap_xmlschema
6749
    */
6750
	function getTypeDef($type, $ns) {
6751
		$this->debug("in getTypeDef: type=$type, ns=$ns");
6752
		if ((! $ns) && isset($this->namespaces['tns'])) {
6753
			$ns = $this->namespaces['tns'];
6754
			$this->debug("in getTypeDef: type namespace forced to $ns");
6755
		}
6756
		if (!isset($this->schemas[$ns])) {
6757
			foreach ($this->schemas as $ns0 => $schema0) {
6758
				if (strcasecmp($ns, $ns0) == 0) {
6759
					$this->debug("in getTypeDef: replacing schema namespace $ns with $ns0");
6760
					$ns = $ns0;
6761
					break;
6762
				}
6763
			}
6764
		}
6765
		if (isset($this->schemas[$ns])) {
6766
			$this->debug("in getTypeDef: have schema for namespace $ns");
6767
			for ($i = 0; $i < count($this->schemas[$ns]); $i++) {
0 ignored issues
show
Performance Best Practice introduced by
It seems like you are calling the size function count() as part of the test condition. You might want to compute the size beforehand, and not on each iteration.

If the size of the collection does not change during the iteration, it is generally a good practice to compute it beforehand, and not on each iteration:

for ($i=0; $i<count($array); $i++) { // calls count() on each iteration
}

// Better
for ($i=0, $c=count($array); $i<$c; $i++) { // calls count() just once
}
Loading history...
6768
				$xs = &$this->schemas[$ns][$i];
6769
				$t = $xs->getTypeDef($type);
6770
				$this->appendDebug($xs->getDebug());
6771
				$xs->clearDebug();
6772
				if ($t) {
6773
					$this->debug("in getTypeDef: found type $type");
6774
					if (!isset($t['phpType'])) {
6775
						// get info for type to tack onto the element
6776
						$uqType = substr($t['type'], strrpos($t['type'], ':') + 1);
6777
						$ns = substr($t['type'], 0, strrpos($t['type'], ':'));
6778
						$etype = $this->getTypeDef($uqType, $ns);
6779
						if ($etype) {
6780
							$this->debug("found type for [element] $type:");
6781
							$this->debug($this->varDump($etype));
6782
							if (isset($etype['phpType'])) {
6783
								$t['phpType'] = $etype['phpType'];
6784
							}
6785
							if (isset($etype['elements'])) {
6786
								$t['elements'] = $etype['elements'];
6787
							}
6788
							if (isset($etype['attrs'])) {
6789
								$t['attrs'] = $etype['attrs'];
6790
							}
6791
						} else {
6792
							$this->debug("did not find type for [element] $type");
6793
						}
6794
					}
6795
					return $t;
6796
				}
6797
			}
6798
			$this->debug("in getTypeDef: did not find type $type");
6799
		} else {
6800
			$this->debug("in getTypeDef: do not have schema for namespace $ns");
6801
		}
6802
		return false;
6803
	}
6804
6805
    /**
6806
    * prints html description of services
6807
    *
6808
    * @access private
6809
    */
6810
    function webDescription(){
6811
    	global $HTTP_SERVER_VARS;
6812
6813
		if (isset($_SERVER)) {
6814
			$PHP_SELF = $_SERVER['PHP_SELF'];
6815
		} elseif (isset($HTTP_SERVER_VARS)) {
6816
			$PHP_SELF = $HTTP_SERVER_VARS['PHP_SELF'];
6817
		} else {
6818
			$this->setError("Neither _SERVER nor HTTP_SERVER_VARS is available");
6819
		}
6820
6821
		$b = '
6822
		<html><head><title>NuSOAP: '.$this->serviceName.'</title>
6823
		<style type="text/css">
6824
		    body    { font-family: arial; color: #000000; background-color: #ffffff; margin: 0px 0px 0px 0px; }
6825
		    p       { font-family: arial; color: #000000; margin-top: 0px; margin-bottom: 12px; }
6826
		    pre { background-color: silver; padding: 5px; font-family: Courier New; font-size: x-small; color: #000000;}
6827
		    ul      { margin-top: 10px; margin-left: 20px; }
6828
		    li      { list-style-type: none; margin-top: 10px; color: #000000; }
6829
		    .content{
6830
			margin-left: 0px; padding-bottom: 2em; }
6831
		    .nav {
6832
			padding-top: 10px; padding-bottom: 10px; padding-left: 15px; font-size: .70em;
6833
			margin-top: 10px; margin-left: 0px; color: #000000;
6834
			background-color: #ccccff; width: 20%; margin-left: 20px; margin-top: 20px; }
6835
		    .title {
6836
			font-family: arial; font-size: 26px; color: #ffffff;
6837
			background-color: #999999; width: 100%;
6838
			margin-left: 0px; margin-right: 0px;
6839
			padding-top: 10px; padding-bottom: 10px;}
6840
		    .hidden {
6841
			position: absolute; visibility: hidden; z-index: 200; left: 250px; top: 100px;
6842
			font-family: arial; overflow: hidden; width: 600;
6843
			padding: 20px; font-size: 10px; background-color: #999999;
6844
			layer-background-color:#FFFFFF; }
6845
		    a,a:active  { color: charcoal; font-weight: bold; }
6846
		    a:visited   { color: #666666; font-weight: bold; }
6847
		    a:hover     { color: cc3300; font-weight: bold; }
6848
		</style>
6849
		<script language="JavaScript" type="text/javascript">
6850
		<!--
6851
		// POP-UP CAPTIONS...
6852
		function lib_bwcheck(){ //Browsercheck (needed)
6853
		    this.ver=navigator.appVersion
6854
		    this.agent=navigator.userAgent
6855
		    this.dom=document.getElementById?1:0
6856
		    this.opera5=this.agent.indexOf("Opera 5")>-1
6857
		    this.ie5=(this.ver.indexOf("MSIE 5")>-1 && this.dom && !this.opera5)?1:0;
6858
		    this.ie6=(this.ver.indexOf("MSIE 6")>-1 && this.dom && !this.opera5)?1:0;
6859
		    this.ie4=(document.all && !this.dom && !this.opera5)?1:0;
6860
		    this.ie=this.ie4||this.ie5||this.ie6
6861
		    this.mac=this.agent.indexOf("Mac")>-1
6862
		    this.ns6=(this.dom && parseInt(this.ver) >= 5) ?1:0;
6863
		    this.ns4=(document.layers && !this.dom)?1:0;
6864
		    this.bw=(this.ie6 || this.ie5 || this.ie4 || this.ns4 || this.ns6 || this.opera5)
6865
		    return this
6866
		}
6867
		var bw = new lib_bwcheck()
6868
		//Makes crossbrowser object.
6869
		function makeObj(obj){
6870
		    this.evnt=bw.dom? document.getElementById(obj):bw.ie4?document.all[obj]:bw.ns4?document.layers[obj]:0;
6871
		    if(!this.evnt) return false
6872
		    this.css=bw.dom||bw.ie4?this.evnt.style:bw.ns4?this.evnt:0;
6873
		    this.wref=bw.dom||bw.ie4?this.evnt:bw.ns4?this.css.document:0;
6874
		    this.writeIt=b_writeIt;
6875
		    return this
6876
		}
6877
		// A unit of measure that will be added when setting the position of a layer.
6878
		//var px = bw.ns4||window.opera?"":"px";
6879
		function b_writeIt(text){
6880
		    if (bw.ns4){this.wref.write(text);this.wref.close()}
6881
		    else this.wref.innerHTML = text
6882
		}
6883
		//Shows the messages
6884
		var oDesc;
6885
		function popup(divid){
6886
		    if(oDesc = new makeObj(divid)){
6887
			oDesc.css.visibility = "visible"
6888
		    }
6889
		}
6890
		function popout(){ // Hides message
6891
		    if(oDesc) oDesc.css.visibility = "hidden"
6892
		}
6893
		//-->
6894
		</script>
6895
		</head>
6896
		<body>
6897
		<div class=content>
6898
			<br><br>
6899
			<div class=title>'.$this->serviceName.'</div>
6900
			<div class=nav>
6901
				<p>View the <a href="'.$PHP_SELF.'?wsdl">WSDL</a> for the service.
6902
				Click on an operation name to view it&apos;s details.</p>
6903
				<ul>';
6904
				foreach($this->getOperations() as $op => $data){
6905
				    $b .= "<li><a href='#' onclick=\"popout();popup('$op')\">$op</a></li>";
6906
				    // create hidden div
6907
				    $b .= "<div id='$op' class='hidden'>
6908
				    <a href='#' onclick='popout()'><font color='#ffffff'>Close</font></a><br><br>";
6909
				    foreach($data as $donnie => $marie){ // loop through opdata
6910
						if($donnie == 'input' || $donnie == 'output'){ // show input/output data
6911
						    $b .= "<font color='white'>".ucfirst($donnie).':</font><br>';
6912
						    foreach($marie as $captain => $tenille){ // loop through data
6913
								if($captain == 'parts'){ // loop thru parts
6914
								    $b .= "&nbsp;&nbsp;$captain:<br>";
6915
					                //if(is_array($tenille)){
6916
								    	foreach($tenille as $joanie => $chachi){
6917
											$b .= "&nbsp;&nbsp;&nbsp;&nbsp;$joanie: $chachi<br>";
6918
								    	}
6919
					        		//}
6920
								} else {
6921
								    $b .= "&nbsp;&nbsp;$captain: $tenille<br>";
6922
								}
6923
						    }
6924
						} else {
6925
						    $b .= "<font color='white'>".ucfirst($donnie).":</font> $marie<br>";
6926
						}
6927
				    }
6928
					$b .= '</div>';
6929
				}
6930
				$b .= '
6931
				<ul>
6932
			</div>
6933
		</div></body></html>';
6934
		return $b;
6935
    }
6936
6937
	/**
6938
	* serialize the parsed wsdl
6939
	*
6940
	* @param mixed $debug whether to put debug=1 in endpoint URL
6941
	* @return string serialization of WSDL
6942
	* @access public
6943
	*/
6944
	function serialize($debug = 0)
6945
	{
6946
		$xml = '<?xml version="1.0" encoding="ISO-8859-1"?>';
6947
		$xml .= "\n<definitions";
6948
		foreach($this->namespaces as $k => $v) {
6949
			$xml .= " xmlns:$k=\"$v\"";
6950
		}
6951
		// 10.9.02 - add poulter fix for wsdl and tns declarations
6952
		if (isset($this->namespaces['wsdl'])) {
6953
			$xml .= " xmlns=\"" . $this->namespaces['wsdl'] . "\"";
6954
		}
6955
		if (isset($this->namespaces['tns'])) {
6956
			$xml .= " targetNamespace=\"" . $this->namespaces['tns'] . "\"";
6957
		}
6958
		$xml .= '>';
6959
		// imports
6960
		if (sizeof($this->import) > 0) {
6961
			foreach($this->import as $ns => $list) {
6962
				foreach ($list as $ii) {
6963
					if ($ii['location'] != '') {
6964
						$xml .= '<import location="' . $ii['location'] . '" namespace="' . $ns . '" />';
6965
					} else {
6966
						$xml .= '<import namespace="' . $ns . '" />';
6967
					}
6968
				}
6969
			}
6970
		}
6971
		// types
6972
		if (count($this->schemas)>=1) {
6973
			$xml .= "\n<types>\n";
6974
			foreach ($this->schemas as $ns => $list) {
6975
				foreach ($list as $xs) {
6976
					$xml .= $xs->serializeSchema();
6977
				}
6978
			}
6979
			$xml .= '</types>';
6980
		}
6981
		// messages
6982
		if (count($this->messages) >= 1) {
6983
			foreach($this->messages as $msgName => $msgParts) {
6984
				$xml .= "\n<message name=\"" . $msgName . '">';
6985
				if(is_array($msgParts)){
6986
					foreach($msgParts as $partName => $partType) {
6987
						// print 'serializing '.$partType.', sv: '.$this->XMLSchemaVersion.'<br>';
6988
						if (strpos($partType, ':')) {
6989
						    $typePrefix = $this->getPrefixFromNamespace($this->getPrefix($partType));
0 ignored issues
show
It seems like $this->getPrefix($partType) targeting nusoap_base::getPrefix() can also be of type false; however, nusoap_base::getPrefixFromNamespace() does only seem to accept string, did you maybe forget to handle an error condition?
Loading history...
6990
						} elseif (isset($this->typemap[$this->namespaces['xsd']][$partType])) {
6991
						    // print 'checking typemap: '.$this->XMLSchemaVersion.'<br>';
6992
						    $typePrefix = 'xsd';
6993
						} else {
6994
						    foreach($this->typemap as $ns => $types) {
6995
						        if (isset($types[$partType])) {
6996
						            $typePrefix = $this->getPrefixFromNamespace($ns);
6997
						        }
6998
						    }
6999
						    if (!isset($typePrefix)) {
7000
						        die("$partType has no namespace!");
7001
						    }
7002
						}
7003
						$ns = $this->getNamespaceFromPrefix($typePrefix);
7004
						$localPart = $this->getLocalPart($partType);
7005
						$typeDef = $this->getTypeDef($localPart, $ns);
7006
						if ($typeDef['typeClass'] == 'element') {
7007
							$elementortype = 'element';
7008
							if (substr($localPart, -1) == '^') {
7009
								$localPart = substr($localPart, 0, -1);
7010
							}
7011
						} else {
7012
							$elementortype = 'type';
7013
						}
7014
						$xml .= "\n" . '  <part name="' . $partName . '" ' . $elementortype . '="' . $typePrefix . ':' . $localPart . '" />';
7015
					}
7016
				}
7017
				$xml .= '</message>';
7018
			}
7019
		}
7020
		// bindings & porttypes
7021
		if (count($this->bindings) >= 1) {
7022
			$binding_xml = '';
7023
			$portType_xml = '';
7024
			foreach($this->bindings as $bindingName => $attrs) {
7025
				$binding_xml .= "\n<binding name=\"" . $bindingName . '" type="tns:' . $attrs['portType'] . '">';
7026
				$binding_xml .= "\n" . '  <soap:binding style="' . $attrs['style'] . '" transport="' . $attrs['transport'] . '"/>';
7027
				$portType_xml .= "\n<portType name=\"" . $attrs['portType'] . '">';
7028
				foreach($attrs['operations'] as $opName => $opParts) {
7029
					$binding_xml .= "\n" . '  <operation name="' . $opName . '">';
7030
					$binding_xml .= "\n" . '    <soap:operation soapAction="' . $opParts['soapAction'] . '" style="'. $opParts['style'] . '"/>';
7031
					if (isset($opParts['input']['encodingStyle']) && $opParts['input']['encodingStyle'] != '') {
7032
						$enc_style = ' encodingStyle="' . $opParts['input']['encodingStyle'] . '"';
7033
					} else {
7034
						$enc_style = '';
7035
					}
7036
					$binding_xml .= "\n" . '    <input><soap:body use="' . $opParts['input']['use'] . '" namespace="' . $opParts['input']['namespace'] . '"' . $enc_style . '/></input>';
7037
					if (isset($opParts['output']['encodingStyle']) && $opParts['output']['encodingStyle'] != '') {
7038
						$enc_style = ' encodingStyle="' . $opParts['output']['encodingStyle'] . '"';
7039
					} else {
7040
						$enc_style = '';
7041
					}
7042
					$binding_xml .= "\n" . '    <output><soap:body use="' . $opParts['output']['use'] . '" namespace="' . $opParts['output']['namespace'] . '"' . $enc_style . '/></output>';
7043
					$binding_xml .= "\n" . '  </operation>';
7044
					$portType_xml .= "\n" . '  <operation name="' . $opParts['name'] . '"';
7045
					if (isset($opParts['parameterOrder'])) {
7046
					    $portType_xml .= ' parameterOrder="' . $opParts['parameterOrder'] . '"';
7047
					}
7048
					$portType_xml .= '>';
7049
					if(isset($opParts['documentation']) && $opParts['documentation'] != '') {
7050
						$portType_xml .= "\n" . '    <documentation>' . htmlspecialchars($opParts['documentation']) . '</documentation>';
7051
					}
7052
					$portType_xml .= "\n" . '    <input message="tns:' . $opParts['input']['message'] . '"/>';
7053
					$portType_xml .= "\n" . '    <output message="tns:' . $opParts['output']['message'] . '"/>';
7054
					$portType_xml .= "\n" . '  </operation>';
7055
				}
7056
				$portType_xml .= "\n" . '</portType>';
7057
				$binding_xml .= "\n" . '</binding>';
7058
			}
7059
			$xml .= $portType_xml . $binding_xml;
7060
		}
7061
		// services
7062
		$xml .= "\n<service name=\"" . $this->serviceName . '">';
7063
		if (count($this->ports) >= 1) {
7064
			foreach($this->ports as $pName => $attrs) {
7065
				$xml .= "\n" . '  <port name="' . $pName . '" binding="tns:' . $attrs['binding'] . '">';
7066
				$xml .= "\n" . '    <soap:address location="' . $attrs['location'] . ($debug ? '?debug=1' : '') . '"/>';
7067
				$xml .= "\n" . '  </port>';
7068
			}
7069
		}
7070
		$xml .= "\n" . '</service>';
7071
		return $xml . "\n</definitions>";
7072
	}
7073
7074
	/**
7075
	 * determine whether a set of parameters are unwrapped
7076
	 * when they are expect to be wrapped, Microsoft-style.
7077
	 *
7078
	 * @param string $type the type (element name) of the wrapper
7079
	 * @param array $parameters the parameter values for the SOAP call
7080
	 * @return boolean whether they parameters are unwrapped (and should be wrapped)
7081
	 * @access private
7082
	 */
7083
	function parametersMatchWrapped($type, &$parameters) {
7084
		$this->debug("in parametersMatchWrapped type=$type, parameters=");
7085
		$this->appendDebug($this->varDump($parameters));
7086
7087
		// split type into namespace:unqualified-type
7088
		if (strpos($type, ':')) {
7089
			$uqType = substr($type, strrpos($type, ':') + 1);
7090
			$ns = substr($type, 0, strrpos($type, ':'));
7091
			$this->debug("in parametersMatchWrapped: got a prefixed type: $uqType, $ns");
7092
			if ($this->getNamespaceFromPrefix($ns)) {
7093
				$ns = $this->getNamespaceFromPrefix($ns);
7094
				$this->debug("in parametersMatchWrapped: expanded prefixed type: $uqType, $ns");
7095
			}
7096
		} else {
7097
			// TODO: should the type be compared to types in XSD, and the namespace
7098
			// set to XSD if the type matches?
7099
			$this->debug("in parametersMatchWrapped: No namespace for type $type");
7100
			$ns = '';
7101
			$uqType = $type;
7102
		}
7103
7104
		// get the type information
7105
		if (!$typeDef = $this->getTypeDef($uqType, $ns)) {
7106
			$this->debug("in parametersMatchWrapped: $type ($uqType) is not a supported type.");
7107
			return false;
7108
		}
7109
		$this->debug("in parametersMatchWrapped: found typeDef=");
7110
		$this->appendDebug($this->varDump($typeDef));
7111
		if (substr($uqType, -1) == '^') {
7112
			$uqType = substr($uqType, 0, -1);
7113
		}
7114
		$phpType = $typeDef['phpType'];
7115
		$arrayType = (isset($typeDef['arrayType']) ? $typeDef['arrayType'] : '');
7116
		$this->debug("in parametersMatchWrapped: uqType: $uqType, ns: $ns, phptype: $phpType, arrayType: $arrayType");
7117
7118
		// we expect a complexType or element of complexType
7119
		if ($phpType != 'struct') {
7120
			$this->debug("in parametersMatchWrapped: not a struct");
7121
			return false;
7122
		}
7123
7124
		// see whether the parameter names match the elements
7125
		if (isset($typeDef['elements']) && is_array($typeDef['elements'])) {
7126
			$elements = 0;
7127
			$matches = 0;
7128
			foreach ($typeDef['elements'] as $name => $attrs) {
7129
				if (isset($parameters[$name])) {
7130
					$this->debug("in parametersMatchWrapped: have parameter named $name");
7131
					$matches++;
7132
				} else {
7133
					$this->debug("in parametersMatchWrapped: do not have parameter named $name");
7134
				}
7135
				$elements++;
7136
			}
7137
7138
			$this->debug("in parametersMatchWrapped: $matches parameter names match $elements wrapped parameter names");
7139
			if ($matches == 0) {
7140
				return false;
7141
			}
7142
			return true;
7143
		}
7144
7145
		// since there are no elements for the type, if the user passed no
7146
		// parameters, the parameters match wrapped.
7147
		$this->debug("in parametersMatchWrapped: no elements type $ns:$uqType");
7148
		return count($parameters) == 0;
7149
	}
7150
7151
	/**
7152
	 * serialize PHP values according to a WSDL message definition
7153
	 * contrary to the method name, this is not limited to RPC
7154
	 *
7155
	 * TODO
7156
	 * - multi-ref serialization
7157
	 * - validate PHP values against type definitions, return errors if invalid
7158
	 *
7159
	 * @param string $operation operation name
7160
	 * @param string $direction (input|output)
7161
	 * @param mixed $parameters parameter value(s)
7162
	 * @param string $bindingType (soap|soap12)
7163
	 * @return mixed parameters serialized as XML or false on error (e.g. operation not found)
7164
	 * @access public
7165
	 */
7166
	function serializeRPCParameters($operation, $direction, $parameters, $bindingType = 'soap') {
7167
		$this->debug("in serializeRPCParameters: operation=$operation, direction=$direction, XMLSchemaVersion=$this->XMLSchemaVersion, bindingType=$bindingType");
7168
		$this->appendDebug('parameters=' . $this->varDump($parameters));
7169
7170
		if ($direction != 'input' && $direction != 'output') {
7171
			$this->debug('The value of the \$direction argument needs to be either "input" or "output"');
7172
			$this->setError('The value of the \$direction argument needs to be either "input" or "output"');
7173
			return false;
7174
		}
7175
		if (!$opData = $this->getOperationData($operation, $bindingType)) {
7176
			$this->debug('Unable to retrieve WSDL data for operation: ' . $operation . ' bindingType: ' . $bindingType);
7177
			$this->setError('Unable to retrieve WSDL data for operation: ' . $operation . ' bindingType: ' . $bindingType);
7178
			return false;
7179
		}
7180
		$this->debug('in serializeRPCParameters: opData:');
7181
		$this->appendDebug($this->varDump($opData));
7182
7183
		// Get encoding style for output and set to current
7184
		$encodingStyle = 'http://schemas.xmlsoap.org/soap/encoding/';
7185
		if(($direction == 'input') && isset($opData['output']['encodingStyle']) && ($opData['output']['encodingStyle'] != $encodingStyle)) {
7186
			$encodingStyle = $opData['output']['encodingStyle'];
7187
			$enc_style = $encodingStyle;
7188
		}
7189
7190
		// set input params
7191
		$xml = '';
7192
		if (isset($opData[$direction]['parts']) && sizeof($opData[$direction]['parts']) > 0) {
7193
			$parts = &$opData[$direction]['parts'];
7194
			$part_count = sizeof($parts);
7195
			$style = $opData['style'];
7196
			$use = $opData[$direction]['use'];
7197
			$this->debug("have $part_count part(s) to serialize using $style/$use");
7198
			if (is_array($parameters)) {
7199
				$parametersArrayType = $this->isArraySimpleOrStruct($parameters);
7200
				$parameter_count = count($parameters);
7201
				$this->debug("have $parameter_count parameter(s) provided as $parametersArrayType to serialize");
7202
				// check for Microsoft-style wrapped parameters
7203
				if ($style == 'document' && $use == 'literal' && $part_count == 1 && isset($parts['parameters'])) {
7204
					$this->debug('check whether the caller has wrapped the parameters');
7205
					if ($direction == 'output' && $parametersArrayType == 'arraySimple' && $parameter_count == 1) {
7206
						// TODO: consider checking here for double-wrapping, when
7207
						// service function wraps, then NuSOAP wraps again
7208
						$this->debug("change simple array to associative with 'parameters' element");
7209
						$parameters['parameters'] = $parameters[0];
7210
						unset($parameters[0]);
7211
					}
7212
					if (($parametersArrayType == 'arrayStruct' || $parameter_count == 0) && !isset($parameters['parameters'])) {
7213
						$this->debug('check whether caller\'s parameters match the wrapped ones');
7214
						if ($this->parametersMatchWrapped($parts['parameters'], $parameters)) {
7215
							$this->debug('wrap the parameters for the caller');
7216
							$parameters = array('parameters' => $parameters);
7217
							$parameter_count = 1;
7218
						}
7219
					}
7220
				}
7221
				foreach ($parts as $name => $type) {
7222
					$this->debug("serializing part $name of type $type");
7223
					// Track encoding style
7224
					if (isset($opData[$direction]['encodingStyle']) && $encodingStyle != $opData[$direction]['encodingStyle']) {
7225
						$encodingStyle = $opData[$direction]['encodingStyle'];
7226
						$enc_style = $encodingStyle;
7227
					} else {
7228
						$enc_style = false;
7229
					}
7230
					// NOTE: add error handling here
7231
					// if serializeType returns false, then catch global error and fault
7232
					if ($parametersArrayType == 'arraySimple') {
7233
						$p = array_shift($parameters);
7234
						$this->debug('calling serializeType w/indexed param');
7235
						$xml .= $this->serializeType($name, $type, $p, $use, $enc_style);
7236
					} elseif (isset($parameters[$name])) {
7237
						$this->debug('calling serializeType w/named param');
7238
						$xml .= $this->serializeType($name, $type, $parameters[$name], $use, $enc_style);
7239
					} else {
7240
						// TODO: only send nillable
7241
						$this->debug('calling serializeType w/null param');
7242
						$xml .= $this->serializeType($name, $type, null, $use, $enc_style);
7243
					}
7244
				}
7245
			} else {
7246
				$this->debug('no parameters passed.');
7247
			}
7248
		}
7249
		$this->debug("serializeRPCParameters returning: $xml");
7250
		return $xml;
7251
	}
7252
7253
	/**
7254
	 * serialize a PHP value according to a WSDL message definition
7255
	 *
7256
	 * TODO
7257
	 * - multi-ref serialization
7258
	 * - validate PHP values against type definitions, return errors if invalid
7259
	 *
7260
	 * @param string $operation operation name
7261
	 * @param string $direction (input|output)
7262
	 * @param mixed $parameters parameter value(s)
7263
	 * @return mixed parameters serialized as XML or false on error (e.g. operation not found)
7264
	 * @access public
7265
	 * @deprecated
7266
	 */
7267
	function serializeParameters($operation, $direction, $parameters)
7268
	{
7269
		$this->debug("in serializeParameters: operation=$operation, direction=$direction, XMLSchemaVersion=$this->XMLSchemaVersion");
7270
		$this->appendDebug('parameters=' . $this->varDump($parameters));
7271
7272
		if ($direction != 'input' && $direction != 'output') {
7273
			$this->debug('The value of the \$direction argument needs to be either "input" or "output"');
7274
			$this->setError('The value of the \$direction argument needs to be either "input" or "output"');
7275
			return false;
7276
		}
7277
		if (!$opData = $this->getOperationData($operation)) {
7278
			$this->debug('Unable to retrieve WSDL data for operation: ' . $operation);
7279
			$this->setError('Unable to retrieve WSDL data for operation: ' . $operation);
7280
			return false;
7281
		}
7282
		$this->debug('opData:');
7283
		$this->appendDebug($this->varDump($opData));
7284
7285
		// Get encoding style for output and set to current
7286
		$encodingStyle = 'http://schemas.xmlsoap.org/soap/encoding/';
7287
		if(($direction == 'input') && isset($opData['output']['encodingStyle']) && ($opData['output']['encodingStyle'] != $encodingStyle)) {
7288
			$encodingStyle = $opData['output']['encodingStyle'];
7289
			$enc_style = $encodingStyle;
7290
		}
7291
7292
		// set input params
7293
		$xml = '';
7294
		if (isset($opData[$direction]['parts']) && sizeof($opData[$direction]['parts']) > 0) {
7295
7296
			$use = $opData[$direction]['use'];
7297
			$this->debug("use=$use");
7298
			$this->debug('got ' . count($opData[$direction]['parts']) . ' part(s)');
7299
			if (is_array($parameters)) {
7300
				$parametersArrayType = $this->isArraySimpleOrStruct($parameters);
7301
				$this->debug('have ' . $parametersArrayType . ' parameters');
7302
				foreach($opData[$direction]['parts'] as $name => $type) {
7303
					$this->debug('serializing part "'.$name.'" of type "'.$type.'"');
7304
					// Track encoding style
7305
					if(isset($opData[$direction]['encodingStyle']) && $encodingStyle != $opData[$direction]['encodingStyle']) {
7306
						$encodingStyle = $opData[$direction]['encodingStyle'];
7307
						$enc_style = $encodingStyle;
7308
					} else {
7309
						$enc_style = false;
7310
					}
7311
					// NOTE: add error handling here
7312
					// if serializeType returns false, then catch global error and fault
7313
					if ($parametersArrayType == 'arraySimple') {
7314
						$p = array_shift($parameters);
7315
						$this->debug('calling serializeType w/indexed param');
7316
						$xml .= $this->serializeType($name, $type, $p, $use, $enc_style);
7317
					} elseif (isset($parameters[$name])) {
7318
						$this->debug('calling serializeType w/named param');
7319
						$xml .= $this->serializeType($name, $type, $parameters[$name], $use, $enc_style);
7320
					} else {
7321
						// TODO: only send nillable
7322
						$this->debug('calling serializeType w/null param');
7323
						$xml .= $this->serializeType($name, $type, null, $use, $enc_style);
7324
					}
7325
				}
7326
			} else {
7327
				$this->debug('no parameters passed.');
7328
			}
7329
		}
7330
		$this->debug("serializeParameters returning: $xml");
7331
		return $xml;
7332
	}
7333
7334
	/**
7335
	 * serializes a PHP value according a given type definition
7336
	 *
7337
	 * @param string $name name of value (part or element)
7338
	 * @param string $type XML schema type of value (type or element)
7339
	 * @param mixed $value a native PHP value (parameter value)
7340
	 * @param string $use use for part (encoded|literal)
7341
	 * @param string $encodingStyle SOAP encoding style for the value (if different than the enclosing style)
7342
	 * @param boolean $unqualified a kludge for what should be XML namespace form handling
7343
	 * @return string value serialized as an XML string
7344
	 * @access private
7345
	 */
7346
	function serializeType($name, $type, $value, $use='encoded', $encodingStyle=false, $unqualified=false)
7347
	{
7348
		$this->debug("in serializeType: name=$name, type=$type, use=$use, encodingStyle=$encodingStyle, unqualified=" . ($unqualified ? "unqualified" : "qualified"));
7349
		$this->appendDebug("value=" . $this->varDump($value));
7350
		if($use == 'encoded' && $encodingStyle) {
7351
			$encodingStyle = ' SOAP-ENV:encodingStyle="' . $encodingStyle . '"';
7352
		}
7353
7354
		// if a soapval has been supplied, let its type override the WSDL
7355
    	if (is_object($value) && get_class($value) == 'soapval') {
7356
    		if ($value->type_ns) {
7357
    			$type = $value->type_ns . ':' . $value->type;
7358
		    	$forceType = true;
7359
		    	$this->debug("in serializeType: soapval overrides type to $type");
7360
    		} elseif ($value->type) {
7361
	    		$type = $value->type;
7362
		    	$forceType = true;
7363
		    	$this->debug("in serializeType: soapval overrides type to $type");
7364
	    	} else {
7365
	    		$forceType = false;
7366
		    	$this->debug("in serializeType: soapval does not override type");
7367
	    	}
7368
	    	$attrs = $value->attributes;
7369
	    	$value = $value->value;
7370
	    	$this->debug("in serializeType: soapval overrides value to $value");
7371
	    	if ($attrs) {
7372
	    		if (!is_array($value)) {
7373
	    			$value['!'] = $value;
7374
	    		}
7375
	    		foreach ($attrs as $n => $v) {
7376
	    			$value['!' . $n] = $v;
7377
	    		}
7378
		    	$this->debug("in serializeType: soapval provides attributes");
7379
		    }
7380
        } else {
7381
        	$forceType = false;
7382
        }
7383
7384
		$xml = '';
7385
		if (strpos($type, ':')) {
7386
			$uqType = substr($type, strrpos($type, ':') + 1);
7387
			$ns = substr($type, 0, strrpos($type, ':'));
7388
			$this->debug("in serializeType: got a prefixed type: $uqType, $ns");
7389
			if ($this->getNamespaceFromPrefix($ns)) {
7390
				$ns = $this->getNamespaceFromPrefix($ns);
7391
				$this->debug("in serializeType: expanded prefixed type: $uqType, $ns");
7392
			}
7393
7394
			if($ns == $this->XMLSchemaVersion || $ns == 'http://schemas.xmlsoap.org/soap/encoding/'){
7395
				$this->debug('in serializeType: type namespace indicates XML Schema or SOAP Encoding type');
7396
				if ($unqualified && $use == 'literal') {
7397
					$elementNS = " xmlns=\"\"";
7398
				} else {
7399
					$elementNS = '';
7400
				}
7401
				if (is_null($value)) {
7402
					if ($use == 'literal') {
7403
						// TODO: depends on minOccurs
7404
						$xml = "<$name$elementNS/>";
7405
					} else {
7406
						// TODO: depends on nillable, which should be checked before calling this method
7407
						$xml = "<$name$elementNS xsi:nil=\"true\" xsi:type=\"" . $this->getPrefixFromNamespace($ns) . ":$uqType\"/>";
7408
					}
7409
					$this->debug("in serializeType: returning: $xml");
7410
					return $xml;
7411
				}
7412
				if ($uqType == 'Array') {
7413
					// JBoss/Axis does this sometimes
7414
					return $this->serialize_val($value, $name, false, false, false, false, $use);
7415
				}
7416
		    	if ($uqType == 'boolean') {
7417
		    		if ((is_string($value) && $value == 'false') || (! $value)) {
7418
						$value = 'false';
7419
					} else {
7420
						$value = 'true';
7421
					}
7422
				}
7423
				if ($uqType == 'string' && gettype($value) == 'string') {
7424
					$value = $this->expandEntities($value);
7425
				}
7426
				if (($uqType == 'long' || $uqType == 'unsignedLong') && gettype($value) == 'double') {
7427
					$value = sprintf("%.0lf", $value);
7428
				}
7429
				// it's a scalar
7430
				// TODO: what about null/nil values?
7431
				// check type isn't a custom type extending xmlschema namespace
7432
				if (!$this->getTypeDef($uqType, $ns)) {
7433
					if ($use == 'literal') {
7434
						if ($forceType) {
7435
							$xml = "<$name$elementNS xsi:type=\"" . $this->getPrefixFromNamespace($ns) . ":$uqType\">$value</$name>";
7436
						} else {
7437
							$xml = "<$name$elementNS>$value</$name>";
7438
						}
7439
					} else {
7440
						$xml = "<$name$elementNS xsi:type=\"" . $this->getPrefixFromNamespace($ns) . ":$uqType\"$encodingStyle>$value</$name>";
7441
					}
7442
					$this->debug("in serializeType: returning: $xml");
7443
					return $xml;
7444
				}
7445
				$this->debug('custom type extends XML Schema or SOAP Encoding namespace (yuck)');
7446
			} else if ($ns == 'http://xml.apache.org/xml-soap') {
7447
				$this->debug('in serializeType: appears to be Apache SOAP type');
7448
				if ($uqType == 'Map') {
7449
					$tt_prefix = $this->getPrefixFromNamespace('http://xml.apache.org/xml-soap');
7450
					if (! $tt_prefix) {
7451
						$this->debug('in serializeType: Add namespace for Apache SOAP type');
7452
						$tt_prefix = 'ns' . rand(1000, 9999);
7453
						$this->namespaces[$tt_prefix] = 'http://xml.apache.org/xml-soap';
7454
						// force this to be added to usedNamespaces
7455
						$tt_prefix = $this->getPrefixFromNamespace('http://xml.apache.org/xml-soap');
7456
					}
7457
					$contents = '';
7458
					foreach($value as $k => $v) {
7459
						$this->debug("serializing map element: key $k, value $v");
7460
						$contents .= '<item>';
7461
						$contents .= $this->serialize_val($k,'key',false,false,false,false,$use);
7462
						$contents .= $this->serialize_val($v,'value',false,false,false,false,$use);
7463
						$contents .= '</item>';
7464
					}
7465
					if ($use == 'literal') {
7466
						if ($forceType) {
7467
							$xml = "<$name xsi:type=\"" . $tt_prefix . ":$uqType\">$contents</$name>";
7468
						} else {
7469
							$xml = "<$name>$contents</$name>";
7470
						}
7471
					} else {
7472
						$xml = "<$name xsi:type=\"" . $tt_prefix . ":$uqType\"$encodingStyle>$contents</$name>";
7473
					}
7474
					$this->debug("in serializeType: returning: $xml");
7475
					return $xml;
7476
				}
7477
				$this->debug('in serializeType: Apache SOAP type, but only support Map');
7478
			}
7479
		} else {
7480
			// TODO: should the type be compared to types in XSD, and the namespace
7481
			// set to XSD if the type matches?
7482
			$this->debug("in serializeType: No namespace for type $type");
7483
			$ns = '';
7484
			$uqType = $type;
7485
		}
7486
		if(!$typeDef = $this->getTypeDef($uqType, $ns)){
7487
			$this->setError("$type ($uqType) is not a supported type.");
7488
			$this->debug("in serializeType: $type ($uqType) is not a supported type.");
7489
			return false;
7490
		} else {
7491
			$this->debug("in serializeType: found typeDef");
7492
			$this->appendDebug('typeDef=' . $this->varDump($typeDef));
7493
			if (substr($uqType, -1) == '^') {
7494
				$uqType = substr($uqType, 0, -1);
7495
			}
7496
		}
7497
		if (!isset($typeDef['phpType'])) {
7498
			$this->setError("$type ($uqType) has no phpType.");
7499
			$this->debug("in serializeType: $type ($uqType) has no phpType.");
7500
			return false;
7501
		}
7502
		$phpType = $typeDef['phpType'];
7503
		$this->debug("in serializeType: uqType: $uqType, ns: $ns, phptype: $phpType, arrayType: " . (isset($typeDef['arrayType']) ? $typeDef['arrayType'] : '') );
7504
		// if php type == struct, map value to the <all> element names
7505
		if ($phpType == 'struct') {
7506
			if (isset($typeDef['typeClass']) && $typeDef['typeClass'] == 'element') {
7507
				$elementName = $uqType;
7508
				if (isset($typeDef['form']) && ($typeDef['form'] == 'qualified')) {
7509
					$elementNS = " xmlns=\"$ns\"";
7510
				} else {
7511
					$elementNS = " xmlns=\"\"";
7512
				}
7513
			} else {
7514
				$elementName = $name;
7515
				if ($unqualified) {
7516
					$elementNS = " xmlns=\"\"";
7517
				} else {
7518
					$elementNS = '';
7519
				}
7520
			}
7521
			if (is_null($value)) {
7522
				if ($use == 'literal') {
7523
					// TODO: depends on minOccurs and nillable
7524
					$xml = "<$elementName$elementNS/>";
7525
				} else {
7526
					$xml = "<$elementName$elementNS xsi:nil=\"true\" xsi:type=\"" . $this->getPrefixFromNamespace($ns) . ":$uqType\"/>";
7527
				}
7528
				$this->debug("in serializeType: returning: $xml");
7529
				return $xml;
7530
			}
7531
			if (is_object($value)) {
7532
				$value = get_object_vars($value);
7533
			}
7534
			if (is_array($value)) {
7535
				$elementAttrs = $this->serializeComplexTypeAttributes($typeDef, $value, $ns, $uqType);
7536
				if ($use == 'literal') {
7537
					if ($forceType) {
7538
						$xml = "<$elementName$elementNS$elementAttrs xsi:type=\"" . $this->getPrefixFromNamespace($ns) . ":$uqType\">";
7539
					} else {
7540
						$xml = "<$elementName$elementNS$elementAttrs>";
7541
					}
7542
				} else {
7543
					$xml = "<$elementName$elementNS$elementAttrs xsi:type=\"" . $this->getPrefixFromNamespace($ns) . ":$uqType\"$encodingStyle>";
7544
				}
7545
7546
				if (isset($typeDef['simpleContent']) && $typeDef['simpleContent'] == 'true') {
7547
					if (isset($value['!'])) {
7548
						$xml .= $value['!'];
7549
						$this->debug("in serializeType: serialized simpleContent for type $type");
7550
					} else {
7551
						$this->debug("in serializeType: no simpleContent to serialize for type $type");
7552
					}
7553
				} else {
7554
					// complexContent
7555
					$xml .= $this->serializeComplexTypeElements($typeDef, $value, $ns, $uqType, $use, $encodingStyle);
7556
				}
7557
				$xml .= "</$elementName>";
7558
			} else {
7559
				$this->debug("in serializeType: phpType is struct, but value is not an array");
7560
				$this->setError("phpType is struct, but value is not an array: see debug output for details");
7561
				$xml = '';
7562
			}
7563
		} elseif ($phpType == 'array') {
7564
			if (isset($typeDef['form']) && ($typeDef['form'] == 'qualified')) {
7565
				$elementNS = " xmlns=\"$ns\"";
7566
			} else {
7567
				if ($unqualified) {
7568
					$elementNS = " xmlns=\"\"";
7569
				} else {
7570
					$elementNS = '';
7571
				}
7572
			}
7573
			if (is_null($value)) {
7574
				if ($use == 'literal') {
7575
					// TODO: depends on minOccurs
7576
					$xml = "<$name$elementNS/>";
7577
				} else {
7578
					$xml = "<$name$elementNS xsi:nil=\"true\" xsi:type=\"" .
7579
						$this->getPrefixFromNamespace('http://schemas.xmlsoap.org/soap/encoding/') .
7580
						":Array\" " .
7581
						$this->getPrefixFromNamespace('http://schemas.xmlsoap.org/soap/encoding/') .
7582
						':arrayType="' .
7583
						$this->getPrefixFromNamespace($this->getPrefix($typeDef['arrayType'])) .
0 ignored issues
show
It seems like $this->getPrefix($typeDef['arrayType']) targeting nusoap_base::getPrefix() can also be of type false; however, nusoap_base::getPrefixFromNamespace() does only seem to accept string, did you maybe forget to handle an error condition?
Loading history...
7584
						':' .
7585
						$this->getLocalPart($typeDef['arrayType'])."[0]\"/>";
7586
				}
7587
				$this->debug("in serializeType: returning: $xml");
7588
				return $xml;
7589
			}
7590
			if (isset($typeDef['multidimensional'])) {
7591
				$nv = array();
7592
				foreach($value as $v) {
0 ignored issues
show
The expression $value of type object|integer|double|string|array|boolean is not guaranteed to be traversable. How about adding an additional type check?

There are different options of fixing this problem.

  1. If you want to be on the safe side, you can add an additional type-check:

    $collection = json_decode($data, true);
    if ( ! is_array($collection)) {
        throw new \RuntimeException('$collection must be an array.');
    }
    
    foreach ($collection as $item) { /** ... */ }
    
  2. If you are sure that the expression is traversable, you might want to add a doc comment cast to improve IDE auto-completion and static analysis:

    /** @var array $collection */
    $collection = json_decode($data, true);
    
    foreach ($collection as $item) { /** .. */ }
    
  3. Mark the issue as a false-positive: Just hover the remove button, in the top-right corner of this issue for more options.

Loading history...
7593
					$cols = ',' . sizeof($v);
7594
					$nv = array_merge($nv, $v);
7595
				}
7596
				$value = $nv;
7597
			} else {
7598
				$cols = '';
7599
			}
7600
			if (is_array($value) && sizeof($value) >= 1) {
7601
				$rows = sizeof($value);
7602
				$contents = '';
7603
				foreach($value as $k => $v) {
7604
					$this->debug("serializing array element: $k, $v of type: $typeDef[arrayType]");
7605
					//if (strpos($typeDef['arrayType'], ':') ) {
7606
					if (!in_array($typeDef['arrayType'],$this->typemap['http://www.w3.org/2001/XMLSchema'])) {
7607
					    $contents .= $this->serializeType('item', $typeDef['arrayType'], $v, $use);
7608
					} else {
7609
					    $contents .= $this->serialize_val($v, 'item', $typeDef['arrayType'], null, $this->XMLSchemaVersion, false, $use);
7610
					}
7611
				}
7612
			} else {
7613
				$rows = 0;
7614
				$contents = null;
7615
			}
7616
			// TODO: for now, an empty value will be serialized as a zero element
7617
			// array.  Revisit this when coding the handling of null/nil values.
7618
			if ($use == 'literal') {
7619
				$xml = "<$name$elementNS>"
7620
					.$contents
7621
					."</$name>";
7622
			} else {
7623
				$xml = "<$name$elementNS xsi:type=\"".$this->getPrefixFromNamespace('http://schemas.xmlsoap.org/soap/encoding/').':Array" '.
7624
					$this->getPrefixFromNamespace('http://schemas.xmlsoap.org/soap/encoding/')
7625
					.':arrayType="'
7626
					.$this->getPrefixFromNamespace($this->getPrefix($typeDef['arrayType']))
0 ignored issues
show
It seems like $this->getPrefix($typeDef['arrayType']) targeting nusoap_base::getPrefix() can also be of type false; however, nusoap_base::getPrefixFromNamespace() does only seem to accept string, did you maybe forget to handle an error condition?
Loading history...
7627
					.":".$this->getLocalPart($typeDef['arrayType'])."[$rows$cols]\">"
7628
					.$contents
7629
					."</$name>";
7630
			}
7631
		} elseif ($phpType == 'scalar') {
7632
			if (isset($typeDef['form']) && ($typeDef['form'] == 'qualified')) {
7633
				$elementNS = " xmlns=\"$ns\"";
7634
			} else {
7635
				if ($unqualified) {
7636
					$elementNS = " xmlns=\"\"";
7637
				} else {
7638
					$elementNS = '';
7639
				}
7640
			}
7641
			if ($use == 'literal') {
7642
				if ($forceType) {
7643
					$xml = "<$name$elementNS xsi:type=\"" . $this->getPrefixFromNamespace($ns) . ":$uqType\">$value</$name>";
7644
				} else {
7645
					$xml = "<$name$elementNS>$value</$name>";
7646
				}
7647
			} else {
7648
				$xml = "<$name$elementNS xsi:type=\"" . $this->getPrefixFromNamespace($ns) . ":$uqType\"$encodingStyle>$value</$name>";
7649
			}
7650
		}
7651
		$this->debug("in serializeType: returning: $xml");
7652
		return $xml;
7653
	}
7654
7655
	/**
7656
	 * serializes the attributes for a complexType
7657
	 *
7658
	 * @param array $typeDef our internal representation of an XML schema type (or element)
7659
	 * @param mixed $value a native PHP value (parameter value)
7660
	 * @param string $ns the namespace of the type
7661
	 * @param string $uqType the local part of the type
7662
	 * @return string value serialized as an XML string
7663
	 * @access private
7664
	 */
7665
	function serializeComplexTypeAttributes($typeDef, $value, $ns, $uqType) {
7666
		$this->debug("serializeComplexTypeAttributes for XML Schema type $ns:$uqType");
7667
		$xml = '';
7668
		if (isset($typeDef['extensionBase'])) {
7669
			$nsx = $this->getPrefix($typeDef['extensionBase']);
7670
			$uqTypex = $this->getLocalPart($typeDef['extensionBase']);
7671
			if ($this->getNamespaceFromPrefix($nsx)) {
0 ignored issues
show
It seems like $nsx defined by $this->getPrefix($typeDef['extensionBase']) on line 7669 can also be of type false; however, nusoap_base::getNamespaceFromPrefix() does only seem to accept string, did you maybe forget to handle an error condition?

This check looks for type mismatches where the missing type is false. This is usually indicative of an error condtion.

Consider the follow example

<?php

function getDate($date)
{
    if ($date !== null) {
        return new DateTime($date);
    }

    return false;
}

This function either returns a new DateTime object or false, if there was an error. This is a typical pattern in PHP programming to show that an error has occurred without raising an exception. The calling code should check for this returned false before passing on the value to another function or method that may not be able to handle a false.

Loading history...
7672
				$nsx = $this->getNamespaceFromPrefix($nsx);
0 ignored issues
show
It seems like $nsx defined by $this->getNamespaceFromPrefix($nsx) on line 7672 can also be of type false; however, nusoap_base::getNamespaceFromPrefix() does only seem to accept string, did you maybe forget to handle an error condition?

This check looks for type mismatches where the missing type is false. This is usually indicative of an error condtion.

Consider the follow example

<?php

function getDate($date)
{
    if ($date !== null) {
        return new DateTime($date);
    }

    return false;
}

This function either returns a new DateTime object or false, if there was an error. This is a typical pattern in PHP programming to show that an error has occurred without raising an exception. The calling code should check for this returned false before passing on the value to another function or method that may not be able to handle a false.

Loading history...
7673
			}
7674
			if ($typeDefx = $this->getTypeDef($uqTypex, $nsx)) {
7675
				$this->debug("serialize attributes for extension base $nsx:$uqTypex");
7676
				$xml .= $this->serializeComplexTypeAttributes($typeDefx, $value, $nsx, $uqTypex);
7677
			} else {
7678
				$this->debug("extension base $nsx:$uqTypex is not a supported type");
7679
			}
7680
		}
7681
		if (isset($typeDef['attrs']) && is_array($typeDef['attrs'])) {
7682
			$this->debug("serialize attributes for XML Schema type $ns:$uqType");
7683
			if (is_array($value)) {
7684
				$xvalue = $value;
7685
			} elseif (is_object($value)) {
7686
				$xvalue = get_object_vars($value);
7687
			} else {
7688
				$this->debug("value is neither an array nor an object for XML Schema type $ns:$uqType");
7689
				$xvalue = array();
7690
			}
7691
			foreach ($typeDef['attrs'] as $aName => $attrs) {
7692
				if (isset($xvalue['!' . $aName])) {
7693
					$xname = '!' . $aName;
7694
					$this->debug("value provided for attribute $aName with key $xname");
7695
				} elseif (isset($xvalue[$aName])) {
7696
					$xname = $aName;
7697
					$this->debug("value provided for attribute $aName with key $xname");
7698
				} elseif (isset($attrs['default'])) {
7699
					$xname = '!' . $aName;
7700
					$xvalue[$xname] = $attrs['default'];
7701
					$this->debug('use default value of ' . $xvalue[$aName] . ' for attribute ' . $aName);
7702
				} else {
7703
					$xname = '';
7704
					$this->debug("no value provided for attribute $aName");
7705
				}
7706
				if ($xname) {
7707
					$xml .=  " $aName=\"" . $this->expandEntities($xvalue[$xname]) . "\"";
7708
				}
7709
			}
7710
		} else {
7711
			$this->debug("no attributes to serialize for XML Schema type $ns:$uqType");
7712
		}
7713
		return $xml;
7714
	}
7715
7716
	/**
7717
	 * serializes the elements for a complexType
7718
	 *
7719
	 * @param array $typeDef our internal representation of an XML schema type (or element)
7720
	 * @param mixed $value a native PHP value (parameter value)
7721
	 * @param string $ns the namespace of the type
7722
	 * @param string $uqType the local part of the type
7723
	 * @param string $use use for part (encoded|literal)
7724
	 * @param string $encodingStyle SOAP encoding style for the value (if different than the enclosing style)
7725
	 * @return string value serialized as an XML string
7726
	 * @access private
7727
	 */
7728
	function serializeComplexTypeElements($typeDef, $value, $ns, $uqType, $use='encoded', $encodingStyle=false) {
7729
		$this->debug("in serializeComplexTypeElements for XML Schema type $ns:$uqType");
7730
		$xml = '';
7731
		if (isset($typeDef['extensionBase'])) {
7732
			$nsx = $this->getPrefix($typeDef['extensionBase']);
7733
			$uqTypex = $this->getLocalPart($typeDef['extensionBase']);
7734
			if ($this->getNamespaceFromPrefix($nsx)) {
0 ignored issues
show
It seems like $nsx defined by $this->getPrefix($typeDef['extensionBase']) on line 7732 can also be of type false; however, nusoap_base::getNamespaceFromPrefix() does only seem to accept string, did you maybe forget to handle an error condition?

This check looks for type mismatches where the missing type is false. This is usually indicative of an error condtion.

Consider the follow example

<?php

function getDate($date)
{
    if ($date !== null) {
        return new DateTime($date);
    }

    return false;
}

This function either returns a new DateTime object or false, if there was an error. This is a typical pattern in PHP programming to show that an error has occurred without raising an exception. The calling code should check for this returned false before passing on the value to another function or method that may not be able to handle a false.

Loading history...
7735
				$nsx = $this->getNamespaceFromPrefix($nsx);
0 ignored issues
show
It seems like $nsx defined by $this->getNamespaceFromPrefix($nsx) on line 7735 can also be of type false; however, nusoap_base::getNamespaceFromPrefix() does only seem to accept string, did you maybe forget to handle an error condition?

This check looks for type mismatches where the missing type is false. This is usually indicative of an error condtion.

Consider the follow example

<?php

function getDate($date)
{
    if ($date !== null) {
        return new DateTime($date);
    }

    return false;
}

This function either returns a new DateTime object or false, if there was an error. This is a typical pattern in PHP programming to show that an error has occurred without raising an exception. The calling code should check for this returned false before passing on the value to another function or method that may not be able to handle a false.

Loading history...
7736
			}
7737
			if ($typeDefx = $this->getTypeDef($uqTypex, $nsx)) {
7738
				$this->debug("serialize elements for extension base $nsx:$uqTypex");
7739
				$xml .= $this->serializeComplexTypeElements($typeDefx, $value, $nsx, $uqTypex, $use, $encodingStyle);
7740
			} else {
7741
				$this->debug("extension base $nsx:$uqTypex is not a supported type");
7742
			}
7743
		}
7744
		if (isset($typeDef['elements']) && is_array($typeDef['elements'])) {
7745
			$this->debug("in serializeComplexTypeElements, serialize elements for XML Schema type $ns:$uqType");
7746
			if (is_array($value)) {
7747
				$xvalue = $value;
7748
			} elseif (is_object($value)) {
7749
				$xvalue = get_object_vars($value);
7750
			} else {
7751
				$this->debug("value is neither an array nor an object for XML Schema type $ns:$uqType");
7752
				$xvalue = array();
7753
			}
7754
			// toggle whether all elements are present - ideally should validate against schema
7755
			if (count($typeDef['elements']) != count($xvalue)){
7756
				$optionals = true;
7757
			}
7758
			foreach ($typeDef['elements'] as $eName => $attrs) {
7759
				if (!isset($xvalue[$eName])) {
7760
					if (isset($attrs['default'])) {
7761
						$xvalue[$eName] = $attrs['default'];
7762
						$this->debug('use default value of ' . $xvalue[$eName] . ' for element ' . $eName);
7763
					}
7764
				}
7765
				// if user took advantage of a minOccurs=0, then only serialize named parameters
7766
				if (isset($optionals)
7767
				    && (!isset($xvalue[$eName]))
7768
					&& ( (!isset($attrs['nillable'])) || $attrs['nillable'] != 'true')
7769
					){
7770
					if (isset($attrs['minOccurs']) && $attrs['minOccurs'] <> '0') {
7771
						$this->debug("apparent error: no value provided for element $eName with minOccurs=" . $attrs['minOccurs']);
7772
					}
7773
					// do nothing
7774
					$this->debug("no value provided for complexType element $eName and element is not nillable, so serialize nothing");
7775
				} else {
7776
					// get value
7777
					if (isset($xvalue[$eName])) {
7778
					    $v = $xvalue[$eName];
7779
					} else {
7780
					    $v = null;
7781
					}
7782
					if (isset($attrs['form'])) {
7783
						$unqualified = ($attrs['form'] == 'unqualified');
7784
					} else {
7785
						$unqualified = false;
7786
					}
7787
					if (isset($attrs['maxOccurs']) && ($attrs['maxOccurs'] == 'unbounded' || $attrs['maxOccurs'] > 1) && isset($v) && is_array($v) && $this->isArraySimpleOrStruct($v) == 'arraySimple') {
7788
						$vv = $v;
7789
						foreach ($vv as $k => $v) {
7790
							if (isset($attrs['type']) || isset($attrs['ref'])) {
7791
								// serialize schema-defined type
7792
							    $xml .= $this->serializeType($eName, isset($attrs['type']) ? $attrs['type'] : $attrs['ref'], $v, $use, $encodingStyle, $unqualified);
7793
							} else {
7794
								// serialize generic type (can this ever really happen?)
7795
							    $this->debug("calling serialize_val() for $v, $eName, false, false, false, false, $use");
7796
							    $xml .= $this->serialize_val($v, $eName, false, false, false, false, $use);
7797
							}
7798
						}
7799
					} else {
7800
						if (is_null($v) && isset($attrs['minOccurs']) && $attrs['minOccurs'] == '0') {
0 ignored issues
show
This if statement is empty and can be removed.

This check looks for the bodies of if statements that have no statements or where all statements have been commented out. This may be the result of changes for debugging or the code may simply be obsolete.

These if bodies can be removed. If you have an empty if but statements in the else branch, consider inverting the condition.

if (rand(1, 6) > 3) {
//print "Check failed";
} else {
    print "Check succeeded";
}

could be turned into

if (rand(1, 6) <= 3) {
    print "Check succeeded";
}

This is much more concise to read.

Loading history...
7801
							// do nothing
7802
						} elseif (is_null($v) && isset($attrs['nillable']) && $attrs['nillable'] == 'true') {
7803
							// TODO: serialize a nil correctly, but for now serialize schema-defined type
7804
						    $xml .= $this->serializeType($eName, isset($attrs['type']) ? $attrs['type'] : $attrs['ref'], $v, $use, $encodingStyle, $unqualified);
7805
						} elseif (isset($attrs['type']) || isset($attrs['ref'])) {
7806
							// serialize schema-defined type
7807
						    $xml .= $this->serializeType($eName, isset($attrs['type']) ? $attrs['type'] : $attrs['ref'], $v, $use, $encodingStyle, $unqualified);
7808
						} else {
7809
							// serialize generic type (can this ever really happen?)
7810
						    $this->debug("calling serialize_val() for $v, $eName, false, false, false, false, $use");
7811
						    $xml .= $this->serialize_val($v, $eName, false, false, false, false, $use);
7812
						}
7813
					}
7814
				}
7815
			}
7816
		} else {
7817
			$this->debug("no elements to serialize for XML Schema type $ns:$uqType");
7818
		}
7819
		return $xml;
7820
	}
7821
7822
	/**
7823
	* adds an XML Schema complex type to the WSDL types
7824
	*
7825
	* @param string	$name
7826
	* @param string $typeClass (complexType|simpleType|attribute)
7827
	* @param string $phpType currently supported are array and struct (php assoc array)
7828
	* @param string $compositor (all|sequence|choice)
7829
	* @param string $restrictionBase namespace:name (http://schemas.xmlsoap.org/soap/encoding/:Array)
7830
	* @param array $elements e.g. array ( name => array(name=>'',type=>'') )
7831
	* @param array $attrs e.g. array(array('ref'=>'SOAP-ENC:arrayType','wsdl:arrayType'=>'xsd:string[]'))
7832
	* @param string $arrayType as namespace:name (xsd:string)
7833
	* @see nusoap_xmlschema
7834
	* @access public
7835
	*/
7836
	function addComplexType($name,$typeClass='complexType',$phpType='array',$compositor='',$restrictionBase='',$elements=array(),$attrs=array(),$arrayType='') {
7837
		if (count($elements) > 0) {
7838
			$eElements = array();
7839
	    	foreach($elements as $n => $e){
7840
	            // expand each element
7841
	            $ee = array();
7842
	            foreach ($e as $k => $v) {
7843
		            $k = strpos($k,':') ? $this->expandQname($k) : $k;
7844
		            $v = strpos($v,':') ? $this->expandQname($v) : $v;
7845
		            $ee[$k] = $v;
7846
		    	}
7847
	    		$eElements[$n] = $ee;
7848
	    	}
7849
	    	$elements = $eElements;
7850
		}
7851
7852
		if (count($attrs) > 0) {
7853
	    	foreach($attrs as $n => $a){
7854
	            // expand each attribute
7855
	            foreach ($a as $k => $v) {
7856
		            $k = strpos($k,':') ? $this->expandQname($k) : $k;
7857
		            $v = strpos($v,':') ? $this->expandQname($v) : $v;
7858
		            $aa[$k] = $v;
7859
		    	}
7860
	    		$eAttrs[$n] = $aa;
7861
	    	}
7862
	    	$attrs = $eAttrs;
7863
		}
7864
7865
		$restrictionBase = strpos($restrictionBase,':') ? $this->expandQname($restrictionBase) : $restrictionBase;
7866
		$arrayType = strpos($arrayType,':') ? $this->expandQname($arrayType) : $arrayType;
7867
7868
		$typens = isset($this->namespaces['types']) ? $this->namespaces['types'] : $this->namespaces['tns'];
7869
		$this->schemas[$typens][0]->addComplexType($name,$typeClass,$phpType,$compositor,$restrictionBase,$elements,$attrs,$arrayType);
7870
	}
7871
7872
	/**
7873
	* adds an XML Schema simple type to the WSDL types
7874
	*
7875
	* @param string $name
7876
	* @param string $restrictionBase namespace:name (http://schemas.xmlsoap.org/soap/encoding/:Array)
7877
	* @param string $typeClass (should always be simpleType)
7878
	* @param string $phpType (should always be scalar)
7879
	* @param array $enumeration array of values
7880
	* @see nusoap_xmlschema
7881
	* @access public
7882
	*/
7883
	function addSimpleType($name, $restrictionBase='', $typeClass='simpleType', $phpType='scalar', $enumeration=array()) {
7884
		$restrictionBase = strpos($restrictionBase,':') ? $this->expandQname($restrictionBase) : $restrictionBase;
7885
7886
		$typens = isset($this->namespaces['types']) ? $this->namespaces['types'] : $this->namespaces['tns'];
7887
		$this->schemas[$typens][0]->addSimpleType($name, $restrictionBase, $typeClass, $phpType, $enumeration);
7888
	}
7889
7890
	/**
7891
	* adds an element to the WSDL types
7892
	*
7893
	* @param array $attrs attributes that must include name and type
7894
	* @see nusoap_xmlschema
7895
	* @access public
7896
	*/
7897
	function addElement($attrs) {
7898
		$typens = isset($this->namespaces['types']) ? $this->namespaces['types'] : $this->namespaces['tns'];
7899
		$this->schemas[$typens][0]->addElement($attrs);
7900
	}
7901
7902
	/**
7903
	* register an operation with the server
7904
	*
7905
	* @param string $name operation (method) name
7906
	* @param array $in assoc array of input values: key = param name, value = param type
7907
	* @param array $out assoc array of output values: key = param name, value = param type
7908
	* @param string $namespace optional The namespace for the operation
7909
	* @param string $soapaction optional The soapaction for the operation
7910
	* @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
7911
	* @param string $use (encoded|literal) optional The use for the parameters (cannot mix right now)
7912
	* @param string $documentation optional The description to include in the WSDL
7913
	* @param string $encodingStyle optional (usually 'http://schemas.xmlsoap.org/soap/encoding/' for encoded)
7914
	* @access public
7915
	*/
7916
	function addOperation($name, $in = false, $out = false, $namespace = false, $soapaction = false, $style = 'rpc', $use = 'encoded', $documentation = '', $encodingStyle = ''){
7917
		if ($use == 'encoded' && $encodingStyle == '') {
7918
			$encodingStyle = 'http://schemas.xmlsoap.org/soap/encoding/';
7919
		}
7920
7921
		if ($style == 'document') {
7922
			$elements = array();
7923
			foreach ($in as $n => $t) {
0 ignored issues
show
The expression $in of type false|array is not guaranteed to be traversable. How about adding an additional type check?

There are different options of fixing this problem.

  1. If you want to be on the safe side, you can add an additional type-check:

    $collection = json_decode($data, true);
    if ( ! is_array($collection)) {
        throw new \RuntimeException('$collection must be an array.');
    }
    
    foreach ($collection as $item) { /** ... */ }
    
  2. If you are sure that the expression is traversable, you might want to add a doc comment cast to improve IDE auto-completion and static analysis:

    /** @var array $collection */
    $collection = json_decode($data, true);
    
    foreach ($collection as $item) { /** .. */ }
    
  3. Mark the issue as a false-positive: Just hover the remove button, in the top-right corner of this issue for more options.

Loading history...
7924
				$elements[$n] = array('name' => $n, 'type' => $t, 'form' => 'unqualified');
7925
			}
7926
			$this->addComplexType($name . 'RequestType', 'complexType', 'struct', 'all', '', $elements);
7927
			$this->addElement(array('name' => $name, 'type' => $name . 'RequestType'));
7928
			$in = array('parameters' => 'tns:' . $name . '^');
7929
7930
			$elements = array();
7931
			foreach ($out as $n => $t) {
0 ignored issues
show
The expression $out of type false|array is not guaranteed to be traversable. How about adding an additional type check?

There are different options of fixing this problem.

  1. If you want to be on the safe side, you can add an additional type-check:

    $collection = json_decode($data, true);
    if ( ! is_array($collection)) {
        throw new \RuntimeException('$collection must be an array.');
    }
    
    foreach ($collection as $item) { /** ... */ }
    
  2. If you are sure that the expression is traversable, you might want to add a doc comment cast to improve IDE auto-completion and static analysis:

    /** @var array $collection */
    $collection = json_decode($data, true);
    
    foreach ($collection as $item) { /** .. */ }
    
  3. Mark the issue as a false-positive: Just hover the remove button, in the top-right corner of this issue for more options.

Loading history...
7932
				$elements[$n] = array('name' => $n, 'type' => $t, 'form' => 'unqualified');
7933
			}
7934
			$this->addComplexType($name . 'ResponseType', 'complexType', 'struct', 'all', '', $elements);
7935
			$this->addElement(array('name' => $name . 'Response', 'type' => $name . 'ResponseType', 'form' => 'qualified'));
7936
			$out = array('parameters' => 'tns:' . $name . 'Response' . '^');
7937
		}
7938
7939
		// get binding
7940
		$this->bindings[ $this->serviceName . 'Binding' ]['operations'][$name] =
7941
		array(
7942
		'name' => $name,
7943
		'binding' => $this->serviceName . 'Binding',
7944
		'endpoint' => $this->endpoint,
7945
		'soapAction' => $soapaction,
7946
		'style' => $style,
7947
		'input' => array(
7948
			'use' => $use,
7949
			'namespace' => $namespace,
7950
			'encodingStyle' => $encodingStyle,
7951
			'message' => $name . 'Request',
7952
			'parts' => $in),
7953
		'output' => array(
7954
			'use' => $use,
7955
			'namespace' => $namespace,
7956
			'encodingStyle' => $encodingStyle,
7957
			'message' => $name . 'Response',
7958
			'parts' => $out),
7959
		'namespace' => $namespace,
7960
		'transport' => 'http://schemas.xmlsoap.org/soap/http',
7961
		'documentation' => $documentation);
7962
		// add portTypes
7963
		// add messages
7964
		if($in)
7965
		{
7966
			foreach($in as $pName => $pType)
7967
			{
7968
				if(strpos($pType,':')) {
7969
					$pType = $this->getNamespaceFromPrefix($this->getPrefix($pType)).":".$this->getLocalPart($pType);
0 ignored issues
show
It seems like $this->getPrefix($pType) targeting nusoap_base::getPrefix() can also be of type false; however, nusoap_base::getNamespaceFromPrefix() does only seem to accept string, did you maybe forget to handle an error condition?
Loading history...
7970
				}
7971
				$this->messages[$name.'Request'][$pName] = $pType;
7972
			}
7973
		} else {
7974
            $this->messages[$name.'Request']= '0';
7975
        }
7976
		if($out)
7977
		{
7978
			foreach($out as $pName => $pType)
7979
			{
7980
				if(strpos($pType,':')) {
7981
					$pType = $this->getNamespaceFromPrefix($this->getPrefix($pType)).":".$this->getLocalPart($pType);
0 ignored issues
show
It seems like $this->getPrefix($pType) targeting nusoap_base::getPrefix() can also be of type false; however, nusoap_base::getNamespaceFromPrefix() does only seem to accept string, did you maybe forget to handle an error condition?
Loading history...
7982
				}
7983
				$this->messages[$name.'Response'][$pName] = $pType;
7984
			}
7985
		} else {
7986
            $this->messages[$name.'Response']= '0';
7987
        }
7988
		return true;
7989
	}
7990
}
7991
?><?php
7992
7993
/*
7994
7995
Modification information for LGPL compliance
7996
7997
r58622 - 2010-10-22 18:18:59 -0700 (Fri, 22 Oct 2010) - engsvnbuild - Author: lam <[email protected]>
7998
    bug 40066
7999
8000
r58361 - 2010-09-29 16:59:02 -0700 (Wed, 29 Sep 2010) - kjing - Author: Jenny Gonsalves <[email protected]>
8001
    Merging with maint_6_0_1 (svn merge -r 58250:58342)
8002
8003
r57813 - 2010-08-19 10:34:44 -0700 (Thu, 19 Aug 2010) - kjing - Author: John Mertic <[email protected]>
8004
    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.
8005
8006
r57707 - 2010-08-10 12:26:13 -0700 (Tue, 10 Aug 2010) - kjing - Author: Stanislav Malyshev <[email protected]>
8007
    fix SOAP calls with no parameters
8008
8009
r56990 - 2010-06-16 13:05:36 -0700 (Wed, 16 Jun 2010) - kjing - snapshot "Mango" svn branch to a new one for GitHub sync
8010
8011
r56989 - 2010-06-16 13:01:33 -0700 (Wed, 16 Jun 2010) - kjing - defunt "Mango" svn dev branch before github cutover
8012
8013
r55980 - 2010-04-19 13:31:28 -0700 (Mon, 19 Apr 2010) - kjing - create Mango (6.1) based on windex
8014
8015
r51719 - 2009-10-22 10:18:00 -0700 (Thu, 22 Oct 2009) - mitani - Converted to Build 3  tags and updated the build system
8016
8017
r51634 - 2009-10-19 13:32:22 -0700 (Mon, 19 Oct 2009) - mitani - Windex is the branch for Sugar Sales 1.0 development
8018
8019
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.
8020
8021
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.
8022
8023
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:
8024
- Changing all ereg function to either preg or simple string based ones
8025
- No more references to magic quotes.
8026
- Change all the session_unregister() functions to just unset() the correct session variable instead.
8027
8028
r50375 - 2009-08-24 18:07:43 -0700 (Mon, 24 Aug 2009) - dwong - branch kobe2 from tokyo r50372
8029
8030
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
8031
8032
r45680 - 2009-03-30 14:34:35 -0700 (Mon, 30 Mar 2009) - Samir Gandhi - modifeid serializeSchema to generate WS-I compliant WSDL
8033
8034
r42807 - 2008-12-29 11:16:59 -0800 (Mon, 29 Dec 2008) - dwong - Branch from trunk/sugarcrm r42806 to branches/tokyo/sugarcrm
8035
8036
r42645 - 2008-12-18 13:41:08 -0800 (Thu, 18 Dec 2008) - awu - merging maint_5_2_0 rev41336:HEAD to trunk
8037
8038
r41647 - 2008-11-11 17:44:30 -0800 (Tue, 11 Nov 2008) - majed - Fixes a few bugs
8039
8040
r41596 - 2008-11-10 19:20:04 -0800 (Mon, 10 Nov 2008) - Samir Gandhi - modified to set $method in the code
8041
8042
r41558 - 2008-11-10 14:35:34 -0800 (Mon, 10 Nov 2008) - majed - changes nusoap to allow for registering classes
8043
8044
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.
8045
Touched:
8046
- data/SugarBean.php
8047
- include/domit/php_http_client_generic.php
8048
- include/domit/php_http_connector.php
8049
- include/domit/testing_domit.php
8050
- include/domit/xml_domit_getelementsbypath.php
8051
- include/domit/xml_domit_lite_parser.php
8052
- include/domit/xml_domit_nodemaps.php
8053
- include/domit/xml_domit_parser.php
8054
- include/domit/xml_domit_shared.php
8055
- include/generic/SugarWidgets/SugarWidgetField.php
8056
- include/generic/SugarWidgets/SugarWidgetReportField.php
8057
- include/ListView/ProcessView.php
8058
- include/nusoap/class.soapclient.php
8059
- include/nusoap/nusoap.php
8060
- include/nusoap/nusoapmime.php
8061
- include/Pear/HTML_Safe/Safe.php
8062
- include/Pear/XML_HTMLSax3/HTMLSax3.php
8063
- modules/Administration/RebuildWorkFlow.php
8064
- modules/Expressions/RelateSelector.php
8065
- modules/Reports/templates/templates_reports.php
8066
- modules/WorkFlow/Delete.php
8067
- modules/WorkFlow/Save.php
8068
- modules/WorkFlow/SaveSequence.php
8069
- modules/WorkFlow/WorkFlow.php
8070
- modules/WorkFlowActionShells/CreateStep1.php
8071
- modules/WorkFlowActionShells/CreateStep2.php
8072
- modules/WorkFlowActionShells/Save.php
8073
- modules/WorkFlowActionShells/WorkFlowActionShell.php
8074
- modules/WorkFlowAlerts/Save.php
8075
- modules/WorkFlowAlerts/WorkFlowAlert.php
8076
- modules/WorkFlowAlertShells/DetailView.php
8077
- modules/WorkFlowAlertShells/WorkFlowAlertShell.php
8078
- modules/WorkFlowTriggerShells/CreateStep1.php
8079
- modules/WorkFlowTriggerShells/CreateStepFilter.php
8080
- modules/WorkFlowTriggerShells/SaveFilter.php
8081
- modules/WorkFlowTriggerShells/WorkFlowTriggerShell.php
8082
- soap/SoapHelperFunctions.php
8083
- test/modules/DynamicFields/DynamicFields_Bug24095_test.php
8084
- test/simpletest/browser.php
8085
- test/simpletest/default_reporter.php
8086
- test/simpletest/detached.php
8087
- test/simpletest/eclipse.php
8088
- test/simpletest/expectation.php
8089
- test/simpletest/extensions/pear_test_case.php
8090
- test/simpletest/form.php
8091
- test/simpletest/http.php
8092
- test/simpletest/mock_objects.php
8093
- test/simpletest/page.php
8094
- test/simpletest/parser.php
8095
- test/simpletest/remote.php
8096
- test/simpletest/shell_tester.php
8097
- test/simpletest/simple_test.php
8098
- test/simpletest/simpletest.php
8099
- test/simpletest/test/acceptance_test.php
8100
- test/simpletest/test/adapter_test.php
8101
- test/simpletest/test/authentication_test.php
8102
- test/simpletest/test/browser_test.php
8103
- test/simpletest/test/collector_test.php
8104
- test/simpletest/test/compatibility_test.php
8105
- test/simpletest/test/detached_test.php
8106
- test/simpletest/test/eclipse_test.php
8107
- test/simpletest/test/encoding_test.php
8108
- test/simpletest/test/errors_test.php
8109
- test/simpletest/test/expectation_test.php
8110
- test/simpletest/test/form_test.php
8111
- test/simpletest/test/frames_test.php
8112
- test/simpletest/test/http_test.php
8113
- test/simpletest/test/live_test.php
8114
- test/simpletest/test/mock_objects_test.php
8115
- test/simpletest/test/page_test.php
8116
- test/simpletest/test/parse_error_test.php
8117
- test/simpletest/test/parser_test.php
8118
- test/simpletest/test/remote_test.php
8119
- test/simpletest/test/shell_test.php
8120
- test/simpletest/test/shell_tester_test.php
8121
- test/simpletest/test/simpletest_test.php
8122
- test/simpletest/test/site/page_request.php
8123
- test/simpletest/test/tag_test.php
8124
- test/simpletest/test/unit_tester_test.php
8125
- test/simpletest/test/user_agent_test.php
8126
- test/simpletest/test/visual_test.php
8127
- test/simpletest/test/xml_test.php
8128
- test/simpletest/test_case.php
8129
- test/simpletest/ui/array_reporter/test.php
8130
- test/simpletest/ui/recorder/test.php
8131
- test/simpletest/unit_tester.php
8132
- test/simpletest/url.php
8133
- test/simpletest/user_agent.php
8134
- test/simpletest/web_tester.php
8135
- test/spikephpcoverage/src/PEAR.php
8136
- test/spikephpcoverage/src/util/Utility.php
8137
- test/spikephpcoverage/src/XML/Parser.php
8138
- test/spikephpcoverage/src/XML/Parser/Simple.php
8139
- test/test_utilities/SugarTest_SimpleBrowser.php
8140
8141
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.
8142
8143
r38300 - 2008-07-25 13:33:43 -0700 (Fri, 25 Jul 2008) - Samir Gandhi - put the debug in parseresponse function
8144
8145
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
8146
8147
r36824 - 2008-06-18 09:26:11 -0700 (Wed, 18 Jun 2008) - roger - bug: 21832
8148
8149
r26422 - 2007-09-05 17:29:12 -0700 (Wed, 05 Sep 2007) - majed - migrate from beta 1 to trunk
8150
8151
r15787 - 2006-08-10 10:14:41 -0700 (Thu, 10 Aug 2006) - roger - RRS: bug 7961
8152
8153
r14701 - 2006-07-17 13:37:26 -0700 (Mon, 17 Jul 2006) - roger - RRS: bug 5801
8154
8155
r13782 - 2006-06-06 10:58:55 -0700 (Tue, 06 Jun 2006) - majed - changes entry point code
8156
8157
r11466 - 2006-02-01 15:49:47 -0800 (Wed, 01 Feb 2006) - jacob - Adding extra !empty check to get around a PHP warning.
8158
8159
r11115 - 2006-01-17 14:54:45 -0800 (Tue, 17 Jan 2006) - majed - add entry point validation
8160
8161
r10585 - 2005-12-13 14:42:26 -0800 (Tue, 13 Dec 2005) - majed - adds new license mechanisim
8162
8163
r10170 - 2005-12-05 18:37:46 -0800 (Mon, 05 Dec 2005) - majed - fixes various issues
8164
8165
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.
8166
8167
r8991 - 2005-11-03 19:07:25 -0800 (Thu, 03 Nov 2005) - majed - fixes nusoap issue
8168
8169
r8846 - 2005-10-31 11:01:12 -0800 (Mon, 31 Oct 2005) - majed - new version of nusoap
8170
8171
r7905 - 2005-09-21 19:12:57 -0700 (Wed, 21 Sep 2005) - majed - restores old nusoap pre & with a few fixes
8172
8173
r7861 - 2005-09-20 15:40:25 -0700 (Tue, 20 Sep 2005) - majed - & fix for 3.5.1
8174
8175
r7452 - 2005-08-17 11:32:34 -0700 (Wed, 17 Aug 2005) - majed - changes soap to nusoap
8176
8177
r5820 - 2005-06-21 14:22:24 -0700 (Tue, 21 Jun 2005) - majed - fixes issues with nusoap and with custom fields
8178
8179
r5462 - 2005-05-25 13:50:11 -0700 (Wed, 25 May 2005) - majed - upgraded nusoap to .6.9
8180
8181
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
8182
8183
r573 - 2004-09-04 13:03:32 -0700 (Sat, 04 Sep 2004) - sugarclint - undoing copyrights added in inadvertantly.  --clint
8184
8185
r546 - 2004-09-03 11:49:38 -0700 (Fri, 03 Sep 2004) - sugarmsi - removed echo count
8186
8187
r354 - 2004-08-02 23:00:37 -0700 (Mon, 02 Aug 2004) - sugarjacob - Adding Soap
8188
8189
8190
*/
8191
8192
8193
8194
8195
8196
/**
8197
*
8198
* nusoap_parser class parses SOAP XML messages into native PHP values
8199
*
8200
* @author   Dietrich Ayala <[email protected]>
8201
* @author   Scott Nichol <[email protected]>
8202
8203
* @access   public
8204
*/
8205
class nusoap_parser extends nusoap_base {
0 ignored issues
show
Comprehensibility Best Practice introduced by
The type nusoap_parser has been defined more than once; this definition is ignored, only the first definition in include/nusoap/class.soap_parser.php (L65-684) is considered.

This check looks for classes that have been defined more than once.

If you can, we would recommend to use standard object-oriented programming techniques. For example, to avoid multiple types, it might make sense to create a common interface, and then multiple, different implementations for that interface.

This also has the side-effect of providing you with better IDE auto-completion, static analysis and also better OPCode caching from PHP.

Loading history...
Coding Style Compatibility introduced by
PSR1 recommends that each class should be in its own file to aid autoloaders.

Having each class in a dedicated file usually plays nice with PSR autoloaders and is therefore a well established practice. If you use other autoloaders, you might not want to follow this rule.

Loading history...
8206
8207
	var $xml = '';
8208
	var $xml_encoding = '';
8209
	var $method = '';
8210
	var $root_struct = '';
8211
	var $root_struct_name = '';
8212
	var $root_struct_namespace = '';
8213
	var $root_header = '';
8214
    var $document = '';			// incoming SOAP body (text)
8215
	// determines where in the message we are (envelope,header,body,method)
8216
	var $status = '';
8217
	var $position = 0;
8218
	var $depth = 0;
8219
	var $default_namespace = '';
8220
	var $namespaces = array();
8221
	var $message = array();
8222
    var $parent = '';
8223
	var $fault = false;
8224
	var $fault_code = '';
8225
	var $fault_str = '';
8226
	var $fault_detail = '';
8227
	var $depth_array = array();
8228
	var $debug_flag = true;
8229
	var $soapresponse = NULL;	// parsed SOAP Body
8230
	var $soapheader = NULL;		// parsed SOAP Header
8231
	var $responseHeaders = '';	// incoming SOAP headers (text)
8232
	var $body_position = 0;
8233
	// for multiref parsing:
8234
	// array of id => pos
8235
	var $ids = array();
8236
	// array of id => hrefs => pos
8237
	var $multirefs = array();
8238
	// toggle for auto-decoding element content
8239
	var $decode_utf8 = false;
8240
8241
	/**
8242
	* constructor that actually does the parsing
8243
	*
8244
	* @param    string $xml SOAP message
8245
	* @param    string $encoding character encoding scheme of message
8246
	* @param    string $method method for which XML is parsed (unused?)
8247
	* @param    string $decode_utf8 whether to decode UTF-8 to ISO-8859-1
8248
	* @access   public
8249
	*/
8250
	function nusoap_parser($xml,$encoding='UTF-8',$method='',$decode_utf8=true){
8251
		parent::nusoap_base();
8252
		$this->xml = $xml;
8253
		$this->xml_encoding = $encoding;
8254
		$this->method = $method;
8255
		$this->decode_utf8 = $decode_utf8;
0 ignored issues
show
Documentation Bug introduced by
It seems like $decode_utf8 can also be of type string. However, the property $decode_utf8 is declared as type boolean. Maybe add an additional type check?

Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a mixed type is assigned to a property that is type hinted more strictly.

For example, imagine you have a variable $accountId that can either hold an Id object or false (if there is no account id yet). Your code now assigns that value to the id property of an instance of the Account class. This class holds a proper account, so the id value must no longer be false.

Either this assignment is in error or a type check should be added for that assignment.

class Id
{
    public $id;

    public function __construct($id)
    {
        $this->id = $id;
    }

}

class Account
{
    /** @var  Id $id */
    public $id;
}

$account_id = false;

if (starsAreRight()) {
    $account_id = new Id(42);
}

$account = new Account();
if ($account instanceof Id)
{
    $account->id = $account_id;
}
Loading history...
8256
8257
		// Check whether content has been read.
8258
		if(!empty($xml)){
8259
			// Check XML encoding
8260
			$pos_xml = strpos($xml, '<?xml');
8261
			if ($pos_xml !== FALSE) {
8262
				$xml_decl = substr($xml, $pos_xml, strpos($xml, '?>', $pos_xml + 2) - $pos_xml + 1);
8263
				if (preg_match("/encoding=[\"']([^\"']*)[\"']/", $xml_decl, $res)) {
8264
					$xml_encoding = $res[1];
8265
					if (strtoupper($xml_encoding) != $encoding) {
8266
						$err = "Charset from HTTP Content-Type '" . $encoding . "' does not match encoding from XML declaration '" . $xml_encoding . "'";
8267
						$this->debug($err);
8268
						if ($encoding != 'ISO-8859-1' || strtoupper($xml_encoding) != 'UTF-8') {
8269
							$this->setError($err);
8270
							return;
8271
						}
8272
						// when HTTP says ISO-8859-1 (the default) and XML says UTF-8 (the typical), assume the other endpoint is just sloppy and proceed
8273
					} else {
8274
						$this->debug('Charset from HTTP Content-Type matches encoding from XML declaration');
8275
					}
8276
				} else {
8277
					$this->debug('No encoding specified in XML declaration');
8278
				}
8279
			} else {
8280
				$this->debug('No XML declaration');
8281
			}
8282
			$this->debug('Entering nusoap_parser(), length='.strlen($xml).', encoding='.$encoding);
8283
			// Create an XML parser - why not xml_parser_create_ns?
8284
			$this->parser = xml_parser_create($this->xml_encoding);
8285
			// Set the options for parsing the XML data.
8286
			//xml_parser_set_option($parser, XML_OPTION_SKIP_WHITE, 1);
8287
			xml_parser_set_option($this->parser, XML_OPTION_CASE_FOLDING, 0);
8288
			xml_parser_set_option($this->parser, XML_OPTION_TARGET_ENCODING, $this->xml_encoding);
8289
			// Set the object for the parser.
8290
			xml_set_object($this->parser, $this);
8291
			// Set the element handlers for the parser.
8292
			xml_set_element_handler($this->parser, 'start_element','end_element');
8293
			xml_set_character_data_handler($this->parser,'character_data');
8294
8295
			// Parse the XML file.
8296
			if(!xml_parse($this->parser,$xml,true)){
8297
			    // Display an error message.
8298
			    $err = sprintf('XML error parsing SOAP payload on line %d: %s',
8299
			    xml_get_current_line_number($this->parser),
8300
			    xml_error_string(xml_get_error_code($this->parser)));
8301
				$this->debug($err);
8302
				$this->debug("XML payload:\n" . $xml);
8303
				$this->setError($err);
8304
			} else {
8305
				$this->debug('in nusoap_parser ctor, message:');
8306
				$this->appendDebug($this->varDump($this->message));
8307
				$this->debug('parsed successfully, found root struct: '.$this->root_struct.' of name '.$this->root_struct_name);
8308
				// get final value
8309
				$this->soapresponse = $this->message[$this->root_struct]['result'];
8310
				// get header value
8311
				if($this->root_header != '' && isset($this->message[$this->root_header]['result'])){
8312
					$this->soapheader = $this->message[$this->root_header]['result'];
8313
				}
8314
				// resolve hrefs/ids
8315
				if(sizeof($this->multirefs) > 0){
8316
					foreach($this->multirefs as $id => $hrefs){
8317
						$this->debug('resolving multirefs for id: '.$id);
8318
						$idVal = $this->buildVal($this->ids[$id]);
8319
						if (is_array($idVal) && isset($idVal['!id'])) {
8320
							unset($idVal['!id']);
8321
						}
8322
						foreach($hrefs as $refPos => $ref){
8323
							$this->debug('resolving href at pos '.$refPos);
8324
							$this->multirefs[$id][$refPos] = $idVal;
8325
						}
8326
					}
8327
				}
8328
			}
8329
			xml_parser_free($this->parser);
8330
		} else {
8331
			$this->debug('xml was empty, didn\'t parse!');
8332
			$this->setError('xml was empty, didn\'t parse!');
8333
		}
8334
	}
8335
8336
	/**
8337
	* start-element handler
8338
	*
8339
	* @param    resource $parser XML parser object
8340
	* @param    string $name element name
8341
	* @param    array $attrs associative array of attributes
8342
	* @access   private
8343
	*/
8344
	function start_element($parser, $name, $attrs) {
8345
		// position in a total number of elements, starting from 0
8346
		// update class level pos
8347
		$pos = $this->position++;
8348
		// and set mine
8349
		$this->message[$pos] = array('pos' => $pos,'children'=>'','cdata'=>'');
8350
		// depth = how many levels removed from root?
8351
		// set mine as current global depth and increment global depth value
8352
		$this->message[$pos]['depth'] = $this->depth++;
8353
8354
		// else add self as child to whoever the current parent is
8355
		if($pos != 0){
8356
			$this->message[$this->parent]['children'] .= '|'.$pos;
8357
		}
8358
		// set my parent
8359
		$this->message[$pos]['parent'] = $this->parent;
8360
		// set self as current parent
8361
		$this->parent = $pos;
0 ignored issues
show
Documentation Bug introduced by
The property $parent was declared of type string, but $pos is of type integer. Maybe add a type cast?

This check looks for assignments to scalar types that may be of the wrong type.

To ensure the code behaves as expected, it may be a good idea to add an explicit type cast.

$answer = 42;

$correct = false;

$correct = (bool) $answer;
Loading history...
8362
		// set self as current value for this depth
8363
		$this->depth_array[$this->depth] = $pos;
8364
		// get element prefix
8365
		if(strpos($name,':')){
8366
			// get ns prefix
8367
			$prefix = substr($name,0,strpos($name,':'));
8368
			// get unqualified name
8369
			$name = substr(strstr($name,':'),1);
8370
		}
8371
		// set status
8372
		if ($name == 'Envelope' && $this->status == '') {
8373
			$this->status = 'envelope';
8374
		} elseif ($name == 'Header' && $this->status == 'envelope') {
8375
			$this->root_header = $pos;
0 ignored issues
show
Documentation Bug introduced by
The property $root_header was declared of type string, but $pos is of type integer. Maybe add a type cast?

This check looks for assignments to scalar types that may be of the wrong type.

To ensure the code behaves as expected, it may be a good idea to add an explicit type cast.

$answer = 42;

$correct = false;

$correct = (bool) $answer;
Loading history...
8376
			$this->status = 'header';
8377
		} elseif ($name == 'Body' && $this->status == 'envelope'){
8378
			$this->status = 'body';
8379
			$this->body_position = $pos;
8380
		// set method
8381
		} elseif($this->status == 'body' && $pos == ($this->body_position+1)) {
8382
			$this->status = 'method';
8383
			$this->root_struct_name = $name;
8384
			$this->root_struct = $pos;
0 ignored issues
show
Documentation Bug introduced by
The property $root_struct was declared of type string, but $pos is of type integer. Maybe add a type cast?

This check looks for assignments to scalar types that may be of the wrong type.

To ensure the code behaves as expected, it may be a good idea to add an explicit type cast.

$answer = 42;

$correct = false;

$correct = (bool) $answer;
Loading history...
8385
			$this->message[$pos]['type'] = 'struct';
8386
			$this->debug("found root struct $this->root_struct_name, pos $this->root_struct");
8387
		}
8388
		// set my status
8389
		$this->message[$pos]['status'] = $this->status;
8390
		// set name
8391
		$this->message[$pos]['name'] = htmlspecialchars($name);
8392
		// set attrs
8393
		$this->message[$pos]['attrs'] = $attrs;
8394
8395
		// loop through atts, logging ns and type declarations
8396
        $attstr = '';
8397
		foreach($attrs as $key => $value){
8398
        	$key_prefix = $this->getPrefix($key);
8399
			$key_localpart = $this->getLocalPart($key);
8400
			// if ns declarations, add to class level array of valid namespaces
8401
            if($key_prefix == 'xmlns'){
8402
				if(preg_match('/^http:\/\/www.w3.org\/[0-9]{4}\/XMLSchema$/',$value)){
8403
					$this->XMLSchemaVersion = $value;
8404
					$this->namespaces['xsd'] = $this->XMLSchemaVersion;
8405
					$this->namespaces['xsi'] = $this->XMLSchemaVersion.'-instance';
8406
				}
8407
                $this->namespaces[$key_localpart] = $value;
8408
				// set method namespace
8409
				if($name == $this->root_struct_name){
8410
					$this->methodNamespace = $value;
8411
				}
8412
			// if it's a type declaration, set type
8413
        } elseif($key_localpart == 'type'){
8414
        		if (isset($this->message[$pos]['type']) && $this->message[$pos]['type'] == 'array') {
0 ignored issues
show
This if statement is empty and can be removed.

This check looks for the bodies of if statements that have no statements or where all statements have been commented out. This may be the result of changes for debugging or the code may simply be obsolete.

These if bodies can be removed. If you have an empty if but statements in the else branch, consider inverting the condition.

if (rand(1, 6) > 3) {
//print "Check failed";
} else {
    print "Check succeeded";
}

could be turned into

if (rand(1, 6) <= 3) {
    print "Check succeeded";
}

This is much more concise to read.

Loading history...
8415
        			// do nothing: already processed arrayType
8416
        		} else {
8417
	            	$value_prefix = $this->getPrefix($value);
8418
	                $value_localpart = $this->getLocalPart($value);
8419
					$this->message[$pos]['type'] = $value_localpart;
8420
					$this->message[$pos]['typePrefix'] = $value_prefix;
8421
	                if(isset($this->namespaces[$value_prefix])){
8422
	                	$this->message[$pos]['type_namespace'] = $this->namespaces[$value_prefix];
8423
	                } else if(isset($attrs['xmlns:'.$value_prefix])) {
8424
						$this->message[$pos]['type_namespace'] = $attrs['xmlns:'.$value_prefix];
8425
	                }
8426
					// should do something here with the namespace of specified type?
8427
				}
8428
			} elseif($key_localpart == 'arrayType'){
8429
				$this->message[$pos]['type'] = 'array';
8430
				/* do arrayType ereg here
8431
				[1]    arrayTypeValue    ::=    atype asize
8432
				[2]    atype    ::=    QName rank*
8433
				[3]    rank    ::=    '[' (',')* ']'
8434
				[4]    asize    ::=    '[' length~ ']'
8435
				[5]    length    ::=    nextDimension* Digit+
8436
				[6]    nextDimension    ::=    Digit+ ','
8437
				*/
8438
				$expr = '/([A-Za-z0-9_]+):([A-Za-z]+[A-Za-z0-9_]+)\[([0-9]+),?([0-9]*)\]/';
8439
				if(preg_match($expr,$value,$regs)){
8440
					$this->message[$pos]['typePrefix'] = $regs[1];
8441
					$this->message[$pos]['arrayTypePrefix'] = $regs[1];
8442
	                if (isset($this->namespaces[$regs[1]])) {
8443
	                	$this->message[$pos]['arrayTypeNamespace'] = $this->namespaces[$regs[1]];
8444
	                } else if (isset($attrs['xmlns:'.$regs[1]])) {
8445
						$this->message[$pos]['arrayTypeNamespace'] = $attrs['xmlns:'.$regs[1]];
8446
	                }
8447
					$this->message[$pos]['arrayType'] = $regs[2];
8448
					$this->message[$pos]['arraySize'] = $regs[3];
8449
					$this->message[$pos]['arrayCols'] = $regs[4];
8450
				}
8451
			// specifies nil value (or not)
8452
			} elseif ($key_localpart == 'nil'){
8453
				$this->message[$pos]['nil'] = ($value == 'true' || $value == '1');
8454
			// some other attribute
8455
			} elseif ($key != 'href' && $key != 'xmlns' && $key_localpart != 'encodingStyle' && $key_localpart != 'root') {
8456
				$this->message[$pos]['xattrs']['!' . $key] = $value;
8457
			}
8458
8459
			if ($key == 'xmlns') {
8460
				$this->default_namespace = $value;
8461
			}
8462
			// log id
8463
			if($key == 'id'){
8464
				$this->ids[$value] = $pos;
8465
			}
8466
			// root
8467
			if($key_localpart == 'root' && $value == 1){
8468
				$this->status = 'method';
8469
				$this->root_struct_name = $name;
8470
				$this->root_struct = $pos;
8471
				$this->debug("found root struct $this->root_struct_name, pos $pos");
8472
			}
8473
            // for doclit
8474
            $attstr .= " $key=\"$value\"";
8475
		}
8476
        // get namespace - must be done after namespace atts are processed
8477
		if(isset($prefix)){
8478
			$this->message[$pos]['namespace'] = $this->namespaces[$prefix];
8479
			$this->default_namespace = $this->namespaces[$prefix];
8480
		} else {
8481
			$this->message[$pos]['namespace'] = $this->default_namespace;
8482
		}
8483
        if($this->status == 'header'){
8484
        	if ($this->root_header != $pos) {
8485
	        	$this->responseHeaders .= "<" . (isset($prefix) ? $prefix . ':' : '') . "$name$attstr>";
8486
	        }
8487
        } elseif($this->root_struct_name != ''){
8488
        	$this->document .= "<" . (isset($prefix) ? $prefix . ':' : '') . "$name$attstr>";
8489
        }
8490
	}
8491
8492
	/**
8493
	* end-element handler
8494
	*
8495
	* @param    resource $parser XML parser object
8496
	* @param    string $name element name
8497
	* @access   private
8498
	*/
8499
	function end_element($parser, $name) {
8500
		// position of current element is equal to the last value left in depth_array for my depth
8501
		$pos = $this->depth_array[$this->depth--];
8502
8503
        // get element prefix
8504
		if(strpos($name,':')){
8505
			// get ns prefix
8506
			$prefix = substr($name,0,strpos($name,':'));
8507
			// get unqualified name
8508
			$name = substr(strstr($name,':'),1);
8509
		}
8510
8511
		// build to native type
8512
		if(isset($this->body_position) && $pos > $this->body_position){
8513
			// deal w/ multirefs
8514
			if(isset($this->message[$pos]['attrs']['href'])){
8515
				// get id
8516
				$id = substr($this->message[$pos]['attrs']['href'],1);
8517
				// add placeholder to href array
8518
				$this->multirefs[$id][$pos] = 'placeholder';
8519
				// add set a reference to it as the result value
8520
				$this->message[$pos]['result'] =& $this->multirefs[$id][$pos];
8521
            // build complexType values
8522
			} elseif($this->message[$pos]['children'] != ''){
8523
				// if result has already been generated (struct/array)
8524
				if(!isset($this->message[$pos]['result'])){
8525
					$this->message[$pos]['result'] = $this->buildVal($pos);
8526
				}
8527
			// build complexType values of attributes and possibly simpleContent
8528
			} elseif (isset($this->message[$pos]['xattrs'])) {
8529
				if (isset($this->message[$pos]['nil']) && $this->message[$pos]['nil']) {
8530
					$this->message[$pos]['xattrs']['!'] = null;
8531
				} elseif (isset($this->message[$pos]['cdata']) && trim($this->message[$pos]['cdata']) != '') {
8532
	            	if (isset($this->message[$pos]['type'])) {
8533
						$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'] : '');
8534
					} else {
8535
						$parent = $this->message[$pos]['parent'];
8536
						if (isset($this->message[$parent]['type']) && ($this->message[$parent]['type'] == 'array') && isset($this->message[$parent]['arrayType'])) {
8537
							$this->message[$pos]['xattrs']['!'] = $this->decodeSimple($this->message[$pos]['cdata'], $this->message[$parent]['arrayType'], isset($this->message[$parent]['arrayTypeNamespace']) ? $this->message[$parent]['arrayTypeNamespace'] : '');
8538
						} else {
8539
							$this->message[$pos]['xattrs']['!'] = $this->message[$pos]['cdata'];
8540
						}
8541
					}
8542
				}
8543
				$this->message[$pos]['result'] = $this->message[$pos]['xattrs'];
8544
			// set value of simpleType (or nil complexType)
8545
			} else {
8546
            	//$this->debug('adding data for scalar value '.$this->message[$pos]['name'].' of value '.$this->message[$pos]['cdata']);
8547
				if (isset($this->message[$pos]['nil']) && $this->message[$pos]['nil']) {
8548
					$this->message[$pos]['xattrs']['!'] = null;
8549
				} elseif (isset($this->message[$pos]['type'])) {
8550
					$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'] : '');
8551
				} else {
8552
					$parent = $this->message[$pos]['parent'];
8553
					if (isset($this->message[$parent]['type']) && ($this->message[$parent]['type'] == 'array') && isset($this->message[$parent]['arrayType'])) {
8554
						$this->message[$pos]['result'] = $this->decodeSimple($this->message[$pos]['cdata'], $this->message[$parent]['arrayType'], isset($this->message[$parent]['arrayTypeNamespace']) ? $this->message[$parent]['arrayTypeNamespace'] : '');
8555
					} else {
8556
						$this->message[$pos]['result'] = $this->message[$pos]['cdata'];
8557
					}
8558
				}
8559
8560
				/* add value to parent's result, if parent is struct/array
8561
				$parent = $this->message[$pos]['parent'];
8562
				if($this->message[$parent]['type'] != 'map'){
8563
					if(strtolower($this->message[$parent]['type']) == 'array'){
8564
						$this->message[$parent]['result'][] = $this->message[$pos]['result'];
8565
					} else {
8566
						$this->message[$parent]['result'][$this->message[$pos]['name']] = $this->message[$pos]['result'];
8567
					}
8568
				}
8569
				*/
8570
			}
8571
		}
8572
8573
        // for doclit
8574
        if($this->status == 'header'){
8575
        	if ($this->root_header != $pos) {
8576
	        	$this->responseHeaders .= "</" . (isset($prefix) ? $prefix . ':' : '') . "$name>";
8577
	        }
8578
        } elseif($pos >= $this->root_struct){
8579
        	$this->document .= "</" . (isset($prefix) ? $prefix . ':' : '') . "$name>";
8580
        }
8581
		// switch status
8582
		if ($pos == $this->root_struct){
8583
			$this->status = 'body';
8584
			$this->root_struct_namespace = $this->message[$pos]['namespace'];
8585
		} elseif ($pos == $this->root_header) {
8586
			$this->status = 'envelope';
8587
		} elseif ($name == 'Body' && $this->status == 'body') {
8588
			$this->status = 'envelope';
8589
		} elseif ($name == 'Header' && $this->status == 'header') { // will never happen
8590
			$this->status = 'envelope';
8591
		} elseif ($name == 'Envelope' && $this->status == 'envelope') {
8592
			$this->status = '';
8593
		}
8594
		// set parent back to my parent
8595
		$this->parent = $this->message[$pos]['parent'];
8596
	}
8597
8598
	/**
8599
	* element content handler
8600
	*
8601
	* @param    resource $parser XML parser object
8602
	* @param    string $data element content
8603
	* @access   private
8604
	*/
8605
	function character_data($parser, $data){
8606
		$pos = $this->depth_array[$this->depth];
8607
		if ($this->xml_encoding=='UTF-8'){
8608
			// TODO: add an option to disable this for folks who want
8609
			// raw UTF-8 that, e.g., might not map to iso-8859-1
8610
			// TODO: this can also be handled with xml_parser_set_option($this->parser, XML_OPTION_TARGET_ENCODING, "ISO-8859-1");
8611
			if($this->decode_utf8){
8612
				$data = utf8_decode($data);
8613
			}
8614
		}
8615
        $this->message[$pos]['cdata'] .= $data;
8616
        // for doclit
8617
        if($this->status == 'header'){
8618
        	$this->responseHeaders .= $data;
8619
        } else {
8620
        	$this->document .= $data;
8621
        }
8622
	}
8623
8624
	/**
8625
	* get the parsed message (SOAP Body)
8626
	*
8627
	* @return	mixed
8628
	* @access   public
8629
	* @deprecated	use get_soapbody instead
8630
	*/
8631
	function get_response(){
8632
		return $this->soapresponse;
8633
	}
8634
8635
	/**
8636
	* get the parsed SOAP Body (NULL if there was none)
8637
	*
8638
	* @return	mixed
8639
	* @access   public
8640
	*/
8641
	function get_soapbody(){
8642
		return $this->soapresponse;
8643
	}
8644
8645
	/**
8646
	* get the parsed SOAP Header (NULL if there was none)
8647
	*
8648
	* @return	mixed
8649
	* @access   public
8650
	*/
8651
	function get_soapheader(){
8652
		return $this->soapheader;
8653
	}
8654
8655
	/**
8656
	* get the unparsed SOAP Header
8657
	*
8658
	* @return	string XML or empty if no Header
8659
	* @access   public
8660
	*/
8661
	function getHeaders(){
8662
	    return $this->responseHeaders;
8663
	}
8664
8665
	/**
8666
	* decodes simple types into PHP variables
8667
	*
8668
	* @param    string $value value to decode
8669
	* @param    string $type XML type to decode
8670
	* @param    string $typens XML type namespace to decode
8671
	* @return	mixed PHP value
8672
	* @access   private
8673
	*/
8674
	function decodeSimple($value, $type, $typens) {
8675
		// TODO: use the namespace!
8676
		if ((!isset($type)) || $type == 'string' || $type == 'long' || $type == 'unsignedLong') {
8677
			return (string) $value;
8678
		}
8679
		if ($type == 'int' || $type == 'integer' || $type == 'short' || $type == 'byte') {
8680
			return (int) $value;
8681
		}
8682
		if ($type == 'float' || $type == 'double' || $type == 'decimal') {
8683
			return (double) $value;
8684
		}
8685
		if ($type == 'boolean') {
8686
			if (strtolower($value) == 'false' || strtolower($value) == 'f') {
8687
				return false;
8688
			}
8689
			return (boolean) $value;
8690
		}
8691
		if ($type == 'base64' || $type == 'base64Binary') {
8692
			$this->debug('Decode base64 value');
8693
			return base64_decode($value);
8694
		}
8695
		// obscure numeric types
8696
		if ($type == 'nonPositiveInteger' || $type == 'negativeInteger'
8697
			|| $type == 'nonNegativeInteger' || $type == 'positiveInteger'
8698
			|| $type == 'unsignedInt'
8699
			|| $type == 'unsignedShort' || $type == 'unsignedByte') {
8700
			return (int) $value;
8701
		}
8702
		// bogus: parser treats array with no elements as a simple type
8703
		if ($type == 'array') {
8704
			return array();
8705
		}
8706
		// everything else
8707
		return (string) $value;
8708
	}
8709
8710
	/**
8711
	* builds response structures for compound values (arrays/structs)
8712
	* and scalars
8713
	*
8714
	* @param    integer $pos position in node tree
8715
	* @return	mixed	PHP value
8716
	* @access   private
8717
	*/
8718
	function buildVal($pos){
8719
		if(!isset($this->message[$pos]['type'])){
8720
			$this->message[$pos]['type'] = '';
8721
		}
8722
		$this->debug('in buildVal() for '.$this->message[$pos]['name']."(pos $pos) of type ".$this->message[$pos]['type']);
8723
		// if there are children...
8724
		if($this->message[$pos]['children'] != ''){
8725
			$this->debug('in buildVal, there are children');
8726
			$children = explode('|',$this->message[$pos]['children']);
8727
			array_shift($children); // knock off empty
8728
			// md array
8729
			if(isset($this->message[$pos]['arrayCols']) && $this->message[$pos]['arrayCols'] != ''){
8730
            	$r=0; // rowcount
8731
            	$c=0; // colcount
8732
            	foreach($children as $child_pos){
8733
					$this->debug("in buildVal, got an MD array element: $r, $c");
8734
					$params[$r][] = $this->message[$child_pos]['result'];
8735
				    $c++;
8736
				    if($c == $this->message[$pos]['arrayCols']){
8737
				    	$c = 0;
8738
						$r++;
8739
				    }
8740
                }
8741
            // array
8742
			} elseif($this->message[$pos]['type'] == 'array' || $this->message[$pos]['type'] == 'Array'){
8743
                $this->debug('in buildVal, adding array '.$this->message[$pos]['name']);
8744
                foreach($children as $child_pos){
8745
                	$params[] = &$this->message[$child_pos]['result'];
8746
                }
8747
            // apache Map type: java hashtable
8748
            } elseif($this->message[$pos]['type'] == 'Map' && $this->message[$pos]['type_namespace'] == 'http://xml.apache.org/xml-soap'){
8749
                $this->debug('in buildVal, Java Map '.$this->message[$pos]['name']);
8750
                foreach($children as $child_pos){
8751
                	$kv = explode("|",$this->message[$child_pos]['children']);
8752
                   	$params[$this->message[$kv[1]]['result']] = &$this->message[$kv[2]]['result'];
8753
                }
8754
            // generic compound type
8755
            //} elseif($this->message[$pos]['type'] == 'SOAPStruct' || $this->message[$pos]['type'] == 'struct') {
8756
		    } else {
8757
	    		// Apache Vector type: treat as an array
8758
                $this->debug('in buildVal, adding Java Vector or generic compound type '.$this->message[$pos]['name']);
8759
				if ($this->message[$pos]['type'] == 'Vector' && $this->message[$pos]['type_namespace'] == 'http://xml.apache.org/xml-soap') {
8760
					$notstruct = 1;
8761
				} else {
8762
					$notstruct = 0;
8763
	            }
8764
            	//
8765
            	foreach($children as $child_pos){
8766
            		if($notstruct){
8767
            			$params[] = &$this->message[$child_pos]['result'];
8768
            		} else {
8769
            			if (isset($params[$this->message[$child_pos]['name']])) {
8770
            				// de-serialize repeated element name into an array
8771
            				if ((!is_array($params[$this->message[$child_pos]['name']])) || (!isset($params[$this->message[$child_pos]['name']][0]))) {
8772
            					$params[$this->message[$child_pos]['name']] = array($params[$this->message[$child_pos]['name']]);
8773
            				}
8774
            				$params[$this->message[$child_pos]['name']][] = &$this->message[$child_pos]['result'];
8775
            			} else {
8776
					    	$params[$this->message[$child_pos]['name']] = &$this->message[$child_pos]['result'];
8777
					    }
8778
                	}
8779
                }
8780
			}
8781
			if (isset($this->message[$pos]['xattrs'])) {
8782
                $this->debug('in buildVal, handling attributes');
8783
				foreach ($this->message[$pos]['xattrs'] as $n => $v) {
8784
					$params[$n] = $v;
8785
				}
8786
			}
8787
			// handle simpleContent
8788
			if (isset($this->message[$pos]['cdata']) && trim($this->message[$pos]['cdata']) != '') {
8789
                $this->debug('in buildVal, handling simpleContent');
8790
            	if (isset($this->message[$pos]['type'])) {
8791
					$params['!'] = $this->decodeSimple($this->message[$pos]['cdata'], $this->message[$pos]['type'], isset($this->message[$pos]['type_namespace']) ? $this->message[$pos]['type_namespace'] : '');
8792
				} else {
8793
					$parent = $this->message[$pos]['parent'];
8794
					if (isset($this->message[$parent]['type']) && ($this->message[$parent]['type'] == 'array') && isset($this->message[$parent]['arrayType'])) {
8795
						$params['!'] = $this->decodeSimple($this->message[$pos]['cdata'], $this->message[$parent]['arrayType'], isset($this->message[$parent]['arrayTypeNamespace']) ? $this->message[$parent]['arrayTypeNamespace'] : '');
8796
					} else {
8797
						$params['!'] = $this->message[$pos]['cdata'];
8798
					}
8799
				}
8800
			}
8801
			$ret = is_array($params) ? $params : array();
8802
			$this->debug('in buildVal, return:');
8803
			$this->appendDebug($this->varDump($ret));
8804
			return $ret;
8805
		} else {
8806
        	$this->debug('in buildVal, no children, building scalar');
8807
			$cdata = isset($this->message[$pos]['cdata']) ? $this->message[$pos]['cdata'] : '';
8808
        	if (isset($this->message[$pos]['type'])) {
8809
				$ret = $this->decodeSimple($cdata, $this->message[$pos]['type'], isset($this->message[$pos]['type_namespace']) ? $this->message[$pos]['type_namespace'] : '');
8810
				$this->debug("in buildVal, return: $ret");
8811
				return $ret;
8812
			}
8813
			$parent = $this->message[$pos]['parent'];
8814
			if (isset($this->message[$parent]['type']) && ($this->message[$parent]['type'] == 'array') && isset($this->message[$parent]['arrayType'])) {
8815
				$ret = $this->decodeSimple($cdata, $this->message[$parent]['arrayType'], isset($this->message[$parent]['arrayTypeNamespace']) ? $this->message[$parent]['arrayTypeNamespace'] : '');
8816
				$this->debug("in buildVal, return: $ret");
8817
				return $ret;
8818
			}
8819
           	$ret = $this->message[$pos]['cdata'];
8820
			$this->debug("in buildVal, return: $ret");
8821
           	return $ret;
8822
		}
8823
	}
8824
}
8825
8826
/**
8827
 * Backward compatibility
8828
 */
8829
class soap_parser extends nusoap_parser {
0 ignored issues
show
Comprehensibility Best Practice introduced by
The type soap_parser has been defined more than once; this definition is ignored, only the first definition in include/nusoap/class.soap_parser.php (L689-690) is considered.

This check looks for classes that have been defined more than once.

If you can, we would recommend to use standard object-oriented programming techniques. For example, to avoid multiple types, it might make sense to create a common interface, and then multiple, different implementations for that interface.

This also has the side-effect of providing you with better IDE auto-completion, static analysis and also better OPCode caching from PHP.

Loading history...
Coding Style Compatibility introduced by
PSR1 recommends that each class should be in its own file to aid autoloaders.

Having each class in a dedicated file usually plays nice with PSR autoloaders and is therefore a well established practice. If you use other autoloaders, you might not want to follow this rule.

Loading history...
8830
}
8831
8832
?><?php
8833
8834
/*
8835
8836
Modification information for LGPL compliance
8837
8838
r58622 - 2010-10-22 18:18:59 -0700 (Fri, 22 Oct 2010) - engsvnbuild - Author: lam <[email protected]>
8839
    bug 40066
8840
8841
r58361 - 2010-09-29 16:59:02 -0700 (Wed, 29 Sep 2010) - kjing - Author: Jenny Gonsalves <[email protected]>
8842
    Merging with maint_6_0_1 (svn merge -r 58250:58342)
8843
8844
r57813 - 2010-08-19 10:34:44 -0700 (Thu, 19 Aug 2010) - kjing - Author: John Mertic <[email protected]>
8845
    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.
8846
8847
r57707 - 2010-08-10 12:26:13 -0700 (Tue, 10 Aug 2010) - kjing - Author: Stanislav Malyshev <[email protected]>
8848
    fix SOAP calls with no parameters
8849
8850
r56990 - 2010-06-16 13:05:36 -0700 (Wed, 16 Jun 2010) - kjing - snapshot "Mango" svn branch to a new one for GitHub sync
8851
8852
r56989 - 2010-06-16 13:01:33 -0700 (Wed, 16 Jun 2010) - kjing - defunt "Mango" svn dev branch before github cutover
8853
8854
r55980 - 2010-04-19 13:31:28 -0700 (Mon, 19 Apr 2010) - kjing - create Mango (6.1) based on windex
8855
8856
r51719 - 2009-10-22 10:18:00 -0700 (Thu, 22 Oct 2009) - mitani - Converted to Build 3  tags and updated the build system
8857
8858
r51634 - 2009-10-19 13:32:22 -0700 (Mon, 19 Oct 2009) - mitani - Windex is the branch for Sugar Sales 1.0 development
8859
8860
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.
8861
8862
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.
8863
8864
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:
8865
- Changing all ereg function to either preg or simple string based ones
8866
- No more references to magic quotes.
8867
- Change all the session_unregister() functions to just unset() the correct session variable instead.
8868
8869
r50375 - 2009-08-24 18:07:43 -0700 (Mon, 24 Aug 2009) - dwong - branch kobe2 from tokyo r50372
8870
8871
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
8872
8873
r45680 - 2009-03-30 14:34:35 -0700 (Mon, 30 Mar 2009) - Samir Gandhi - modifeid serializeSchema to generate WS-I compliant WSDL
8874
8875
r42807 - 2008-12-29 11:16:59 -0800 (Mon, 29 Dec 2008) - dwong - Branch from trunk/sugarcrm r42806 to branches/tokyo/sugarcrm
8876
8877
r42645 - 2008-12-18 13:41:08 -0800 (Thu, 18 Dec 2008) - awu - merging maint_5_2_0 rev41336:HEAD to trunk
8878
8879
r41647 - 2008-11-11 17:44:30 -0800 (Tue, 11 Nov 2008) - majed - Fixes a few bugs
8880
8881
r41596 - 2008-11-10 19:20:04 -0800 (Mon, 10 Nov 2008) - Samir Gandhi - modified to set $method in the code
8882
8883
r41558 - 2008-11-10 14:35:34 -0800 (Mon, 10 Nov 2008) - majed - changes nusoap to allow for registering classes
8884
8885
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.
8886
Touched:
8887
- data/SugarBean.php
8888
- include/domit/php_http_client_generic.php
8889
- include/domit/php_http_connector.php
8890
- include/domit/testing_domit.php
8891
- include/domit/xml_domit_getelementsbypath.php
8892
- include/domit/xml_domit_lite_parser.php
8893
- include/domit/xml_domit_nodemaps.php
8894
- include/domit/xml_domit_parser.php
8895
- include/domit/xml_domit_shared.php
8896
- include/generic/SugarWidgets/SugarWidgetField.php
8897
- include/generic/SugarWidgets/SugarWidgetReportField.php
8898
- include/ListView/ProcessView.php
8899
- include/nusoap/class.soapclient.php
8900
- include/nusoap/nusoap.php
8901
- include/nusoap/nusoapmime.php
8902
- include/Pear/HTML_Safe/Safe.php
8903
- include/Pear/XML_HTMLSax3/HTMLSax3.php
8904
- modules/Administration/RebuildWorkFlow.php
8905
- modules/Expressions/RelateSelector.php
8906
- modules/Reports/templates/templates_reports.php
8907
- modules/WorkFlow/Delete.php
8908
- modules/WorkFlow/Save.php
8909
- modules/WorkFlow/SaveSequence.php
8910
- modules/WorkFlow/WorkFlow.php
8911
- modules/WorkFlowActionShells/CreateStep1.php
8912
- modules/WorkFlowActionShells/CreateStep2.php
8913
- modules/WorkFlowActionShells/Save.php
8914
- modules/WorkFlowActionShells/WorkFlowActionShell.php
8915
- modules/WorkFlowAlerts/Save.php
8916
- modules/WorkFlowAlerts/WorkFlowAlert.php
8917
- modules/WorkFlowAlertShells/DetailView.php
8918
- modules/WorkFlowAlertShells/WorkFlowAlertShell.php
8919
- modules/WorkFlowTriggerShells/CreateStep1.php
8920
- modules/WorkFlowTriggerShells/CreateStepFilter.php
8921
- modules/WorkFlowTriggerShells/SaveFilter.php
8922
- modules/WorkFlowTriggerShells/WorkFlowTriggerShell.php
8923
- soap/SoapHelperFunctions.php
8924
- test/modules/DynamicFields/DynamicFields_Bug24095_test.php
8925
- test/simpletest/browser.php
8926
- test/simpletest/default_reporter.php
8927
- test/simpletest/detached.php
8928
- test/simpletest/eclipse.php
8929
- test/simpletest/expectation.php
8930
- test/simpletest/extensions/pear_test_case.php
8931
- test/simpletest/form.php
8932
- test/simpletest/http.php
8933
- test/simpletest/mock_objects.php
8934
- test/simpletest/page.php
8935
- test/simpletest/parser.php
8936
- test/simpletest/remote.php
8937
- test/simpletest/shell_tester.php
8938
- test/simpletest/simple_test.php
8939
- test/simpletest/simpletest.php
8940
- test/simpletest/test/acceptance_test.php
8941
- test/simpletest/test/adapter_test.php
8942
- test/simpletest/test/authentication_test.php
8943
- test/simpletest/test/browser_test.php
8944
- test/simpletest/test/collector_test.php
8945
- test/simpletest/test/compatibility_test.php
8946
- test/simpletest/test/detached_test.php
8947
- test/simpletest/test/eclipse_test.php
8948
- test/simpletest/test/encoding_test.php
8949
- test/simpletest/test/errors_test.php
8950
- test/simpletest/test/expectation_test.php
8951
- test/simpletest/test/form_test.php
8952
- test/simpletest/test/frames_test.php
8953
- test/simpletest/test/http_test.php
8954
- test/simpletest/test/live_test.php
8955
- test/simpletest/test/mock_objects_test.php
8956
- test/simpletest/test/page_test.php
8957
- test/simpletest/test/parse_error_test.php
8958
- test/simpletest/test/parser_test.php
8959
- test/simpletest/test/remote_test.php
8960
- test/simpletest/test/shell_test.php
8961
- test/simpletest/test/shell_tester_test.php
8962
- test/simpletest/test/simpletest_test.php
8963
- test/simpletest/test/site/page_request.php
8964
- test/simpletest/test/tag_test.php
8965
- test/simpletest/test/unit_tester_test.php
8966
- test/simpletest/test/user_agent_test.php
8967
- test/simpletest/test/visual_test.php
8968
- test/simpletest/test/xml_test.php
8969
- test/simpletest/test_case.php
8970
- test/simpletest/ui/array_reporter/test.php
8971
- test/simpletest/ui/recorder/test.php
8972
- test/simpletest/unit_tester.php
8973
- test/simpletest/url.php
8974
- test/simpletest/user_agent.php
8975
- test/simpletest/web_tester.php
8976
- test/spikephpcoverage/src/PEAR.php
8977
- test/spikephpcoverage/src/util/Utility.php
8978
- test/spikephpcoverage/src/XML/Parser.php
8979
- test/spikephpcoverage/src/XML/Parser/Simple.php
8980
- test/test_utilities/SugarTest_SimpleBrowser.php
8981
8982
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.
8983
8984
r38300 - 2008-07-25 13:33:43 -0700 (Fri, 25 Jul 2008) - Samir Gandhi - put the debug in parseresponse function
8985
8986
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
8987
8988
r36824 - 2008-06-18 09:26:11 -0700 (Wed, 18 Jun 2008) - roger - bug: 21832
8989
8990
r26422 - 2007-09-05 17:29:12 -0700 (Wed, 05 Sep 2007) - majed - migrate from beta 1 to trunk
8991
8992
r15787 - 2006-08-10 10:14:41 -0700 (Thu, 10 Aug 2006) - roger - RRS: bug 7961
8993
8994
r14701 - 2006-07-17 13:37:26 -0700 (Mon, 17 Jul 2006) - roger - RRS: bug 5801
8995
8996
r13782 - 2006-06-06 10:58:55 -0700 (Tue, 06 Jun 2006) - majed - changes entry point code
8997
8998
r11466 - 2006-02-01 15:49:47 -0800 (Wed, 01 Feb 2006) - jacob - Adding extra !empty check to get around a PHP warning.
8999
9000
r11115 - 2006-01-17 14:54:45 -0800 (Tue, 17 Jan 2006) - majed - add entry point validation
9001
9002
r10585 - 2005-12-13 14:42:26 -0800 (Tue, 13 Dec 2005) - majed - adds new license mechanisim
9003
9004
r10170 - 2005-12-05 18:37:46 -0800 (Mon, 05 Dec 2005) - majed - fixes various issues
9005
9006
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.
9007
9008
r8991 - 2005-11-03 19:07:25 -0800 (Thu, 03 Nov 2005) - majed - fixes nusoap issue
9009
9010
r8846 - 2005-10-31 11:01:12 -0800 (Mon, 31 Oct 2005) - majed - new version of nusoap
9011
9012
r7905 - 2005-09-21 19:12:57 -0700 (Wed, 21 Sep 2005) - majed - restores old nusoap pre & with a few fixes
9013
9014
r7861 - 2005-09-20 15:40:25 -0700 (Tue, 20 Sep 2005) - majed - & fix for 3.5.1
9015
9016
r7452 - 2005-08-17 11:32:34 -0700 (Wed, 17 Aug 2005) - majed - changes soap to nusoap
9017
9018
r5820 - 2005-06-21 14:22:24 -0700 (Tue, 21 Jun 2005) - majed - fixes issues with nusoap and with custom fields
9019
9020
r5462 - 2005-05-25 13:50:11 -0700 (Wed, 25 May 2005) - majed - upgraded nusoap to .6.9
9021
9022
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
9023
9024
r573 - 2004-09-04 13:03:32 -0700 (Sat, 04 Sep 2004) - sugarclint - undoing copyrights added in inadvertantly.  --clint
9025
9026
r546 - 2004-09-03 11:49:38 -0700 (Fri, 03 Sep 2004) - sugarmsi - removed echo count
9027
9028
r354 - 2004-08-02 23:00:37 -0700 (Mon, 02 Aug 2004) - sugarjacob - Adding Soap
9029
9030
9031
*/
9032
9033
9034
9035
9036
9037
/**
9038
*
9039
* [nu]soapclient higher level class for easy usage.
9040
*
9041
* usage:
9042
*
9043
* // instantiate client with server info
9044
* $soapclient = new nusoap_client( string path [ ,mixed wsdl] );
9045
*
9046
* // call method, get results
9047
* echo $soapclient->call( string methodname [ ,array parameters] );
9048
*
9049
* // bye bye client
9050
* unset($soapclient);
9051
*
9052
* @author   Dietrich Ayala <[email protected]>
9053
* @author   Scott Nichol <[email protected]>
9054
9055
* @access   public
9056
*/
9057
class nusoap_client extends nusoap_base  {
0 ignored issues
show
Comprehensibility Best Practice introduced by
The type nusoap_client has been defined more than once; this definition is ignored, only the first definition in include/nusoap/class.soapclient.php (L175-1131) is considered.

This check looks for classes that have been defined more than once.

If you can, we would recommend to use standard object-oriented programming techniques. For example, to avoid multiple types, it might make sense to create a common interface, and then multiple, different implementations for that interface.

This also has the side-effect of providing you with better IDE auto-completion, static analysis and also better OPCode caching from PHP.

Loading history...
Coding Style Compatibility introduced by
PSR1 recommends that each class should be in its own file to aid autoloaders.

Having each class in a dedicated file usually plays nice with PSR autoloaders and is therefore a well established practice. If you use other autoloaders, you might not want to follow this rule.

Loading history...
9058
9059
	var $username = '';				// Username for HTTP authentication
9060
	var $password = '';				// Password for HTTP authentication
9061
	var $authtype = '';				// Type of HTTP authentication
9062
	var $certRequest = array();		// Certificate for HTTP SSL authentication
9063
	var $requestHeaders = false;	// SOAP headers in request (text)
9064
	var $responseHeaders = '';		// SOAP headers from response (incomplete namespace resolution) (text)
9065
	var $responseHeader = NULL;		// SOAP Header from response (parsed)
9066
	var $document = '';				// SOAP body response portion (incomplete namespace resolution) (text)
9067
	var $endpoint;
9068
	var $forceEndpoint = '';		// overrides WSDL endpoint
9069
    var $proxyhost = '';
9070
    var $proxyport = '';
9071
	var $proxyusername = '';
9072
	var $proxypassword = '';
9073
	var $portName = '';				// port name to use in WSDL
9074
    var $xml_encoding = '';			// character set encoding of incoming (response) messages
9075
	var $http_encoding = false;
9076
	var $timeout = 0;				// HTTP connection timeout
9077
	var $response_timeout = 30;		// HTTP response timeout
9078
	var $endpointType = '';			// soap|wsdl, empty for WSDL initialization error
9079
	var $persistentConnection = false;
9080
	var $defaultRpcParams = false;	// This is no longer used
9081
	var $request = '';				// HTTP request
9082
	var $response = '';				// HTTP response
9083
	var $responseData = '';			// SOAP payload of response
9084
	var $cookies = array();			// Cookies from response or for request
9085
    var $decode_utf8 = false;		// toggles whether the parser decodes element content w/ utf8_decode()
9086
	var $operations = array();		// WSDL operations, empty for WSDL initialization error
9087
	var $curl_options = array();	// User-specified cURL options
9088
	var $bindingType = '';			// WSDL operation binding type
9089
	var $use_curl = false;			// whether to always try to use cURL
9090
9091
	/*
9092
	 * fault related variables
9093
	 */
9094
	/**
9095
	 * @var      fault
9096
	 * @access   public
9097
	 */
9098
	var $fault;
9099
	/**
9100
	 * @var      faultcode
9101
	 * @access   public
9102
	 */
9103
	var $faultcode;
9104
	/**
9105
	 * @var      faultstring
9106
	 * @access   public
9107
	 */
9108
	var $faultstring;
9109
	/**
9110
	 * @var      faultdetail
9111
	 * @access   public
9112
	 */
9113
	var $faultdetail;
9114
9115
	/**
9116
	* constructor
9117
	*
9118
	* @param    mixed $endpoint SOAP server or WSDL URL (string), or wsdl instance (object)
9119
	* @param    mixed $wsdl optional, set to 'wsdl' or true if using WSDL
9120
	* @param    string $proxyhost optional
9121
	* @param    string $proxyport optional
9122
	* @param	string $proxyusername optional
9123
	* @param	string $proxypassword optional
9124
	* @param	integer $timeout set the connection timeout
9125
	* @param	integer $response_timeout set the response timeout
9126
	* @param	string $portName optional portName in WSDL document
9127
	* @access   public
9128
	*/
9129
	function nusoap_client($endpoint,$wsdl = false,$proxyhost = false,$proxyport = false,$proxyusername = false, $proxypassword = false, $timeout = 0, $response_timeout = 30, $portName = ''){
9130
		parent::nusoap_base();
9131
		//ADDED FOR SUGAR PROXY SUPPORT
9132
		global $proxy_config;
9133
		if(!$proxyhost){
9134
			if(empty($proxy_config)){
9135
				if(!empty($GLOBALS['db'])){
9136
9137
					$proxy_config = new Administration();
9138
					$proxy_config->retrieveSettings('proxy');
9139
				}
9140
			}
9141
9142
			if(!empty($proxy_config))
9143
			{
9144
    			if(!empty($proxy_config->settings['proxy_on'])){
9145
    				$proxyhost = $proxy_config->settings['proxy_host'];
9146
    				$proxyport = $proxy_config->settings['proxy_port'];
9147
9148
    			}
9149
    			if(!empty($proxy_config->settings['proxy_auth'])){
9150
    				$proxyusername = $proxy_config->settings['proxy_username'];
9151
    				$proxypassword = $proxy_config->settings['proxy_password'];
9152
    			}
9153
			}
9154
		}
9155
		$this->endpoint = $endpoint;
9156
		$this->proxyhost = $proxyhost;
9157
		$this->proxyport = $proxyport;
9158
		$this->proxyusername = $proxyusername;
9159
		$this->proxypassword = $proxypassword;
9160
		$this->timeout = $timeout;
9161
		$this->response_timeout = $response_timeout;
9162
		$this->portName = $portName;
9163
9164
		$this->debug("ctor wsdl=$wsdl timeout=$timeout response_timeout=$response_timeout");
9165
		$this->appendDebug('endpoint=' . $this->varDump($endpoint));
9166
9167
		// make values
9168
		if($wsdl){
9169
			if (is_object($endpoint) && (get_class($endpoint) == 'wsdl')) {
9170
				$this->wsdl = $endpoint;
9171
				$this->endpoint = $this->wsdl->wsdl;
9172
				$this->wsdlFile = $this->endpoint;
9173
				$this->debug('existing wsdl instance created from ' . $this->endpoint);
9174
				$this->checkWSDL();
9175
			} else {
9176
				$this->wsdlFile = $this->endpoint;
9177
				$this->wsdl = null;
9178
				$this->debug('will use lazy evaluation of wsdl from ' . $this->endpoint);
9179
			}
9180
			$this->endpointType = 'wsdl';
9181
		} else {
9182
			$this->debug("instantiate SOAP with endpoint at $endpoint");
9183
			$this->endpointType = 'soap';
9184
		}
9185
	}
9186
9187
	/**
9188
	* calls method, returns PHP native type
9189
	*
9190
	* @param    string $operation SOAP server URL or path
9191
	* @param    mixed $params An array, associative or simple, of the parameters
9192
	*			              for the method call, or a string that is the XML
9193
	*			              for the call.  For rpc style, this call will
9194
	*			              wrap the XML in a tag named after the method, as
9195
	*			              well as the SOAP Envelope and Body.  For document
9196
	*			              style, this will only wrap with the Envelope and Body.
9197
	*			              IMPORTANT: when using an array with document style,
9198
	*			              in which case there
9199
	*                         is really one parameter, the root of the fragment
9200
	*                         used in the call, which encloses what programmers
9201
	*                         normally think of parameters.  A parameter array
9202
	*                         *must* include the wrapper.
9203
	* @param	string $namespace optional method namespace (WSDL can override)
9204
	* @param	string $soapAction optional SOAPAction value (WSDL can override)
9205
	* @param	mixed $headers optional string of XML with SOAP header content, or array of soapval objects for SOAP headers, or associative array
9206
	* @param	boolean $rpcParams optional (no longer used)
9207
	* @param	string	$style optional (rpc|document) the style to use when serializing parameters (WSDL can override)
9208
	* @param	string	$use optional (encoded|literal) the use when serializing parameters (WSDL can override)
9209
	* @return	mixed	response from SOAP call, normally an associative array mirroring the structure of the XML response, false for certain fatal errors
9210
	* @access   public
9211
	*/
9212
	function call($operation,$params=array(),$namespace='http://tempuri.org',$soapAction='',$headers=false,$rpcParams=null,$style='rpc',$use='encoded'){
9213
		$this->operation = $operation;
9214
		$this->fault = false;
9215
		$this->setError('');
9216
		$this->request = '';
9217
		$this->response = '';
9218
		$this->responseData = '';
9219
		$this->faultstring = '';
9220
		$this->faultcode = '';
9221
		$this->opData = array();
9222
9223
		$this->debug("call: operation=$operation, namespace=$namespace, soapAction=$soapAction, rpcParams=$rpcParams, style=$style, use=$use, endpointType=$this->endpointType");
9224
		$this->appendDebug('params=' . $this->varDump($params));
9225
		$this->appendDebug('headers=' . $this->varDump($headers));
9226
		if ($headers) {
9227
			$this->requestHeaders = $headers;
9228
		}
9229
		if ($this->endpointType == 'wsdl' && is_null($this->wsdl)) {
9230
			$this->loadWSDL();
9231
			if ($this->getError())
9232
				return false;
9233
		}
9234
		// serialize parameters
9235
		if($this->endpointType == 'wsdl' && $opData = $this->getOperationData($operation)){
9236
			// use WSDL for operation
9237
			$this->opData = $opData;
9238
			$this->debug("found operation");
9239
			$this->appendDebug('opData=' . $this->varDump($opData));
9240
			if (isset($opData['soapAction'])) {
9241
				$soapAction = $opData['soapAction'];
9242
			}
9243
			if (! $this->forceEndpoint) {
9244
				$this->endpoint = $opData['endpoint'];
9245
			} else {
9246
				$this->endpoint = $this->forceEndpoint;
9247
			}
9248
			$namespace = isset($opData['input']['namespace']) ? $opData['input']['namespace'] :	$namespace;
9249
			$style = $opData['style'];
9250
			$use = $opData['input']['use'];
9251
			// add ns to ns array
9252
			if($namespace != '' && !isset($this->wsdl->namespaces[$namespace])){
9253
				$nsPrefix = 'ns' . rand(1000, 9999);
9254
				$this->wsdl->namespaces[$nsPrefix] = $namespace;
9255
			}
9256
            $nsPrefix = $this->wsdl->getPrefixFromNamespace($namespace);
9257
			// serialize payload
9258
			if (is_string($params)) {
9259
				$this->debug("serializing param string for WSDL operation $operation");
9260
				$payload = $params;
9261
			} elseif (is_array($params)) {
9262
				$this->debug("serializing param array for WSDL operation $operation");
9263
				$payload = $this->wsdl->serializeRPCParameters($operation,'input',$params,$this->bindingType);
9264
			} else {
9265
				$this->debug('params must be array or string');
9266
				$this->setError('params must be array or string');
9267
				return false;
9268
			}
9269
            $usedNamespaces = $this->wsdl->usedNamespaces;
9270
			if (isset($opData['input']['encodingStyle'])) {
9271
				$encodingStyle = $opData['input']['encodingStyle'];
9272
			} else {
9273
				$encodingStyle = '';
9274
			}
9275
			$this->appendDebug($this->wsdl->getDebug());
9276
			$this->wsdl->clearDebug();
9277
			if ($errstr = $this->wsdl->getError()) {
9278
				$this->debug('got wsdl error: '.$errstr);
9279
				$this->setError('wsdl error: '.$errstr);
9280
				return false;
9281
			}
9282
		} elseif($this->endpointType == 'wsdl') {
9283
			// operation not in WSDL
9284
			$this->appendDebug($this->wsdl->getDebug());
9285
			$this->wsdl->clearDebug();
9286
			$this->setError('operation '.$operation.' not present in WSDL.');
9287
			$this->debug("operation '$operation' not present in WSDL.");
9288
			return false;
9289
		} else {
9290
			// no WSDL
9291
			//$this->namespaces['ns1'] = $namespace;
9292
			$nsPrefix = 'ns' . rand(1000, 9999);
9293
			// serialize
9294
			$payload = '';
9295
			if (is_string($params)) {
9296
				$this->debug("serializing param string for operation $operation");
9297
				$payload = $params;
9298
			} elseif (is_array($params)) {
9299
				$this->debug("serializing param array for operation $operation");
9300
				foreach($params as $k => $v){
9301
					$payload .= $this->serialize_val($v,$k,false,false,false,false,$use);
9302
				}
9303
			} else {
9304
				$this->debug('params must be array or string');
9305
				$this->setError('params must be array or string');
9306
				return false;
9307
			}
9308
			$usedNamespaces = array();
9309
			if ($use == 'encoded') {
9310
				$encodingStyle = 'http://schemas.xmlsoap.org/soap/encoding/';
9311
			} else {
9312
				$encodingStyle = '';
9313
			}
9314
		}
9315
9316
		// wrap RPC calls with method element
9317
		if ($style == 'rpc') {
9318
			if ($use == 'literal') {
9319
				$this->debug("wrapping RPC request with literal method element");
9320
				if ($namespace) {
9321
					// 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
9322
					$payload = "<$nsPrefix:$operation xmlns:$nsPrefix=\"$namespace\">" .
9323
								$payload .
9324
								"</$nsPrefix:$operation>";
9325
				} else {
9326
					$payload = "<$operation>" . $payload . "</$operation>";
9327
				}
9328
			} else {
9329
				$this->debug("wrapping RPC request with encoded method element");
9330
				if ($namespace) {
9331
					$payload = "<$nsPrefix:$operation xmlns:$nsPrefix=\"$namespace\">" .
9332
								$payload .
9333
								"</$nsPrefix:$operation>";
9334
				} else {
9335
					$payload = "<$operation>" .
9336
								$payload .
9337
								"</$operation>";
9338
				}
9339
			}
9340
		}
9341
9342
		// check for payload override
9343
		$payload = !empty($this->payloadOverride) ? $this->payloadOverride : $payload;
9344
9345
		// serialize envelope
9346
		$soapmsg = $this->serializeEnvelope($payload,$this->requestHeaders,$usedNamespaces,$style,$use,$encodingStyle);
9347
		$this->debug("endpoint=$this->endpoint, soapAction=$soapAction, namespace=$namespace, style=$style, use=$use, encodingStyle=$encodingStyle");
9348
		$this->debug('SOAP message length=' . strlen($soapmsg) . ' contents (max 1000 bytes)=' . substr($soapmsg, 0, 1000));
9349
		// send
9350
		$return = $this->send($this->getHTTPBody($soapmsg),$soapAction,$this->timeout,$this->response_timeout);
9351
		if($errstr = $this->getError()){
9352
			$this->debug('Error: '.$errstr);
9353
			return false;
9354
		} else {
9355
			$this->return = $return;
9356
			$this->debug('sent message successfully and got a(n) '.gettype($return));
9357
           	$this->appendDebug('return=' . $this->varDump($return));
9358
9359
			// fault?
9360
			if(is_array($return) && isset($return['faultcode'])){
9361
				$this->debug('got fault');
9362
				$this->setError($return['faultcode'].': '.$return['faultstring']);
9363
				$this->fault = true;
9364
				foreach($return as $k => $v){
9365
					$this->$k = $v;
9366
					$this->debug("$k = $v<br>");
9367
				}
9368
				$this->debug('return data for faultcode = ' . var_export($return, true));
9369
				return $return;
9370
			} elseif ($style == 'document') {
9371
				// NOTE: if the response is defined to have multiple parts (i.e. unwrapped),
9372
				// we are only going to return the first part here...sorry about that
9373
				return $return;
9374
			} else {
9375
				// array of return values
9376
				if(is_array($return)){
9377
					// multiple 'out' parameters, which we return wrapped up
9378
					// in the array
9379
					if(sizeof($return) > 1){
9380
						return $return;
9381
					}
9382
					// single 'out' parameter (normally the return value)
9383
					$return = array_shift($return);
9384
					$this->debug('return shifted value: ');
9385
					$this->appendDebug($this->varDump($return));
9386
           			return $return;
9387
				// nothing returned (ie, echoVoid)
9388
				} else {
9389
					return "";
9390
				}
9391
			}
9392
		}
9393
	}
9394
9395
	/**
9396
	* check WSDL passed as an instance or pulled from an endpoint
9397
	*
9398
	* @access   private
9399
	*/
9400
	function checkWSDL() {
9401
		$this->appendDebug($this->wsdl->getDebug());
9402
		$this->wsdl->clearDebug();
9403
		$this->debug('checkWSDL');
9404
		// catch errors
9405
		if ($errstr = $this->wsdl->getError()) {
9406
			$this->appendDebug($this->wsdl->getDebug());
9407
			$this->wsdl->clearDebug();
9408
			$this->debug('got wsdl error: '.$errstr);
9409
			$this->setError('wsdl error: '.$errstr);
9410
		} elseif ($this->operations = $this->wsdl->getOperations($this->portName, 'soap')) {
9411
			$this->appendDebug($this->wsdl->getDebug());
9412
			$this->wsdl->clearDebug();
9413
			$this->bindingType = 'soap';
9414
			$this->debug('got '.count($this->operations).' operations from wsdl '.$this->wsdlFile.' for binding type '.$this->bindingType);
9415
		} elseif ($this->operations = $this->wsdl->getOperations($this->portName, 'soap12')) {
9416
			$this->appendDebug($this->wsdl->getDebug());
9417
			$this->wsdl->clearDebug();
9418
			$this->bindingType = 'soap12';
9419
			$this->debug('got '.count($this->operations).' operations from wsdl '.$this->wsdlFile.' for binding type '.$this->bindingType);
9420
			$this->debug('**************** WARNING: SOAP 1.2 BINDING *****************');
9421
		} else {
9422
			$this->appendDebug($this->wsdl->getDebug());
9423
			$this->wsdl->clearDebug();
9424
			$this->debug('getOperations returned false');
9425
			$this->setError('no operations defined in the WSDL document!');
9426
		}
9427
	}
9428
9429
	/**
9430
	 * instantiate wsdl object and parse wsdl file
9431
	 *
9432
	 * @access	public
9433
	 */
9434
	function loadWSDL() {
9435
		$this->debug('instantiating wsdl class with doc: '.$this->wsdlFile);
9436
		$this->wsdl = new wsdl('',$this->proxyhost,$this->proxyport,$this->proxyusername,$this->proxypassword,$this->timeout,$this->response_timeout,$this->curl_options,$this->use_curl);
9437
		$this->wsdl->setCredentials($this->username, $this->password, $this->authtype, $this->certRequest);
9438
		$this->wsdl->fetchWSDL($this->wsdlFile);
9439
		$this->checkWSDL();
9440
	}
9441
9442
	/**
9443
	* get available data pertaining to an operation
9444
	*
9445
	* @param    string $operation operation name
9446
	* @return	array array of data pertaining to the operation
9447
	* @access   public
9448
	*/
9449
	function getOperationData($operation){
9450
		if ($this->endpointType == 'wsdl' && is_null($this->wsdl)) {
9451
			$this->loadWSDL();
9452
			if ($this->getError())
9453
				return false;
9454
		}
9455
		if(isset($this->operations[$operation])){
9456
			return $this->operations[$operation];
9457
		}
9458
		$this->debug("No data for operation: $operation");
9459
	}
9460
9461
    /**
9462
    * send the SOAP message
9463
    *
9464
    * Note: if the operation has multiple return values
9465
    * the return value of this method will be an array
9466
    * of those values.
9467
    *
9468
	* @param    string $msg a SOAPx4 soapmsg object
9469
	* @param    string $soapaction SOAPAction value
9470
	* @param    integer $timeout set connection timeout in seconds
9471
	* @param	integer $response_timeout set response timeout in seconds
9472
	* @return	mixed native PHP types.
9473
	* @access   private
9474
	*/
9475
	function send($msg, $soapaction = '', $timeout=0, $response_timeout=30) {
9476
		$this->checkCookies();
9477
		// detect transport
9478
		switch(true){
0 ignored issues
show
Bug Best Practice introduced by
It seems like you are loosely comparing preg_match('/^http/', $this->endpoint) of type integer to the boolean true. If you are specifically checking for non-zero, consider using something more explicit like > 0 or !== 0 instead.
Loading history...
9479
			// http(s)
9480
			case preg_match('/^http/',$this->endpoint):
9481
				$this->debug('transporting via HTTP');
9482
				if($this->persistentConnection == true && is_object($this->persistentConnection)){
0 ignored issues
show
Coding Style Best Practice introduced by
It seems like you are loosely comparing two booleans. Considering using the strict comparison === instead.

When comparing two booleans, it is generally considered safer to use the strict comparison operator.

Loading history...
9483
					$http =& $this->persistentConnection;
9484
				} else {
9485
					$http = new soap_transport_http($this->endpoint, $this->curl_options, $this->use_curl);
9486
					if ($this->persistentConnection) {
9487
						$http->usePersistentConnection();
9488
					}
9489
				}
9490
				$http->setContentType($this->getHTTPContentType(), $this->getHTTPContentTypeCharset());
9491
				$http->setSOAPAction($soapaction);
9492
				if($this->proxyhost && $this->proxyport){
9493
					$http->setProxy($this->proxyhost,$this->proxyport,$this->proxyusername,$this->proxypassword);
9494
				}
9495
                if($this->authtype != '') {
9496
					$http->setCredentials($this->username, $this->password, $this->authtype, array(), $this->certRequest);
9497
				}
9498
				if($this->http_encoding != ''){
9499
					$http->setEncoding($this->http_encoding);
9500
				}
9501
				$this->debug('sending message, length='.strlen($msg));
9502
				if(preg_match('/^http:/',$this->endpoint)){
9503
				//if(strpos($this->endpoint,'http:')){
9504
					$this->responseData = $http->send($msg,$timeout,$response_timeout,$this->cookies);
0 ignored issues
show
Documentation Bug introduced by
It seems like $http->send($msg, $timeo...imeout, $this->cookies) can also be of type false. However, the property $responseData is declared as type string. Maybe add an additional type check?

Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a mixed type is assigned to a property that is type hinted more strictly.

For example, imagine you have a variable $accountId that can either hold an Id object or false (if there is no account id yet). Your code now assigns that value to the id property of an instance of the Account class. This class holds a proper account, so the id value must no longer be false.

Either this assignment is in error or a type check should be added for that assignment.

class Id
{
    public $id;

    public function __construct($id)
    {
        $this->id = $id;
    }

}

class Account
{
    /** @var  Id $id */
    public $id;
}

$account_id = false;

if (starsAreRight()) {
    $account_id = new Id(42);
}

$account = new Account();
if ($account instanceof Id)
{
    $account->id = $account_id;
}
Loading history...
9505
				} elseif(preg_match('/^https/',$this->endpoint)){
9506
				//} elseif(strpos($this->endpoint,'https:')){
9507
					//if(phpversion() == '4.3.0-dev'){
9508
						//$response = $http->send($msg,$timeout,$response_timeout);
9509
                   		//$this->request = $http->outgoing_payload;
9510
						//$this->response = $http->incoming_payload;
9511
					//} else
9512
					$this->responseData = $http->sendHTTPS($msg,$timeout,$response_timeout,$this->cookies);
0 ignored issues
show
Documentation Bug introduced by
It seems like $http->sendHTTPS($msg, $...imeout, $this->cookies) can also be of type false. However, the property $responseData is declared as type string. Maybe add an additional type check?

Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a mixed type is assigned to a property that is type hinted more strictly.

For example, imagine you have a variable $accountId that can either hold an Id object or false (if there is no account id yet). Your code now assigns that value to the id property of an instance of the Account class. This class holds a proper account, so the id value must no longer be false.

Either this assignment is in error or a type check should be added for that assignment.

class Id
{
    public $id;

    public function __construct($id)
    {
        $this->id = $id;
    }

}

class Account
{
    /** @var  Id $id */
    public $id;
}

$account_id = false;

if (starsAreRight()) {
    $account_id = new Id(42);
}

$account = new Account();
if ($account instanceof Id)
{
    $account->id = $account_id;
}
Loading history...
Deprecated Code introduced by
The method soap_transport_http::sendHTTPS() has been deprecated.

This method has been deprecated.

Loading history...
9513
				} else {
9514
					$this->setError('no http/s in endpoint url');
9515
				}
9516
				$this->request = $http->outgoing_payload;
9517
				$this->response = $http->incoming_payload;
9518
				$this->appendDebug($http->getDebug());
9519
				$this->UpdateCookies($http->incoming_cookies);
9520
9521
				// save transport object if using persistent connections
9522
				if ($this->persistentConnection) {
9523
					$http->clearDebug();
9524
					if (!is_object($this->persistentConnection)) {
9525
						$this->persistentConnection = $http;
9526
					}
9527
				}
9528
9529
				if($err = $http->getError()){
9530
					$this->setError('HTTP Error: '.$err);
9531
					return false;
9532
				} elseif($this->getError()){
9533
					return false;
9534
				} else {
9535
					$this->debug('got response, length='. strlen($this->responseData).' type='.$http->incoming_headers['content-type']);
9536
					return $this->parseResponse($http->incoming_headers, $this->responseData);
0 ignored issues
show
It seems like $this->responseData can also be of type false; however, nusoap_client::parseResponse() does only seem to accept string, did you maybe forget to handle an error condition?
Loading history...
9537
				}
9538
			break;
0 ignored issues
show
break; does not seem to be reachable.

This check looks for unreachable code. It uses sophisticated control flow analysis techniques to find statements which will never be executed.

Unreachable code is most often the result of return, die or exit statements that have been added for debug purposes.

function fx() {
    try {
        doSomething();
        return true;
    }
    catch (\Exception $e) {
        return false;
    }

    return false;
}

In the above example, the last return false will never be executed, because a return statement has already been met in every possible execution path.

Loading history...
9539
			default:
9540
				$this->setError('no transport found, or selected transport is not yet supported!');
9541
			return false;
9542
			break;
0 ignored issues
show
break is not strictly necessary here and could be removed.

The break statement is not necessary if it is preceded for example by a return statement:

switch ($x) {
    case 1:
        return 'foo';
        break; // This break is not necessary and can be left off.
}

If you would like to keep this construct to be consistent with other case statements, you can safely mark this issue as a false-positive.

Loading history...
9543
		}
9544
	}
9545
9546
	/**
9547
	* processes SOAP message returned from server
9548
	*
9549
	* @param	array	$headers	The HTTP headers
9550
	* @param	string	$data		unprocessed response data from server
9551
	* @return	mixed	value of the message, decoded into a PHP type
9552
	* @access   private
9553
	*/
9554
    function parseResponse($headers, $data) {
9555
		$this->debug('Entering parseResponse() for data of length ' . strlen($data) . ' headers:');
9556
		$this->appendDebug($this->varDump($headers));
9557
    	if (!isset($headers['content-type'])) {
9558
			$this->setError('Response not of type text/xml (no content-type header)');
9559
			return false;
9560
    	}
9561
		if (!strstr($headers['content-type'], 'text/xml')) {
9562
			$this->setError('Response not of type text/xml: ' . $headers['content-type']);
9563
			return false;
9564
		}
9565
		if (strpos($headers['content-type'], '=')) {
9566
			$enc = str_replace('"', '', substr(strstr($headers["content-type"], '='), 1));
9567
			$this->debug('Got response encoding: ' . $enc);
9568
			if(preg_match('/^(ISO-8859-1|US-ASCII|UTF-8)$/i',$enc)){
9569
				$this->xml_encoding = strtoupper($enc);
9570
			} else {
9571
				$this->xml_encoding = 'US-ASCII';
9572
			}
9573
		} else {
9574
			// should be US-ASCII for HTTP 1.0 or ISO-8859-1 for HTTP 1.1
9575
			$this->xml_encoding = 'ISO-8859-1';
9576
		}
9577
		$this->debug('Use encoding: ' . $this->xml_encoding . ' when creating nusoap_parser');
9578
		$parser = new nusoap_parser($data,$this->xml_encoding,$this->operation,$this->decode_utf8);
9579
		// add parser debug data to our debug
9580
		$this->appendDebug($parser->getDebug());
9581
		// if parse errors
9582
		if($errstr = $parser->getError()){
9583
			$this->setError( $errstr);
9584
			// destroy the parser object
9585
			unset($parser);
9586
			return false;
9587
		} else {
9588
			// get SOAP headers
9589
			$this->responseHeaders = $parser->getHeaders();
9590
			// get SOAP headers
9591
			$this->responseHeader = $parser->get_soapheader();
9592
			// get decoded message
9593
			$return = $parser->get_soapbody();
9594
            // add document for doclit support
9595
            $this->document = $parser->document;
9596
			// destroy the parser object
9597
			unset($parser);
9598
			// return decode message
9599
			return $return;
9600
		}
9601
	 }
9602
9603
	/**
9604
	* sets user-specified cURL options
9605
	*
9606
	* @param	mixed $option The cURL option (always integer?)
9607
	* @param	mixed $value The cURL option value
9608
	* @access   public
9609
	*/
9610
	function setCurlOption($option, $value) {
9611
		$this->debug("setCurlOption option=$option, value=");
9612
		$this->appendDebug($this->varDump($value));
9613
		$this->curl_options[$option] = $value;
9614
	}
9615
9616
	/**
9617
	* sets the SOAP endpoint, which can override WSDL
9618
	*
9619
	* @param	string $endpoint The endpoint URL to use, or empty string or false to prevent override
9620
	* @access   public
9621
	*/
9622
	function setEndpoint($endpoint) {
9623
		$this->debug("setEndpoint(\"$endpoint\")");
9624
		$this->forceEndpoint = $endpoint;
9625
	}
9626
9627
	/**
9628
	* set the SOAP headers
9629
	*
9630
	* @param	mixed $headers String of XML with SOAP header content, or array of soapval objects for SOAP headers
9631
	* @access   public
9632
	*/
9633
	function setHeaders($headers){
9634
		$this->debug("setHeaders headers=");
9635
		$this->appendDebug($this->varDump($headers));
9636
		$this->requestHeaders = $headers;
9637
	}
9638
9639
	/**
9640
	* get the SOAP response headers (namespace resolution incomplete)
9641
	*
9642
	* @return	string
9643
	* @access   public
9644
	*/
9645
	function getHeaders(){
9646
		return $this->responseHeaders;
9647
	}
9648
9649
	/**
9650
	* get the SOAP response Header (parsed)
9651
	*
9652
	* @return	mixed
9653
	* @access   public
9654
	*/
9655
	function getHeader(){
9656
		return $this->responseHeader;
9657
	}
9658
9659
	/**
9660
	* set proxy info here
9661
	*
9662
	* @param    string $proxyhost
9663
	* @param    string $proxyport
9664
	* @param	string $proxyusername
9665
	* @param	string $proxypassword
9666
	* @access   public
9667
	*/
9668
	function setHTTPProxy($proxyhost, $proxyport, $proxyusername = '', $proxypassword = '') {
9669
		$this->proxyhost = $proxyhost;
9670
		$this->proxyport = $proxyport;
9671
		$this->proxyusername = $proxyusername;
9672
		$this->proxypassword = $proxypassword;
9673
	}
9674
9675
	/**
9676
	* if authenticating, set user credentials here
9677
	*
9678
	* @param    string $username
9679
	* @param    string $password
9680
	* @param	string $authtype (basic|digest|certificate|ntlm)
9681
	* @param	array $certRequest (keys must be cainfofile (optional), sslcertfile, sslkeyfile, passphrase, verifypeer (optional), verifyhost (optional): see corresponding options in cURL docs)
9682
	* @access   public
9683
	*/
9684
	function setCredentials($username, $password, $authtype = 'basic', $certRequest = array()) {
9685
		$this->debug("setCredentials username=$username authtype=$authtype certRequest=");
9686
		$this->appendDebug($this->varDump($certRequest));
9687
		$this->username = $username;
9688
		$this->password = $password;
9689
		$this->authtype = $authtype;
9690
		$this->certRequest = $certRequest;
9691
	}
9692
9693
	/**
9694
	* use HTTP encoding
9695
	*
9696
	* @param    string $enc HTTP encoding
9697
	* @access   public
9698
	*/
9699
	function setHTTPEncoding($enc='gzip, deflate'){
9700
		$this->debug("setHTTPEncoding(\"$enc\")");
9701
		$this->http_encoding = $enc;
0 ignored issues
show
Documentation Bug introduced by
The property $http_encoding was declared of type boolean, but $enc is of type string. Maybe add a type cast?

This check looks for assignments to scalar types that may be of the wrong type.

To ensure the code behaves as expected, it may be a good idea to add an explicit type cast.

$answer = 42;

$correct = false;

$correct = (bool) $answer;
Loading history...
9702
	}
9703
9704
	/**
9705
	* Set whether to try to use cURL connections if possible
9706
	*
9707
	* @param	boolean $use Whether to try to use cURL
9708
	* @access   public
9709
	*/
9710
	function setUseCURL($use) {
9711
		$this->debug("setUseCURL($use)");
9712
		$this->use_curl = $use;
9713
	}
9714
9715
	/**
9716
	* use HTTP persistent connections if possible
9717
	*
9718
	* @access   public
9719
	*/
9720
	function useHTTPPersistentConnection(){
9721
		$this->debug("useHTTPPersistentConnection");
9722
		$this->persistentConnection = true;
9723
	}
9724
9725
	/**
9726
	* gets the default RPC parameter setting.
9727
	* If true, default is that call params are like RPC even for document style.
9728
	* Each call() can override this value.
9729
	*
9730
	* This is no longer used.
9731
	*
9732
	* @return boolean
9733
	* @access public
9734
	* @deprecated
9735
	*/
9736
	function getDefaultRpcParams() {
9737
		return $this->defaultRpcParams;
9738
	}
9739
9740
	/**
9741
	* sets the default RPC parameter setting.
9742
	* If true, default is that call params are like RPC even for document style
9743
	* Each call() can override this value.
9744
	*
9745
	* This is no longer used.
9746
	*
9747
	* @param    boolean $rpcParams
9748
	* @access public
9749
	* @deprecated
9750
	*/
9751
	function setDefaultRpcParams($rpcParams) {
9752
		$this->defaultRpcParams = $rpcParams;
9753
	}
9754
9755
	/**
9756
	* dynamically creates an instance of a proxy class,
9757
	* allowing user to directly call methods from wsdl
9758
	*
9759
	* @return   object soap_proxy object
9760
	* @access   public
9761
	*/
9762
	function getProxy() {
9763
		$r = rand();
9764
		$evalStr = $this->_getProxyClassCode($r);
9765
		//$this->debug("proxy class: $evalStr");
9766
		if ($this->getError()) {
9767
			$this->debug("Error from _getProxyClassCode, so return NULL");
9768
			return null;
9769
		}
9770
		// eval the class
9771
		eval($evalStr);
0 ignored issues
show
It is generally not recommended to use eval unless absolutely required.

On one hand, eval might be exploited by malicious users if they somehow manage to inject dynamic content. On the other hand, with the emergence of faster PHP runtimes like the HHVM, eval prevents some optimization that they perform.

Loading history...
9772
		// instantiate proxy object
9773
		eval("\$proxy = new nusoap_proxy_$r('');");
0 ignored issues
show
It is generally not recommended to use eval unless absolutely required.

On one hand, eval might be exploited by malicious users if they somehow manage to inject dynamic content. On the other hand, with the emergence of faster PHP runtimes like the HHVM, eval prevents some optimization that they perform.

Loading history...
9774
		// transfer current wsdl data to the proxy thereby avoiding parsing the wsdl twice
9775
		$proxy->endpointType = 'wsdl';
9776
		$proxy->wsdlFile = $this->wsdlFile;
9777
		$proxy->wsdl = $this->wsdl;
9778
		$proxy->operations = $this->operations;
9779
		$proxy->defaultRpcParams = $this->defaultRpcParams;
9780
		// transfer other state
9781
		$proxy->soap_defencoding = $this->soap_defencoding;
9782
		$proxy->username = $this->username;
9783
		$proxy->password = $this->password;
9784
		$proxy->authtype = $this->authtype;
9785
		$proxy->certRequest = $this->certRequest;
9786
		$proxy->requestHeaders = $this->requestHeaders;
9787
		$proxy->endpoint = $this->endpoint;
9788
		$proxy->forceEndpoint = $this->forceEndpoint;
9789
		$proxy->proxyhost = $this->proxyhost;
9790
		$proxy->proxyport = $this->proxyport;
9791
		$proxy->proxyusername = $this->proxyusername;
9792
		$proxy->proxypassword = $this->proxypassword;
9793
		$proxy->http_encoding = $this->http_encoding;
9794
		$proxy->timeout = $this->timeout;
9795
		$proxy->response_timeout = $this->response_timeout;
9796
		$proxy->persistentConnection = &$this->persistentConnection;
9797
		$proxy->decode_utf8 = $this->decode_utf8;
9798
		$proxy->curl_options = $this->curl_options;
9799
		$proxy->bindingType = $this->bindingType;
9800
		$proxy->use_curl = $this->use_curl;
9801
		return $proxy;
9802
	}
9803
9804
	/**
9805
	* dynamically creates proxy class code
9806
	*
9807
	* @return   string PHP/NuSOAP code for the proxy class
9808
	* @access   private
9809
	*/
9810
	function _getProxyClassCode($r) {
9811
		$this->debug("in getProxy endpointType=$this->endpointType");
9812
		$this->appendDebug("wsdl=" . $this->varDump($this->wsdl));
9813
		if ($this->endpointType != 'wsdl') {
9814
			$evalStr = 'A proxy can only be created for a WSDL client';
9815
			$this->setError($evalStr);
9816
			$evalStr = "echo \"$evalStr\";";
9817
			return $evalStr;
9818
		}
9819
		if ($this->endpointType == 'wsdl' && is_null($this->wsdl)) {
9820
			$this->loadWSDL();
9821
			if ($this->getError()) {
9822
				return "echo \"" . $this->getError() . "\";";
9823
			}
9824
		}
9825
		$evalStr = '';
9826
		foreach ($this->operations as $operation => $opData) {
9827
			if ($operation != '') {
9828
				// create param string and param comment string
9829
				if (sizeof($opData['input']['parts']) > 0) {
9830
					$paramStr = '';
9831
					$paramArrayStr = '';
9832
					$paramCommentStr = '';
9833
					foreach ($opData['input']['parts'] as $name => $type) {
9834
						$paramStr .= "\$$name, ";
9835
						$paramArrayStr .= "'$name' => \$$name, ";
9836
						$paramCommentStr .= "$type \$$name, ";
9837
					}
9838
					$paramStr = substr($paramStr, 0, strlen($paramStr)-2);
9839
					$paramArrayStr = substr($paramArrayStr, 0, strlen($paramArrayStr)-2);
9840
					$paramCommentStr = substr($paramCommentStr, 0, strlen($paramCommentStr)-2);
9841
				} else {
9842
					$paramStr = '';
9843
					$paramArrayStr = '';
9844
					$paramCommentStr = 'void';
9845
				}
9846
				$opData['namespace'] = !isset($opData['namespace']) ? 'http://testuri.com' : $opData['namespace'];
9847
				$evalStr .= "// $paramCommentStr
9848
	function " . str_replace('.', '__', $operation) . "($paramStr) {
9849
		\$params = array($paramArrayStr);
9850
		return \$this->call('$operation', \$params, '".$opData['namespace']."', '".(isset($opData['soapAction']) ? $opData['soapAction'] : '')."');
9851
	}
9852
	";
9853
				unset($paramStr);
9854
				unset($paramCommentStr);
9855
			}
9856
		}
9857
		$evalStr = 'class nusoap_proxy_'.$r.' extends nusoap_client {
9858
	'.$evalStr.'
9859
}';
9860
		return $evalStr;
9861
	}
9862
9863
	/**
9864
	* dynamically creates proxy class code
9865
	*
9866
	* @return   string PHP/NuSOAP code for the proxy class
9867
	* @access   public
9868
	*/
9869
	function getProxyClassCode() {
9870
		$r = rand();
9871
		return $this->_getProxyClassCode($r);
9872
	}
9873
9874
	/**
9875
	* gets the HTTP body for the current request.
9876
	*
9877
	* @param string $soapmsg The SOAP payload
9878
	* @return string The HTTP body, which includes the SOAP payload
9879
	* @access private
9880
	*/
9881
	function getHTTPBody($soapmsg) {
9882
		return $soapmsg;
9883
	}
9884
9885
	/**
9886
	* gets the HTTP content type for the current request.
9887
	*
9888
	* Note: getHTTPBody must be called before this.
9889
	*
9890
	* @return string the HTTP content type for the current request.
9891
	* @access private
9892
	*/
9893
	function getHTTPContentType() {
9894
		return 'text/xml';
9895
	}
9896
9897
	/**
9898
	* gets the HTTP content type charset for the current request.
9899
	* returns false for non-text content types.
9900
	*
9901
	* Note: getHTTPBody must be called before this.
9902
	*
9903
	* @return string the HTTP content type charset for the current request.
9904
	* @access private
9905
	*/
9906
	function getHTTPContentTypeCharset() {
9907
		return $this->soap_defencoding;
9908
	}
9909
9910
	/*
9911
	* whether or not parser should decode utf8 element content
9912
    *
9913
    * @return   always returns true
9914
    * @access   public
9915
    */
9916
    function decodeUTF8($bool){
9917
		$this->decode_utf8 = $bool;
9918
		return true;
9919
    }
9920
9921
	/**
9922
	 * adds a new Cookie into $this->cookies array
9923
	 *
9924
	 * @param	string $name Cookie Name
9925
	 * @param	string $value Cookie Value
9926
	 * @return	boolean if cookie-set was successful returns true, else false
9927
	 * @access	public
9928
	 */
9929
	function setCookie($name, $value) {
9930
		if (strlen($name) == 0) {
9931
			return false;
9932
		}
9933
		$this->cookies[] = array('name' => $name, 'value' => $value);
9934
		return true;
9935
	}
9936
9937
	/**
9938
	 * gets all Cookies
9939
	 *
9940
	 * @return   array with all internal cookies
9941
	 * @access   public
9942
	 */
9943
	function getCookies() {
9944
		return $this->cookies;
9945
	}
9946
9947
	/**
9948
	 * checks all Cookies and delete those which are expired
9949
	 *
9950
	 * @return   boolean always return true
9951
	 * @access   private
9952
	 */
9953
	function checkCookies() {
9954
		if (sizeof($this->cookies) == 0) {
9955
			return true;
9956
		}
9957
		$this->debug('checkCookie: check ' . sizeof($this->cookies) . ' cookies');
9958
		$curr_cookies = $this->cookies;
9959
		$this->cookies = array();
9960
		foreach ($curr_cookies as $cookie) {
9961
			if (! is_array($cookie)) {
9962
				$this->debug('Remove cookie that is not an array');
9963
				continue;
9964
			}
9965
			if ((isset($cookie['expires'])) && (! empty($cookie['expires']))) {
9966
				if (strtotime($cookie['expires']) > time()) {
9967
					$this->cookies[] = $cookie;
9968
				} else {
9969
					$this->debug('Remove expired cookie ' . $cookie['name']);
9970
				}
9971
			} else {
9972
				$this->cookies[] = $cookie;
9973
			}
9974
		}
9975
		$this->debug('checkCookie: '.sizeof($this->cookies).' cookies left in array');
9976
		return true;
9977
	}
9978
9979
	/**
9980
	 * updates the current cookies with a new set
9981
	 *
9982
	 * @param	array $cookies new cookies with which to update current ones
9983
	 * @return	boolean always return true
9984
	 * @access	private
9985
	 */
9986
	function UpdateCookies($cookies) {
9987
		if (sizeof($this->cookies) == 0) {
9988
			// no existing cookies: take whatever is new
9989
			if (sizeof($cookies) > 0) {
9990
				$this->debug('Setting new cookie(s)');
9991
				$this->cookies = $cookies;
9992
			}
9993
			return true;
9994
		}
9995
		if (sizeof($cookies) == 0) {
9996
			// no new cookies: keep what we've got
9997
			return true;
9998
		}
9999
		// merge
10000
		foreach ($cookies as $newCookie) {
10001
			if (!is_array($newCookie)) {
10002
				continue;
10003
			}
10004
			if ((!isset($newCookie['name'])) || (!isset($newCookie['value']))) {
10005
				continue;
10006
			}
10007
			$newName = $newCookie['name'];
10008
10009
			$found = false;
10010
			for ($i = 0; $i < count($this->cookies); $i++) {
0 ignored issues
show
Performance Best Practice introduced by
It seems like you are calling the size function count() as part of the test condition. You might want to compute the size beforehand, and not on each iteration.

If the size of the collection does not change during the iteration, it is generally a good practice to compute it beforehand, and not on each iteration:

for ($i=0; $i<count($array); $i++) { // calls count() on each iteration
}

// Better
for ($i=0, $c=count($array); $i<$c; $i++) { // calls count() just once
}
Loading history...
10011
				$cookie = $this->cookies[$i];
10012
				if (!is_array($cookie)) {
10013
					continue;
10014
				}
10015
				if (!isset($cookie['name'])) {
10016
					continue;
10017
				}
10018
				if ($newName != $cookie['name']) {
10019
					continue;
10020
				}
10021
				$newDomain = isset($newCookie['domain']) ? $newCookie['domain'] : 'NODOMAIN';
10022
				$domain = isset($cookie['domain']) ? $cookie['domain'] : 'NODOMAIN';
10023
				if ($newDomain != $domain) {
10024
					continue;
10025
				}
10026
				$newPath = isset($newCookie['path']) ? $newCookie['path'] : 'NOPATH';
10027
				$path = isset($cookie['path']) ? $cookie['path'] : 'NOPATH';
10028
				if ($newPath != $path) {
10029
					continue;
10030
				}
10031
				$this->cookies[$i] = $newCookie;
10032
				$found = true;
10033
				$this->debug('Update cookie ' . $newName . '=' . $newCookie['value']);
10034
				break;
10035
			}
10036
			if (! $found) {
10037
				$this->debug('Add cookie ' . $newName . '=' . $newCookie['value']);
10038
				$this->cookies[] = $newCookie;
10039
			}
10040
		}
10041
		return true;
10042
	}
10043
}
10044
10045
if (!extension_loaded('soap')) {
10046
	/**
10047
	 *	For backwards compatiblity, define soapclient unless the PHP SOAP extension is loaded.
10048
	 */
10049
	class soapclient extends nusoap_client {
0 ignored issues
show
Comprehensibility Best Practice introduced by
The type soapclient has been defined more than once; this definition is ignored, only the first definition in include/nusoap/class.soapclient.php (L1137-1138) is considered.

This check looks for classes that have been defined more than once.

If you can, we would recommend to use standard object-oriented programming techniques. For example, to avoid multiple types, it might make sense to create a common interface, and then multiple, different implementations for that interface.

This also has the side-effect of providing you with better IDE auto-completion, static analysis and also better OPCode caching from PHP.

Loading history...
Coding Style Compatibility introduced by
PSR1 recommends that each class should be in its own file to aid autoloaders.

Having each class in a dedicated file usually plays nice with PSR autoloaders and is therefore a well established practice. If you use other autoloaders, you might not want to follow this rule.

Loading history...
10050
	}
10051
}
10052
10053
class nusoapclient extends nusoap_client
0 ignored issues
show
Comprehensibility Best Practice introduced by
The type nusoapclient has been defined more than once; this definition is ignored, only the first definition in include/nusoap/class.soapclient.php (L1144-1145) is considered.

This check looks for classes that have been defined more than once.

If you can, we would recommend to use standard object-oriented programming techniques. For example, to avoid multiple types, it might make sense to create a common interface, and then multiple, different implementations for that interface.

This also has the side-effect of providing you with better IDE auto-completion, static analysis and also better OPCode caching from PHP.

Loading history...
Coding Style Compatibility introduced by
PSR1 recommends that each class should be in its own file to aid autoloaders.

Having each class in a dedicated file usually plays nice with PSR autoloaders and is therefore a well established practice. If you use other autoloaders, you might not want to follow this rule.

Loading history...
10054
{
10055
}
10056
?>
10057