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/class.soap_parser.php (6 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
5
Modification information for LGPL compliance
6
7
r57813 - 2010-08-19 10:34:44 -0700 (Thu, 19 Aug 2010) - kjing - Author: John Mertic <[email protected]>
8
    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.
9
10
r56990 - 2010-06-16 13:05:36 -0700 (Wed, 16 Jun 2010) - kjing - snapshot "Mango" svn branch to a new one for GitHub sync
11
12
r56989 - 2010-06-16 13:01:33 -0700 (Wed, 16 Jun 2010) - kjing - defunt "Mango" svn dev branch before github cutover
13
14
r55980 - 2010-04-19 13:31:28 -0700 (Mon, 19 Apr 2010) - kjing - create Mango (6.1) based on windex
15
16
r51719 - 2009-10-22 10:18:00 -0700 (Thu, 22 Oct 2009) - mitani - Converted to Build 3  tags and updated the build system 
17
18
r51634 - 2009-10-19 13:32:22 -0700 (Mon, 19 Oct 2009) - mitani - Windex is the branch for Sugar Sales 1.0 development
19
20
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:
21
- Changing all ereg function to either preg or simple string based ones
22
- No more references to magic quotes.
23
- Change all the session_unregister() functions to just unset() the correct session variable instead.
24
25
r50375 - 2009-08-24 18:07:43 -0700 (Mon, 24 Aug 2009) - dwong - branch kobe2 from tokyo r50372
26
27
r42807 - 2008-12-29 11:16:59 -0800 (Mon, 29 Dec 2008) - dwong - Branch from trunk/sugarcrm r42806 to branches/tokyo/sugarcrm
28
29
r13782 - 2006-06-06 10:58:55 -0700 (Tue, 06 Jun 2006) - majed - changes entry point code
30
31
r11115 - 2006-01-17 14:54:45 -0800 (Tue, 17 Jan 2006) - majed - add entry point validation
32
33
r8846 - 2005-10-31 11:01:12 -0800 (Mon, 31 Oct 2005) - majed - new version of nusoap
34
35
r7905 - 2005-09-21 19:12:57 -0700 (Wed, 21 Sep 2005) - majed - restores old nusoap pre & with a few fixes
36
37
r7861 - 2005-09-20 15:40:25 -0700 (Tue, 20 Sep 2005) - majed - & fix for 3.5.1
38
39
r5462 - 2005-05-25 13:50:11 -0700 (Wed, 25 May 2005) - majed - upgraded nusoap to .6.9
40
41
r573 - 2004-09-04 13:03:32 -0700 (Sat, 04 Sep 2004) - sugarclint - undoing copyrights added in inadvertantly.  --clint
42
43
r546 - 2004-09-03 11:49:38 -0700 (Fri, 03 Sep 2004) - sugarmsi - removed echo count
44
45
r354 - 2004-08-02 23:00:37 -0700 (Mon, 02 Aug 2004) - sugarjacob - Adding Soap
46
47
48
*/
49
50
51
if(!defined('sugarEntry') || !sugarEntry) die('Not A Valid Entry Point');
52
53
54
55
56
/**
57
*
58
* nusoap_parser class parses SOAP XML messages into native PHP values
59
*
60
* @author   Dietrich Ayala <[email protected]>
61
* @author   Scott Nichol <[email protected]>
62
63
* @access   public
64
*/
65
class nusoap_parser extends nusoap_base {
66
67
	var $xml = '';
68
	var $xml_encoding = '';
69
	var $method = '';
70
	var $root_struct = '';
71
	var $root_struct_name = '';
72
	var $root_struct_namespace = '';
73
	var $root_header = '';
74
    var $document = '';			// incoming SOAP body (text)
75
	// determines where in the message we are (envelope,header,body,method)
76
	var $status = '';
77
	var $position = 0;
78
	var $depth = 0;
79
	var $default_namespace = '';
80
	var $namespaces = array();
81
	var $message = array();
82
    var $parent = '';
83
	var $fault = false;
84
	var $fault_code = '';
85
	var $fault_str = '';
86
	var $fault_detail = '';
87
	var $depth_array = array();
88
	var $debug_flag = true;
89
	var $soapresponse = NULL;	// parsed SOAP Body
90
	var $soapheader = NULL;		// parsed SOAP Header
91
	var $responseHeaders = '';	// incoming SOAP headers (text)
92
	var $body_position = 0;
93
	// for multiref parsing:
94
	// array of id => pos
95
	var $ids = array();
96
	// array of id => hrefs => pos
97
	var $multirefs = array();
98
	// toggle for auto-decoding element content
99
	var $decode_utf8 = true;
100
101
	/**
102
	* constructor that actually does the parsing
103
	*
104
	* @param    string $xml SOAP message
105
	* @param    string $encoding character encoding scheme of message
106
	* @param    string $method method for which XML is parsed (unused?)
107
	* @param    string $decode_utf8 whether to decode UTF-8 to ISO-8859-1
108
	* @access   public
109
	*/
110
	function nusoap_parser($xml,$encoding='UTF-8',$method='',$decode_utf8=true){
111
		parent::nusoap_base();
112
		$this->xml = $xml;
113
		$this->xml_encoding = $encoding;
114
		$this->method = $method;
115
		$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...
116
117
		// Check whether content has been read.
118
		if(!empty($xml)){
119
			// Check XML encoding
120
			$pos_xml = strpos($xml, '<?xml');
121
			if ($pos_xml !== FALSE) {
122
				$xml_decl = substr($xml, $pos_xml, strpos($xml, '?>', $pos_xml + 2) - $pos_xml + 1);
123
				if (preg_match("/encoding=[\"']([^\"']*)[\"']/", $xml_decl, $res)) {
124
					$xml_encoding = $res[1];
125
					if (strtoupper($xml_encoding) != $encoding) {
126
						$err = "Charset from HTTP Content-Type '" . $encoding . "' does not match encoding from XML declaration '" . $xml_encoding . "'";
127
						$this->debug($err);
128
						if ($encoding != 'ISO-8859-1' || strtoupper($xml_encoding) != 'UTF-8') {
129
							$this->setError($err);
130
							return;
131
						}
132
						// when HTTP says ISO-8859-1 (the default) and XML says UTF-8 (the typical), assume the other endpoint is just sloppy and proceed
133
					} else {
134
						$this->debug('Charset from HTTP Content-Type matches encoding from XML declaration');
135
					}
136
				} else {
137
					$this->debug('No encoding specified in XML declaration');
138
				}
139
			} else {
140
				$this->debug('No XML declaration');
141
			}
142
			$this->debug('Entering nusoap_parser(), length='.strlen($xml).', encoding='.$encoding);
143
			// Create an XML parser - why not xml_parser_create_ns?
144
			$this->parser = xml_parser_create($this->xml_encoding);
145
			// Set the options for parsing the XML data.
146
			//xml_parser_set_option($parser, XML_OPTION_SKIP_WHITE, 1);
147
			xml_parser_set_option($this->parser, XML_OPTION_CASE_FOLDING, 0);
148
			xml_parser_set_option($this->parser, XML_OPTION_TARGET_ENCODING, $this->xml_encoding);
149
			// Set the object for the parser.
150
			xml_set_object($this->parser, $this);
151
			// Set the element handlers for the parser.
152
			xml_set_element_handler($this->parser, 'start_element','end_element');
153
			xml_set_character_data_handler($this->parser,'character_data');
154
155
			// Parse the XML file.
156
			if(!xml_parse($this->parser,$xml,true)){
157
			    // Display an error message.
158
			    $err = sprintf('XML error parsing SOAP payload on line %d: %s',
159
			    xml_get_current_line_number($this->parser),
160
			    xml_error_string(xml_get_error_code($this->parser)));
161
				$this->debug($err);
162
				$this->debug("XML payload:\n" . $xml);
163
				$this->setError($err);
164
			} else {
165
				$this->debug('in nusoap_parser ctor, message:');
166
				$this->appendDebug($this->varDump($this->message));
167
				$this->debug('parsed successfully, found root struct: '.$this->root_struct.' of name '.$this->root_struct_name);
168
				// get final value
169
				$this->soapresponse = $this->message[$this->root_struct]['result'];
170
				// get header value
171
				if($this->root_header != '' && isset($this->message[$this->root_header]['result'])){
172
					$this->soapheader = $this->message[$this->root_header]['result'];
173
				}
174
				// resolve hrefs/ids
175
				if(sizeof($this->multirefs) > 0){
176
					foreach($this->multirefs as $id => $hrefs){
177
						$this->debug('resolving multirefs for id: '.$id);
178
						$idVal = $this->buildVal($this->ids[$id]);
179
						if (is_array($idVal) && isset($idVal['!id'])) {
180
							unset($idVal['!id']);
181
						}
182
						foreach($hrefs as $refPos => $ref){
183
							$this->debug('resolving href at pos '.$refPos);
184
							$this->multirefs[$id][$refPos] = $idVal;
185
						}
186
					}
187
				}
188
			}
189
			xml_parser_free($this->parser);
190
		} else {
191
			$this->debug('xml was empty, didn\'t parse!');
192
			$this->setError('xml was empty, didn\'t parse!');
193
		}
194
	}
195
196
	/**
197
	* start-element handler
198
	*
199
	* @param    resource $parser XML parser object
200
	* @param    string $name element name
201
	* @param    array $attrs associative array of attributes
202
	* @access   private
203
	*/
204
	function start_element($parser, $name, $attrs) {
205
		// position in a total number of elements, starting from 0
206
		// update class level pos
207
		$pos = $this->position++;
208
		// and set mine
209
		$this->message[$pos] = array('pos' => $pos,'children'=>'','cdata'=>'');
210
		// depth = how many levels removed from root?
211
		// set mine as current global depth and increment global depth value
212
		$this->message[$pos]['depth'] = $this->depth++;
213
214
		// else add self as child to whoever the current parent is
215
		if($pos != 0){
216
			$this->message[$this->parent]['children'] .= '|'.$pos;
217
		}
218
		// set my parent
219
		$this->message[$pos]['parent'] = $this->parent;
220
		// set self as current parent
221
		$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...
222
		// set self as current value for this depth
223
		$this->depth_array[$this->depth] = $pos;
224
		// get element prefix
225
		if(strpos($name,':')){
226
			// get ns prefix
227
			$prefix = substr($name,0,strpos($name,':'));
228
			// get unqualified name
229
			$name = substr(strstr($name,':'),1);
230
		}
231
		// set status
232
		if ($name == 'Envelope' && $this->status == '') {
233
			$this->status = 'envelope';
234
		} elseif ($name == 'Header' && $this->status == 'envelope') {
235
			$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...
236
			$this->status = 'header';
237
		} elseif ($name == 'Body' && $this->status == 'envelope'){
238
			$this->status = 'body';
239
			$this->body_position = $pos;
240
		// set method
241
		} elseif($this->status == 'body' && $pos == ($this->body_position+1)) {
242
			$this->status = 'method';
243
			$this->root_struct_name = $name;
244
			$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...
245
			$this->message[$pos]['type'] = 'struct';
246
			$this->debug("found root struct $this->root_struct_name, pos $this->root_struct");
247
		}
248
		// set my status
249
		$this->message[$pos]['status'] = $this->status;
250
		// set name
251
		$this->message[$pos]['name'] = htmlspecialchars($name);
252
		// set attrs
253
		$this->message[$pos]['attrs'] = $attrs;
254
255
		// loop through atts, logging ns and type declarations
256
        $attstr = '';
257
		foreach($attrs as $key => $value){
258
        	$key_prefix = $this->getPrefix($key);
259
			$key_localpart = $this->getLocalPart($key);
260
			// if ns declarations, add to class level array of valid namespaces
261
            if($key_prefix == 'xmlns'){
262
				if(preg_match('/^http:\/\/www.w3.org\/[0-9]{4}\/XMLSchema$/',$value)){
263
					$this->XMLSchemaVersion = $value;
264
					$this->namespaces['xsd'] = $this->XMLSchemaVersion;
265
					$this->namespaces['xsi'] = $this->XMLSchemaVersion.'-instance';
266
				}
267
                $this->namespaces[$key_localpart] = $value;
268
				// set method namespace
269
				if($name == $this->root_struct_name){
270
					$this->methodNamespace = $value;
271
				}
272
			// if it's a type declaration, set type
273
        } elseif($key_localpart == 'type'){
274
        		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...
275
        			// do nothing: already processed arrayType
276
        		} else {
277
	            	$value_prefix = $this->getPrefix($value);
278
	                $value_localpart = $this->getLocalPart($value);
279
					$this->message[$pos]['type'] = $value_localpart;
280
					$this->message[$pos]['typePrefix'] = $value_prefix;
281
	                if(isset($this->namespaces[$value_prefix])){
282
	                	$this->message[$pos]['type_namespace'] = $this->namespaces[$value_prefix];
283
	                } else if(isset($attrs['xmlns:'.$value_prefix])) {
284
						$this->message[$pos]['type_namespace'] = $attrs['xmlns:'.$value_prefix];
285
	                }
286
					// should do something here with the namespace of specified type?
287
				}
288
			} elseif($key_localpart == 'arrayType'){
289
				$this->message[$pos]['type'] = 'array';
290
				/* do arrayType ereg here
291
				[1]    arrayTypeValue    ::=    atype asize
292
				[2]    atype    ::=    QName rank*
293
				[3]    rank    ::=    '[' (',')* ']'
294
				[4]    asize    ::=    '[' length~ ']'
295
				[5]    length    ::=    nextDimension* Digit+
296
				[6]    nextDimension    ::=    Digit+ ','
297
				*/
298
				$expr = '/([A-Za-z0-9_]+):([A-Za-z]+[A-Za-z0-9_]+)\[([0-9]+),?([0-9]*)\]/';
299
				if(preg_match($expr,$value,$regs)){
300
					$this->message[$pos]['typePrefix'] = $regs[1];
301
					$this->message[$pos]['arrayTypePrefix'] = $regs[1];
302
	                if (isset($this->namespaces[$regs[1]])) {
303
	                	$this->message[$pos]['arrayTypeNamespace'] = $this->namespaces[$regs[1]];
304
	                } else if (isset($attrs['xmlns:'.$regs[1]])) {
305
						$this->message[$pos]['arrayTypeNamespace'] = $attrs['xmlns:'.$regs[1]];
306
	                }
307
					$this->message[$pos]['arrayType'] = $regs[2];
308
					$this->message[$pos]['arraySize'] = $regs[3];
309
					$this->message[$pos]['arrayCols'] = $regs[4];
310
				}
311
			// specifies nil value (or not)
312
			} elseif ($key_localpart == 'nil'){
313
				$this->message[$pos]['nil'] = ($value == 'true' || $value == '1');
314
			// some other attribute
315
			} elseif ($key != 'href' && $key != 'xmlns' && $key_localpart != 'encodingStyle' && $key_localpart != 'root') {
316
				$this->message[$pos]['xattrs']['!' . $key] = $value;
317
			}
318
319
			if ($key == 'xmlns') {
320
				$this->default_namespace = $value;
321
			}
322
			// log id
323
			if($key == 'id'){
324
				$this->ids[$value] = $pos;
325
			}
326
			// root
327
			if($key_localpart == 'root' && $value == 1){
328
				$this->status = 'method';
329
				$this->root_struct_name = $name;
330
				$this->root_struct = $pos;
331
				$this->debug("found root struct $this->root_struct_name, pos $pos");
332
			}
333
            // for doclit
334
            $attstr .= " $key=\"$value\"";
335
		}
336
        // get namespace - must be done after namespace atts are processed
337
		if(isset($prefix)){
338
			$this->message[$pos]['namespace'] = $this->namespaces[$prefix];
339
			$this->default_namespace = $this->namespaces[$prefix];
340
		} else {
341
			$this->message[$pos]['namespace'] = $this->default_namespace;
342
		}
343
        if($this->status == 'header'){
344
        	if ($this->root_header != $pos) {
345
	        	$this->responseHeaders .= "<" . (isset($prefix) ? $prefix . ':' : '') . "$name$attstr>";
346
	        }
347
        } elseif($this->root_struct_name != ''){
348
        	$this->document .= "<" . (isset($prefix) ? $prefix . ':' : '') . "$name$attstr>";
349
        }
350
	}
351
352
	/**
353
	* end-element handler
354
	*
355
	* @param    resource $parser XML parser object
356
	* @param    string $name element name
357
	* @access   private
358
	*/
359
	function end_element($parser, $name) {
360
		// position of current element is equal to the last value left in depth_array for my depth
361
		$pos = $this->depth_array[$this->depth--];
362
363
        // get element prefix
364
		if(strpos($name,':')){
365
			// get ns prefix
366
			$prefix = substr($name,0,strpos($name,':'));
367
			// get unqualified name
368
			$name = substr(strstr($name,':'),1);
369
		}
370
		
371
		// build to native type
372
		if(isset($this->body_position) && $pos > $this->body_position){
373
			// deal w/ multirefs
374
			if(isset($this->message[$pos]['attrs']['href'])){
375
				// get id
376
				$id = substr($this->message[$pos]['attrs']['href'],1);
377
				// add placeholder to href array
378
				$this->multirefs[$id][$pos] = 'placeholder';
379
				// add set a reference to it as the result value
380
				$this->message[$pos]['result'] =& $this->multirefs[$id][$pos];
381
            // build complexType values
382
			} elseif($this->message[$pos]['children'] != ''){
383
				// if result has already been generated (struct/array)
384
				if(!isset($this->message[$pos]['result'])){
385
					$this->message[$pos]['result'] = $this->buildVal($pos);
386
				}
387
			// build complexType values of attributes and possibly simpleContent
388
			} elseif (isset($this->message[$pos]['xattrs'])) {
389
				if (isset($this->message[$pos]['nil']) && $this->message[$pos]['nil']) {
390
					$this->message[$pos]['xattrs']['!'] = null;
391
				} elseif (isset($this->message[$pos]['cdata']) && trim($this->message[$pos]['cdata']) != '') {
392
	            	if (isset($this->message[$pos]['type'])) {
393
						$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'] : '');
394
					} else {
395
						$parent = $this->message[$pos]['parent'];
396
						if (isset($this->message[$parent]['type']) && ($this->message[$parent]['type'] == 'array') && isset($this->message[$parent]['arrayType'])) {
397
							$this->message[$pos]['xattrs']['!'] = $this->decodeSimple($this->message[$pos]['cdata'], $this->message[$parent]['arrayType'], isset($this->message[$parent]['arrayTypeNamespace']) ? $this->message[$parent]['arrayTypeNamespace'] : '');
398
						} else {
399
							$this->message[$pos]['xattrs']['!'] = $this->message[$pos]['cdata'];
400
						}
401
					}
402
				}
403
				$this->message[$pos]['result'] = $this->message[$pos]['xattrs'];
404
			// set value of simpleType (or nil complexType)
405
			} else {
406
            	//$this->debug('adding data for scalar value '.$this->message[$pos]['name'].' of value '.$this->message[$pos]['cdata']);
407
				if (isset($this->message[$pos]['nil']) && $this->message[$pos]['nil']) {
408
					$this->message[$pos]['xattrs']['!'] = null;
409
				} elseif (isset($this->message[$pos]['type'])) {
410
					$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'] : '');
411
				} else {
412
					$parent = $this->message[$pos]['parent'];
413
					if (isset($this->message[$parent]['type']) && ($this->message[$parent]['type'] == 'array') && isset($this->message[$parent]['arrayType'])) {
414
						$this->message[$pos]['result'] = $this->decodeSimple($this->message[$pos]['cdata'], $this->message[$parent]['arrayType'], isset($this->message[$parent]['arrayTypeNamespace']) ? $this->message[$parent]['arrayTypeNamespace'] : '');
415
					} else {
416
						$this->message[$pos]['result'] = $this->message[$pos]['cdata'];
417
					}
418
				}
419
420
				/* add value to parent's result, if parent is struct/array
421
				$parent = $this->message[$pos]['parent'];
422
				if($this->message[$parent]['type'] != 'map'){
423
					if(strtolower($this->message[$parent]['type']) == 'array'){
424
						$this->message[$parent]['result'][] = $this->message[$pos]['result'];
425
					} else {
426
						$this->message[$parent]['result'][$this->message[$pos]['name']] = $this->message[$pos]['result'];
427
					}
428
				}
429
				*/
430
			}
431
		}
432
		
433
        // for doclit
434
        if($this->status == 'header'){
435
        	if ($this->root_header != $pos) {
436
	        	$this->responseHeaders .= "</" . (isset($prefix) ? $prefix . ':' : '') . "$name>";
437
	        }
438
        } elseif($pos >= $this->root_struct){
439
        	$this->document .= "</" . (isset($prefix) ? $prefix . ':' : '') . "$name>";
440
        }
441
		// switch status
442
		if ($pos == $this->root_struct){
443
			$this->status = 'body';
444
			$this->root_struct_namespace = $this->message[$pos]['namespace'];
445
		} elseif ($pos == $this->root_header) {
446
			$this->status = 'envelope';
447
		} elseif ($name == 'Body' && $this->status == 'body') {
448
			$this->status = 'envelope';
449
		} elseif ($name == 'Header' && $this->status == 'header') { // will never happen
450
			$this->status = 'envelope';
451
		} elseif ($name == 'Envelope' && $this->status == 'envelope') {
452
			$this->status = '';
453
		}
454
		// set parent back to my parent
455
		$this->parent = $this->message[$pos]['parent'];
456
	}
457
458
	/**
459
	* element content handler
460
	*
461
	* @param    resource $parser XML parser object
462
	* @param    string $data element content
463
	* @access   private
464
	*/
465
	function character_data($parser, $data){
466
		$pos = $this->depth_array[$this->depth];
467
		if ($this->xml_encoding=='UTF-8'){
468
			// TODO: add an option to disable this for folks who want
469
			// raw UTF-8 that, e.g., might not map to iso-8859-1
470
			// TODO: this can also be handled with xml_parser_set_option($this->parser, XML_OPTION_TARGET_ENCODING, "ISO-8859-1");
471
			if($this->decode_utf8){
472
				$data = utf8_decode($data);
473
			}
474
		}
475
        $this->message[$pos]['cdata'] .= $data;
476
        // for doclit
477
        if($this->status == 'header'){
478
        	$this->responseHeaders .= $data;
479
        } else {
480
        	$this->document .= $data;
481
        }
482
	}
483
484
	/**
485
	* get the parsed message (SOAP Body)
486
	*
487
	* @return	mixed
488
	* @access   public
489
	* @deprecated	use get_soapbody instead
490
	*/
491
	function get_response(){
492
		return $this->soapresponse;
493
	}
494
495
	/**
496
	* get the parsed SOAP Body (NULL if there was none)
497
	*
498
	* @return	mixed
499
	* @access   public
500
	*/
501
	function get_soapbody(){
502
		return $this->soapresponse;
503
	}
504
505
	/**
506
	* get the parsed SOAP Header (NULL if there was none)
507
	*
508
	* @return	mixed
509
	* @access   public
510
	*/
511
	function get_soapheader(){
512
		return $this->soapheader;
513
	}
514
515
	/**
516
	* get the unparsed SOAP Header
517
	*
518
	* @return	string XML or empty if no Header
519
	* @access   public
520
	*/
521
	function getHeaders(){
522
	    return $this->responseHeaders;
523
	}
524
525
	/**
526
	* decodes simple types into PHP variables
527
	*
528
	* @param    string $value value to decode
529
	* @param    string $type XML type to decode
530
	* @param    string $typens XML type namespace to decode
531
	* @return	mixed PHP value
532
	* @access   private
533
	*/
534
	function decodeSimple($value, $type, $typens) {
535
		// TODO: use the namespace!
536
		if ((!isset($type)) || $type == 'string' || $type == 'long' || $type == 'unsignedLong') {
537
			return (string) $value;
538
		}
539
		if ($type == 'int' || $type == 'integer' || $type == 'short' || $type == 'byte') {
540
			return (int) $value;
541
		}
542
		if ($type == 'float' || $type == 'double' || $type == 'decimal') {
543
			return (double) $value;
544
		}
545
		if ($type == 'boolean') {
546
			if (strtolower($value) == 'false' || strtolower($value) == 'f') {
547
				return false;
548
			}
549
			return (boolean) $value;
550
		}
551
		if ($type == 'base64' || $type == 'base64Binary') {
552
			$this->debug('Decode base64 value');
553
			return base64_decode($value);
554
		}
555
		// obscure numeric types
556
		if ($type == 'nonPositiveInteger' || $type == 'negativeInteger'
557
			|| $type == 'nonNegativeInteger' || $type == 'positiveInteger'
558
			|| $type == 'unsignedInt'
559
			|| $type == 'unsignedShort' || $type == 'unsignedByte') {
560
			return (int) $value;
561
		}
562
		// bogus: parser treats array with no elements as a simple type
563
		if ($type == 'array') {
564
			return array();
565
		}
566
		// everything else
567
		return (string) $value;
568
	}
569
570
	/**
571
	* builds response structures for compound values (arrays/structs)
572
	* and scalars
573
	*
574
	* @param    integer $pos position in node tree
575
	* @return	mixed	PHP value
576
	* @access   private
577
	*/
578
	function buildVal($pos){
579
		if(!isset($this->message[$pos]['type'])){
580
			$this->message[$pos]['type'] = '';
581
		}
582
		$this->debug('in buildVal() for '.$this->message[$pos]['name']."(pos $pos) of type ".$this->message[$pos]['type']);
583
		// if there are children...
584
		if($this->message[$pos]['children'] != ''){
585
			$this->debug('in buildVal, there are children');
586
			$children = explode('|',$this->message[$pos]['children']);
587
			array_shift($children); // knock off empty
588
			// md array
589
			if(isset($this->message[$pos]['arrayCols']) && $this->message[$pos]['arrayCols'] != ''){
590
            	$r=0; // rowcount
591
            	$c=0; // colcount
592
            	foreach($children as $child_pos){
593
					$this->debug("in buildVal, got an MD array element: $r, $c");
594
					$params[$r][] = $this->message[$child_pos]['result'];
595
				    $c++;
596
				    if($c == $this->message[$pos]['arrayCols']){
597
				    	$c = 0;
598
						$r++;
599
				    }
600
                }
601
            // array
602
			} elseif($this->message[$pos]['type'] == 'array' || $this->message[$pos]['type'] == 'Array'){
603
                $this->debug('in buildVal, adding array '.$this->message[$pos]['name']);
604
                foreach($children as $child_pos){
605
                	$params[] = &$this->message[$child_pos]['result'];
606
                }
607
            // apache Map type: java hashtable
608
            } elseif($this->message[$pos]['type'] == 'Map' && $this->message[$pos]['type_namespace'] == 'http://xml.apache.org/xml-soap'){
609
                $this->debug('in buildVal, Java Map '.$this->message[$pos]['name']);
610
                foreach($children as $child_pos){
611
                	$kv = explode("|",$this->message[$child_pos]['children']);
612
                   	$params[$this->message[$kv[1]]['result']] = &$this->message[$kv[2]]['result'];
613
                }
614
            // generic compound type
615
            //} elseif($this->message[$pos]['type'] == 'SOAPStruct' || $this->message[$pos]['type'] == 'struct') {
616
		    } else {
617
	    		// Apache Vector type: treat as an array
618
                $this->debug('in buildVal, adding Java Vector or generic compound type '.$this->message[$pos]['name']);
619
				if ($this->message[$pos]['type'] == 'Vector' && $this->message[$pos]['type_namespace'] == 'http://xml.apache.org/xml-soap') {
620
					$notstruct = 1;
621
				} else {
622
					$notstruct = 0;
623
	            }
624
            	//
625
            	foreach($children as $child_pos){
626
            		if($notstruct){
627
            			$params[] = &$this->message[$child_pos]['result'];
628
            		} else {
629
            			if (isset($params[$this->message[$child_pos]['name']])) {
630
            				// de-serialize repeated element name into an array
631
            				if ((!is_array($params[$this->message[$child_pos]['name']])) || (!isset($params[$this->message[$child_pos]['name']][0]))) {
632
            					$params[$this->message[$child_pos]['name']] = array($params[$this->message[$child_pos]['name']]);
633
            				}
634
            				$params[$this->message[$child_pos]['name']][] = &$this->message[$child_pos]['result'];
635
            			} else {
636
					    	$params[$this->message[$child_pos]['name']] = &$this->message[$child_pos]['result'];
637
					    }
638
                	}
639
                }
640
			}
641
			if (isset($this->message[$pos]['xattrs'])) {
642
                $this->debug('in buildVal, handling attributes');
643
				foreach ($this->message[$pos]['xattrs'] as $n => $v) {
644
					$params[$n] = $v;
645
				}
646
			}
647
			// handle simpleContent
648
			if (isset($this->message[$pos]['cdata']) && trim($this->message[$pos]['cdata']) != '') {
649
                $this->debug('in buildVal, handling simpleContent');
650
            	if (isset($this->message[$pos]['type'])) {
651
					$params['!'] = $this->decodeSimple($this->message[$pos]['cdata'], $this->message[$pos]['type'], isset($this->message[$pos]['type_namespace']) ? $this->message[$pos]['type_namespace'] : '');
652
				} else {
653
					$parent = $this->message[$pos]['parent'];
654
					if (isset($this->message[$parent]['type']) && ($this->message[$parent]['type'] == 'array') && isset($this->message[$parent]['arrayType'])) {
655
						$params['!'] = $this->decodeSimple($this->message[$pos]['cdata'], $this->message[$parent]['arrayType'], isset($this->message[$parent]['arrayTypeNamespace']) ? $this->message[$parent]['arrayTypeNamespace'] : '');
656
					} else {
657
						$params['!'] = $this->message[$pos]['cdata'];
658
					}
659
				}
660
			}
661
			$ret = is_array($params) ? $params : array();
662
			$this->debug('in buildVal, return:');
663
			$this->appendDebug($this->varDump($ret));
664
			return $ret;
665
		} else {
666
        	$this->debug('in buildVal, no children, building scalar');
667
			$cdata = isset($this->message[$pos]['cdata']) ? $this->message[$pos]['cdata'] : '';
668
        	if (isset($this->message[$pos]['type'])) {
669
				$ret = $this->decodeSimple($cdata, $this->message[$pos]['type'], isset($this->message[$pos]['type_namespace']) ? $this->message[$pos]['type_namespace'] : '');
670
				$this->debug("in buildVal, return: $ret");
671
				return $ret;
672
			}
673
			$parent = $this->message[$pos]['parent'];
674
			if (isset($this->message[$parent]['type']) && ($this->message[$parent]['type'] == 'array') && isset($this->message[$parent]['arrayType'])) {
675
				$ret = $this->decodeSimple($cdata, $this->message[$parent]['arrayType'], isset($this->message[$parent]['arrayTypeNamespace']) ? $this->message[$parent]['arrayTypeNamespace'] : '');
676
				$this->debug("in buildVal, return: $ret");
677
				return $ret;
678
			}
679
           	$ret = $this->message[$pos]['cdata'];
680
			$this->debug("in buildVal, return: $ret");
681
           	return $ret;
682
		}
683
	}
684
}
685
686
/**
687
 * Backward compatibility
688
 */
689
class soap_parser extends nusoap_parser {
0 ignored issues
show
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...
690
}
691
692
693
?>