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.xmlschema.php (5 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
r5462 - 2005-05-25 13:50:11 -0700 (Wed, 25 May 2005) - majed - upgraded nusoap to .6.9
36
37
r573 - 2004-09-04 13:03:32 -0700 (Sat, 04 Sep 2004) - sugarclint - undoing copyrights added in inadvertantly.  --clint
38
39
r546 - 2004-09-03 11:49:38 -0700 (Fri, 03 Sep 2004) - sugarmsi - removed echo count
40
41
r354 - 2004-08-02 23:00:37 -0700 (Mon, 02 Aug 2004) - sugarjacob - Adding Soap
42
43
44
*/
45
46
47
if(!defined('sugarEntry') || !sugarEntry) die('Not A Valid Entry Point');
48
49
50
51
52
/**
53
* parses an XML Schema, allows access to it's data, other utility methods.
54
* imperfect, no validation... yet, but quite functional.
55
*
56
* @author   Dietrich Ayala <[email protected]>
57
* @author   Scott Nichol <[email protected]>
58
59
* @access   public
60
*/
61
class nusoap_xmlschema extends nusoap_base  {
62
	
63
	// files
64
	var $schema = '';
65
	var $xml = '';
66
	// namespaces
67
	var $enclosingNamespaces;
68
	// schema info
69
	var $schemaInfo = array();
70
	var $schemaTargetNamespace = '';
71
	// types, elements, attributes defined by the schema
72
	var $attributes = array();
73
	var $complexTypes = array();
74
	var $complexTypeStack = array();
75
	var $currentComplexType = null;
76
	var $elements = array();
77
	var $elementStack = array();
78
	var $currentElement = null;
79
	var $simpleTypes = array();
80
	var $simpleTypeStack = array();
81
	var $currentSimpleType = null;
82
	// imports
83
	var $imports = array();
84
	// parser vars
85
	var $parser;
86
	var $position = 0;
87
	var $depth = 0;
88
	var $depth_array = array();
89
	var $message = array();
90
	var $defaultNamespace = array();
91
    
92
	/**
93
	* constructor
94
	*
95
	* @param    string $schema schema document URI
96
	* @param    string $xml xml document URI
97
	* @param	string $namespaces namespaces defined in enclosing XML
98
	* @access   public
99
	*/
100
	function nusoap_xmlschema($schema='',$xml='',$namespaces=array()){
101
		parent::nusoap_base();
102
		$this->debug('nusoap_xmlschema class instantiated, inside constructor');
103
		// files
104
		$this->schema = $schema;
105
		$this->xml = $xml;
106
107
		// namespaces
108
		$this->enclosingNamespaces = $namespaces;
109
		$this->namespaces = array_merge($this->namespaces, $namespaces);
110
111
		// parse schema file
112
		if($schema != ''){
113
			$this->debug('initial schema file: '.$schema);
114
			$this->parseFile($schema, 'schema');
115
		}
116
117
		// parse xml file
118
		if($xml != ''){
119
			$this->debug('initial xml file: '.$xml);
120
			$this->parseFile($xml, 'xml');
121
		}
122
123
	}
124
125
    /**
126
    * parse an XML file
127
    *
128
    * @param string $xml path/URL to XML file
129
    * @param string $type (schema | xml)
130
	* @return boolean
131
    * @access public
132
    */
133
	function parseFile($xml,$type){
134
		// parse xml file
135
		if($xml != ""){
136
			$xmlStr = @join("",@file($xml));
137
			if($xmlStr == ""){
138
				$msg = 'Error reading XML from '.$xml;
139
				$this->setError($msg);
140
				$this->debug($msg);
141
			return false;
142
			} else {
143
				$this->debug("parsing $xml");
144
				$this->parseString($xmlStr,$type);
145
				$this->debug("done parsing $xml");
146
			return true;
147
			}
148
		}
149
		return false;
150
	}
151
152
	/**
153
	* parse an XML string
154
	*
155
	* @param    string $xml path or URL
156
    * @param	string $type (schema|xml)
157
	* @access   private
158
	*/
159
	function parseString($xml,$type){
160
		// parse xml string
161
		if($xml != ""){
162
163
	    	// Create an XML parser.
164
	    	$this->parser = xml_parser_create();
165
	    	// Set the options for parsing the XML data.
166
	    	xml_parser_set_option($this->parser, XML_OPTION_CASE_FOLDING, 0);
167
168
	    	// Set the object for the parser.
169
	    	xml_set_object($this->parser, $this);
170
171
	    	// Set the element handlers for the parser.
172
			if($type == "schema"){
173
		    	xml_set_element_handler($this->parser, 'schemaStartElement','schemaEndElement');
174
		    	xml_set_character_data_handler($this->parser,'schemaCharacterData');
175
			} elseif($type == "xml"){
176
				xml_set_element_handler($this->parser, 'xmlStartElement','xmlEndElement');
177
		    	xml_set_character_data_handler($this->parser,'xmlCharacterData');
178
			}
179
180
		    // Parse the XML file.
181
		    if(!xml_parse($this->parser,$xml,true)){
182
			// Display an error message.
183
				$errstr = sprintf('XML error parsing XML schema on line %d: %s',
184
				xml_get_current_line_number($this->parser),
185
				xml_error_string(xml_get_error_code($this->parser))
186
				);
187
				$this->debug($errstr);
188
				$this->debug("XML payload:\n" . $xml);
189
				$this->setError($errstr);
190
	    	}
191
            
192
			xml_parser_free($this->parser);
193
		} else{
194
			$this->debug('no xml passed to parseString()!!');
195
			$this->setError('no xml passed to parseString()!!');
196
		}
197
	}
198
199
	/**
200
	 * gets a type name for an unnamed type
201
	 *
202
	 * @param	string	Element name
203
	 * @return	string	A type name for an unnamed type
204
	 * @access	private
205
	 */
206
	function CreateTypeName($ename) {
207
		$scope = '';
208
		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...
209
			$scope .= $this->complexTypeStack[$i] . '_';
210
		}
211
		return $scope . $ename . '_ContainedType';
212
	}
213
	
214
	/**
215
	* start-element handler
216
	*
217
	* @param    string $parser XML parser object
218
	* @param    string $name element name
219
	* @param    string $attrs associative array of attributes
220
	* @access   private
221
	*/
222
	function schemaStartElement($parser, $name, $attrs) {
223
		
224
		// position in the total number of elements, starting from 0
225
		$pos = $this->position++;
226
		$depth = $this->depth++;
227
		// set self as current value for this depth
228
		$this->depth_array[$depth] = $pos;
229
		$this->message[$pos] = array('cdata' => ''); 
230
		if ($depth > 0) {
231
			$this->defaultNamespace[$pos] = $this->defaultNamespace[$this->depth_array[$depth - 1]];
232
		} else {
233
			$this->defaultNamespace[$pos] = false;
234
		}
235
236
		// get element prefix
237
		if($prefix = $this->getPrefix($name)){
238
			// get unqualified name
239
			$name = $this->getLocalPart($name);
240
		} else {
241
        	$prefix = '';
242
        }
243
		
244
        // loop thru attributes, expanding, and registering namespace declarations
245
        if(count($attrs) > 0){
246
        	foreach($attrs as $k => $v){
0 ignored issues
show
The expression $attrs of type string is not traversable.
Loading history...
247
                // if ns declarations, add to class level array of valid namespaces
248
				if(preg_match('/^xmlns/',$k)){
249
                	//$this->xdebug("$k: $v");
250
                	//$this->xdebug('ns_prefix: '.$this->getPrefix($k));
251
                	if($ns_prefix = substr(strrchr($k,':'),1)){
252
                		//$this->xdebug("Add namespace[$ns_prefix] = $v");
253
						$this->namespaces[$ns_prefix] = $v;
254
					} else {
255
						$this->defaultNamespace[$pos] = $v;
256
						if (! $this->getPrefixFromNamespace($v)) {
257
							$this->namespaces['ns'.(count($this->namespaces)+1)] = $v;
258
						}
259
					}
260
					if($v == 'http://www.w3.org/2001/XMLSchema' || $v == 'http://www.w3.org/1999/XMLSchema' || $v == 'http://www.w3.org/2000/10/XMLSchema'){
261
						$this->XMLSchemaVersion = $v;
262
						$this->namespaces['xsi'] = $v.'-instance';
263
					}
264
				}
265
        	}
266
        	foreach($attrs as $k => $v){
0 ignored issues
show
The expression $attrs of type string is not traversable.
Loading history...
267
                // expand each attribute
268
                $k = strpos($k,':') ? $this->expandQname($k) : $k;
269
                $v = strpos($v,':') ? $this->expandQname($v) : $v;
270
        		$eAttrs[$k] = $v;
271
        	}
272
        	$attrs = $eAttrs;
273
        } else {
274
        	$attrs = array();
275
        }
276
		// find status, register data
277
		switch($name){
278
			case 'all':			// (optional) compositor content for a complexType
279
			case 'choice':
280
			case 'group':
281
			case 'sequence':
282
				//$this->xdebug("compositor $name for currentComplexType: $this->currentComplexType and currentElement: $this->currentElement");
283
				$this->complexTypes[$this->currentComplexType]['compositor'] = $name;
284
				//if($name == 'all' || $name == 'sequence'){
285
				//	$this->complexTypes[$this->currentComplexType]['phpType'] = 'struct';
286
				//}
287
			break;
288
			case 'attribute':	// complexType attribute
289
            	//$this->xdebug("parsing attribute $attrs[name] $attrs[ref] of value: ".$attrs['http://schemas.xmlsoap.org/wsdl/:arrayType']);
290
            	$this->xdebug("parsing attribute:");
291
            	$this->appendDebug($this->varDump($attrs));
292
				if (!isset($attrs['form'])) {
293
					// TODO: handle globals
294
					$attrs['form'] = $this->schemaInfo['attributeFormDefault'];
295
				}
296
            	if (isset($attrs['http://schemas.xmlsoap.org/wsdl/:arrayType'])) {
297
					$v = $attrs['http://schemas.xmlsoap.org/wsdl/:arrayType'];
298
					if (!strpos($v, ':')) {
299
						// no namespace in arrayType attribute value...
300
						if ($this->defaultNamespace[$pos]) {
301
							// ...so use the default
302
							$attrs['http://schemas.xmlsoap.org/wsdl/:arrayType'] = $this->defaultNamespace[$pos] . ':' . $attrs['http://schemas.xmlsoap.org/wsdl/:arrayType'];
303
						}
304
					}
305
            	}
306
                if(isset($attrs['name'])){
307
					$this->attributes[$attrs['name']] = $attrs;
308
					$aname = $attrs['name'];
309
				} elseif(isset($attrs['ref']) && $attrs['ref'] == 'http://schemas.xmlsoap.org/soap/encoding/:arrayType'){
310
					if (isset($attrs['http://schemas.xmlsoap.org/wsdl/:arrayType'])) {
311
	                	$aname = $attrs['http://schemas.xmlsoap.org/wsdl/:arrayType'];
312
	                } else {
313
	                	$aname = '';
314
	                }
315
				} elseif(isset($attrs['ref'])){
316
					$aname = $attrs['ref'];
317
                    $this->attributes[$attrs['ref']] = $attrs;
318
				}
319
                
320
				if($this->currentComplexType){	// This should *always* be
321
					$this->complexTypes[$this->currentComplexType]['attrs'][$aname] = $attrs;
322
				}
323
				// arrayType attribute
324
				if(isset($attrs['http://schemas.xmlsoap.org/wsdl/:arrayType']) || $this->getLocalPart($aname) == 'arrayType'){
325
					$this->complexTypes[$this->currentComplexType]['phpType'] = 'array';
326
                	$prefix = $this->getPrefix($aname);
327
					if(isset($attrs['http://schemas.xmlsoap.org/wsdl/:arrayType'])){
328
						$v = $attrs['http://schemas.xmlsoap.org/wsdl/:arrayType'];
329
					} else {
330
						$v = '';
331
					}
332
                    if(strpos($v,'[,]')){
333
                        $this->complexTypes[$this->currentComplexType]['multidimensional'] = true;
334
                    }
335
                    $v = substr($v,0,strpos($v,'[')); // clip the []
336
                    if(!strpos($v,':') && isset($this->typemap[$this->XMLSchemaVersion][$v])){
337
                        $v = $this->XMLSchemaVersion.':'.$v;
338
                    }
339
                    $this->complexTypes[$this->currentComplexType]['arrayType'] = $v;
340
				}
341
			break;
342
			case 'complexContent':	// (optional) content for a complexType
343
				$this->xdebug("do nothing for element $name");
344
			break;
345
			case 'complexType':
346
				array_push($this->complexTypeStack, $this->currentComplexType);
347
				if(isset($attrs['name'])){
348
					// TODO: what is the scope of named complexTypes that appear
349
					//       nested within other c complexTypes?
350
					$this->xdebug('processing named complexType '.$attrs['name']);
351
					//$this->currentElement = false;
352
					$this->currentComplexType = $attrs['name'];
353
					$this->complexTypes[$this->currentComplexType] = $attrs;
354
					$this->complexTypes[$this->currentComplexType]['typeClass'] = 'complexType';
355
					// This is for constructs like
356
					//           <complexType name="ListOfString" base="soap:Array">
357
					//                <sequence>
358
					//                    <element name="string" type="xsd:string"
359
					//                        minOccurs="0" maxOccurs="unbounded" />
360
					//                </sequence>
361
					//            </complexType>
362
					if(isset($attrs['base']) && preg_match('/:Array$/',$attrs['base'])){
363
						$this->xdebug('complexType is unusual array');
364
						$this->complexTypes[$this->currentComplexType]['phpType'] = 'array';
365
					} else {
366
						$this->complexTypes[$this->currentComplexType]['phpType'] = 'struct';
367
					}
368
				} else {
369
					$name = $this->CreateTypeName($this->currentElement);
370
					$this->xdebug('processing unnamed complexType for element ' . $this->currentElement . ' named ' . $name);
371
					$this->currentComplexType = $name;
372
					//$this->currentElement = false;
373
					$this->complexTypes[$this->currentComplexType] = $attrs;
374
					$this->complexTypes[$this->currentComplexType]['typeClass'] = 'complexType';
375
					// This is for constructs like
376
					//           <complexType name="ListOfString" base="soap:Array">
377
					//                <sequence>
378
					//                    <element name="string" type="xsd:string"
379
					//                        minOccurs="0" maxOccurs="unbounded" />
380
					//                </sequence>
381
					//            </complexType>
382
					if(isset($attrs['base']) && preg_match('/:Array$/',$attrs['base'])){
383
						$this->xdebug('complexType is unusual array');
384
						$this->complexTypes[$this->currentComplexType]['phpType'] = 'array';
385
					} else {
386
						$this->complexTypes[$this->currentComplexType]['phpType'] = 'struct';
387
					}
388
				}
389
				$this->complexTypes[$this->currentComplexType]['simpleContent'] = 'false';
390
			break;
391
			case 'element':
392
				array_push($this->elementStack, $this->currentElement);
393
				if (!isset($attrs['form'])) {
394
					if ($this->currentComplexType) {
395
						$attrs['form'] = $this->schemaInfo['elementFormDefault'];
396
					} else {
397
						// global
398
						$attrs['form'] = 'qualified';
399
					}
400
				}
401
				if(isset($attrs['type'])){
402
					$this->xdebug("processing typed element ".$attrs['name']." of type ".$attrs['type']);
403
					if (! $this->getPrefix($attrs['type'])) {
404
						if ($this->defaultNamespace[$pos]) {
405
							$attrs['type'] = $this->defaultNamespace[$pos] . ':' . $attrs['type'];
406
							$this->xdebug('used default namespace to make type ' . $attrs['type']);
407
						}
408
					}
409
					// This is for constructs like
410
					//           <complexType name="ListOfString" base="soap:Array">
411
					//                <sequence>
412
					//                    <element name="string" type="xsd:string"
413
					//                        minOccurs="0" maxOccurs="unbounded" />
414
					//                </sequence>
415
					//            </complexType>
416
					if ($this->currentComplexType && $this->complexTypes[$this->currentComplexType]['phpType'] == 'array') {
417
						$this->xdebug('arrayType for unusual array is ' . $attrs['type']);
418
						$this->complexTypes[$this->currentComplexType]['arrayType'] = $attrs['type'];
419
					}
420
					$this->currentElement = $attrs['name'];
421
					$ename = $attrs['name'];
422
				} elseif(isset($attrs['ref'])){
423
					$this->xdebug("processing element as ref to ".$attrs['ref']);
424
					$this->currentElement = "ref to ".$attrs['ref'];
425
					$ename = $this->getLocalPart($attrs['ref']);
426
				} else {
427
					$type = $this->CreateTypeName($this->currentComplexType . '_' . $attrs['name']);
428
					$this->xdebug("processing untyped element " . $attrs['name'] . ' type ' . $type);
429
					$this->currentElement = $attrs['name'];
430
					$attrs['type'] = $this->schemaTargetNamespace . ':' . $type;
431
					$ename = $attrs['name'];
432
				}
433
				if (isset($ename) && $this->currentComplexType) {
434
					$this->xdebug("add element $ename to complexType $this->currentComplexType");
435
					$this->complexTypes[$this->currentComplexType]['elements'][$ename] = $attrs;
436
				} elseif (!isset($attrs['ref'])) {
437
					$this->xdebug("add element $ename to elements array");
438
					$this->elements[ $attrs['name'] ] = $attrs;
439
					$this->elements[ $attrs['name'] ]['typeClass'] = 'element';
440
				}
441
			break;
442
			case 'enumeration':	//	restriction value list member
443
				$this->xdebug('enumeration ' . $attrs['value']);
444
				if ($this->currentSimpleType) {
445
					$this->simpleTypes[$this->currentSimpleType]['enumeration'][] = $attrs['value'];
446
				} elseif ($this->currentComplexType) {
447
					$this->complexTypes[$this->currentComplexType]['enumeration'][] = $attrs['value'];
448
				}
449
			break;
450
			case 'extension':	// simpleContent or complexContent type extension
451
				$this->xdebug('extension ' . $attrs['base']);
452
				if ($this->currentComplexType) {
453
					$ns = $this->getPrefix($attrs['base']);
454
					if ($ns == '') {
455
						$this->complexTypes[$this->currentComplexType]['extensionBase'] = $this->schemaTargetNamespace . ':' . $attrs['base'];
456
					} else {
457
						$this->complexTypes[$this->currentComplexType]['extensionBase'] = $attrs['base'];
458
					}
459
				} else {
460
					$this->xdebug('no current complexType to set extensionBase');
461
				}
462
			break;
463
			case 'import':
464
			    if (isset($attrs['schemaLocation'])) {
465
					$this->xdebug('import namespace ' . $attrs['namespace'] . ' from ' . $attrs['schemaLocation']);
466
                    $this->imports[$attrs['namespace']][] = array('location' => $attrs['schemaLocation'], 'loaded' => false);
467
				} else {
468
					$this->xdebug('import namespace ' . $attrs['namespace']);
469
                    $this->imports[$attrs['namespace']][] = array('location' => '', 'loaded' => true);
470
					if (! $this->getPrefixFromNamespace($attrs['namespace'])) {
471
						$this->namespaces['ns'.(count($this->namespaces)+1)] = $attrs['namespace'];
472
					}
473
				}
474
			break;
475
			case 'include':
476
			    if (isset($attrs['schemaLocation'])) {
477
					$this->xdebug('include into namespace ' . $this->schemaTargetNamespace . ' from ' . $attrs['schemaLocation']);
478
                    $this->imports[$this->schemaTargetNamespace][] = array('location' => $attrs['schemaLocation'], 'loaded' => false);
479
				} else {
480
					$this->xdebug('ignoring invalid XML Schema construct: include without schemaLocation attribute');
481
				}
482
			break;
483
			case 'list':	// simpleType value list
484
				$this->xdebug("do nothing for element $name");
485
			break;
486
			case 'restriction':	// simpleType, simpleContent or complexContent value restriction
487
				$this->xdebug('restriction ' . $attrs['base']);
488
				if($this->currentSimpleType){
489
					$this->simpleTypes[$this->currentSimpleType]['type'] = $attrs['base'];
490
				} elseif($this->currentComplexType){
491
					$this->complexTypes[$this->currentComplexType]['restrictionBase'] = $attrs['base'];
492
					if(strstr($attrs['base'],':') == ':Array'){
493
						$this->complexTypes[$this->currentComplexType]['phpType'] = 'array';
494
					}
495
				}
496
			break;
497
			case 'schema':
498
				$this->schemaInfo = $attrs;
499
				$this->schemaInfo['schemaVersion'] = $this->getNamespaceFromPrefix($prefix);
500
				if (isset($attrs['targetNamespace'])) {
501
					$this->schemaTargetNamespace = $attrs['targetNamespace'];
502
				}
503
				if (!isset($attrs['elementFormDefault'])) {
504
					$this->schemaInfo['elementFormDefault'] = 'unqualified';
505
				}
506
				if (!isset($attrs['attributeFormDefault'])) {
507
					$this->schemaInfo['attributeFormDefault'] = 'unqualified';
508
				}
509
			break;
510
			case 'simpleContent':	// (optional) content for a complexType
511
				if ($this->currentComplexType) {	// This should *always* be
512
					$this->complexTypes[$this->currentComplexType]['simpleContent'] = 'true';
513
				} else {
514
					$this->xdebug("do nothing for element $name because there is no current complexType");
515
				}
516
			break;
517
			case 'simpleType':
518
				array_push($this->simpleTypeStack, $this->currentSimpleType);
519
				if(isset($attrs['name'])){
520
					$this->xdebug("processing simpleType for name " . $attrs['name']);
521
					$this->currentSimpleType = $attrs['name'];
522
					$this->simpleTypes[ $attrs['name'] ] = $attrs;
523
					$this->simpleTypes[ $attrs['name'] ]['typeClass'] = 'simpleType';
524
					$this->simpleTypes[ $attrs['name'] ]['phpType'] = 'scalar';
525
				} else {
526
					$name = $this->CreateTypeName($this->currentComplexType . '_' . $this->currentElement);
527
					$this->xdebug('processing unnamed simpleType for element ' . $this->currentElement . ' named ' . $name);
528
					$this->currentSimpleType = $name;
529
					//$this->currentElement = false;
530
					$this->simpleTypes[$this->currentSimpleType] = $attrs;
531
					$this->simpleTypes[$this->currentSimpleType]['phpType'] = 'scalar';
532
				}
533
			break;
534
			case 'union':	// simpleType type list
535
				$this->xdebug("do nothing for element $name");
536
			break;
537
			default:
538
				$this->xdebug("do not have any logic to process element $name");
539
		}
540
	}
541
542
	/**
543
	* end-element handler
544
	*
545
	* @param    string $parser XML parser object
546
	* @param    string $name element name
547
	* @access   private
548
	*/
549
	function schemaEndElement($parser, $name) {
550
		// bring depth down a notch
551
		$this->depth--;
552
		// position of current element is equal to the last value left in depth_array for my depth
553
		if(isset($this->depth_array[$this->depth])){
554
        	$pos = $this->depth_array[$this->depth];
555
        }
556
		// get element prefix
557
		if ($prefix = $this->getPrefix($name)){
558
			// get unqualified name
559
			$name = $this->getLocalPart($name);
560
		} else {
561
        	$prefix = '';
562
        }
563
		// move on...
564
		if($name == 'complexType'){
565
			$this->xdebug('done processing complexType ' . ($this->currentComplexType ? $this->currentComplexType : '(unknown)'));
566
			$this->xdebug($this->varDump($this->complexTypes[$this->currentComplexType]));
567
			$this->currentComplexType = array_pop($this->complexTypeStack);
568
			//$this->currentElement = false;
569
		}
570
		if($name == 'element'){
571
			$this->xdebug('done processing element ' . ($this->currentElement ? $this->currentElement : '(unknown)'));
572
			$this->currentElement = array_pop($this->elementStack);
573
		}
574
		if($name == 'simpleType'){
575
			$this->xdebug('done processing simpleType ' . ($this->currentSimpleType ? $this->currentSimpleType : '(unknown)'));
576
			$this->xdebug($this->varDump($this->simpleTypes[$this->currentSimpleType]));
577
			$this->currentSimpleType = array_pop($this->simpleTypeStack);
578
		}
579
	}
580
581
	/**
582
	* element content handler
583
	*
584
	* @param    string $parser XML parser object
585
	* @param    string $data element content
586
	* @access   private
587
	*/
588
	function schemaCharacterData($parser, $data){
589
		$pos = $this->depth_array[$this->depth - 1];
590
		$this->message[$pos]['cdata'] .= $data;
591
	}
592
593
	/**
594
	* serialize the schema
595
	*
596
	* @access   public
597
	*/
598
	function serializeSchema(){
599
600
		$schemaPrefix = $this->getPrefixFromNamespace($this->XMLSchemaVersion);
601
		$xml = '';
602
		// imports
603
		if (sizeof($this->imports) > 0) {
604
			foreach($this->imports as $ns => $list) {
605
				foreach ($list as $ii) {
606
					if ($ii['location'] != '') {
607
						$xml .= " <$schemaPrefix:import location=\"" . $ii['location'] . '" namespace="' . $ns . "\" />\n";
608
					} else {
609
						$xml .= " <$schemaPrefix:import namespace=\"" . $ns . "\" />\n";
610
					}
611
				}
612
			} 
613
		} 
614
		// complex types
615
		foreach($this->complexTypes as $typeName => $attrs){
616
			$contentStr = '';
617
			// serialize child elements
618
			if(isset($attrs['elements']) && (count($attrs['elements']) > 0)){
619
				foreach($attrs['elements'] as $element => $eParts){
620
					if(isset($eParts['ref'])){
621
						$contentStr .= "   <$schemaPrefix:element ref=\"$element\"/>\n";
622
					} else {
623
						$contentStr .= "   <$schemaPrefix:element name=\"$element\" type=\"" . $this->contractQName($eParts['type']) . "\"";
624
						foreach ($eParts as $aName => $aValue) {
625
							// handle, e.g., abstract, default, form, minOccurs, maxOccurs, nillable
626
							if ($aName != 'name' && $aName != 'type') {
627
								$contentStr .= " $aName=\"$aValue\"";
628
							}
629
						}
630
						$contentStr .= "/>\n";
631
					}
632
				}
633
				// compositor wraps elements
634
				if (isset($attrs['compositor']) && ($attrs['compositor'] != '')) {
635
					$contentStr = "  <$schemaPrefix:$attrs[compositor]>\n".$contentStr."  </$schemaPrefix:$attrs[compositor]>\n";
636
				}
637
			}
638
			// attributes
639
			if(isset($attrs['attrs']) && (count($attrs['attrs']) >= 1)){
640
				foreach($attrs['attrs'] as $attr => $aParts){
641
					$contentStr .= "    <$schemaPrefix:attribute";
642
					foreach ($aParts as $a => $v) {
643
						if ($a == 'ref' || $a == 'type') {
644
							$contentStr .= " $a=\"".$this->contractQName($v).'"';
645
						} elseif ($a == 'http://schemas.xmlsoap.org/wsdl/:arrayType') {
646
							$this->usedNamespaces['wsdl'] = $this->namespaces['wsdl'];
647
							$contentStr .= ' wsdl:arrayType="'.$this->contractQName($v).'"';
648
						} else {
649
							$contentStr .= " $a=\"$v\"";
650
						}
651
					}
652
					$contentStr .= "/>\n";
653
				}
654
			}
655
			// if restriction
656
			if (isset($attrs['restrictionBase']) && $attrs['restrictionBase'] != ''){
657
				$contentStr = "   <$schemaPrefix:restriction base=\"".$this->contractQName($attrs['restrictionBase'])."\">\n".$contentStr."   </$schemaPrefix:restriction>\n";
658
				// complex or simple content
659
				if ((isset($attrs['elements']) && count($attrs['elements']) > 0) || (isset($attrs['attrs']) && count($attrs['attrs']) > 0)){
660
					$contentStr = "  <$schemaPrefix:complexContent>\n".$contentStr."  </$schemaPrefix:complexContent>\n";
661
				}
662
			}
663
			// finalize complex type
664
			if($contentStr != ''){
665
				$contentStr = " <$schemaPrefix:complexType name=\"$typeName\">\n".$contentStr." </$schemaPrefix:complexType>\n";
666
			} else {
667
				$contentStr = " <$schemaPrefix:complexType name=\"$typeName\"/>\n";
668
			}
669
			$xml .= $contentStr;
670
		}
671
		// simple types
672
		if(isset($this->simpleTypes) && count($this->simpleTypes) > 0){
673
			foreach($this->simpleTypes as $typeName => $eParts){
674
				$xml .= " <$schemaPrefix:simpleType name=\"$typeName\">\n  <$schemaPrefix:restriction base=\"".$this->contractQName($eParts['type'])."\">\n";
675
				if (isset($eParts['enumeration'])) {
676
					foreach ($eParts['enumeration'] as $e) {
677
						$xml .= "  <$schemaPrefix:enumeration value=\"$e\"/>\n";
678
					}
679
				}
680
				$xml .= "  </$schemaPrefix:restriction>\n </$schemaPrefix:simpleType>";
681
			}
682
		}
683
		// elements
684
		if(isset($this->elements) && count($this->elements) > 0){
685
			foreach($this->elements as $element => $eParts){
686
				$xml .= " <$schemaPrefix:element name=\"$element\" type=\"".$this->contractQName($eParts['type'])."\"/>\n";
687
			}
688
		}
689
		// attributes
690
		if(isset($this->attributes) && count($this->attributes) > 0){
691
			foreach($this->attributes as $attr => $aParts){
692
				$xml .= " <$schemaPrefix:attribute name=\"$attr\" type=\"".$this->contractQName($aParts['type'])."\"\n/>";
693
			}
694
		}
695
		// finish 'er up
696
		$attr = '';
697
		foreach ($this->schemaInfo as $k => $v) {
698
			if ($k == 'elementFormDefault' || $k == 'attributeFormDefault') {
699
				$attr .= " $k=\"$v\"";
700
			}
701
		}
702
		$el = "<$schemaPrefix:schema$attr targetNamespace=\"$this->schemaTargetNamespace\"\n";
703
		foreach (array_diff($this->usedNamespaces, $this->enclosingNamespaces) as $nsp => $ns) {
704
			$el .= " xmlns:$nsp=\"$ns\"";
705
		}
706
		$xml = $el . ">\n".$xml."</$schemaPrefix:schema>\n";
707
		return $xml;
708
	}
709
710
	/**
711
	* adds debug data to the clas level debug string
712
	*
713
	* @param    string $string debug data
714
	* @access   private
715
	*/
716
	function xdebug($string){
717
		$this->debug('<' . $this->schemaTargetNamespace . '> '.$string);
718
	}
719
720
    /**
721
    * get the PHP type of a user defined type in the schema
722
    * PHP type is kind of a misnomer since it actually returns 'struct' for assoc. arrays
723
    * returns false if no type exists, or not w/ the given namespace
724
    * else returns a string that is either a native php type, or 'struct'
725
    *
726
    * @param string $type name of defined type
727
    * @param string $ns namespace of type
728
    * @return mixed
729
    * @access public
730
    * @deprecated
731
    */
732
	function getPHPType($type,$ns){
733
		if(isset($this->typemap[$ns][$type])){
734
			//print "found type '$type' and ns $ns in typemap<br>";
735
			return $this->typemap[$ns][$type];
736
		} elseif(isset($this->complexTypes[$type])){
737
			//print "getting type '$type' and ns $ns from complexTypes array<br>";
738
			return $this->complexTypes[$type]['phpType'];
739
		}
740
		return false;
741
	}
742
743
	/**
744
    * returns an associative array of information about a given type
745
    * returns false if no type exists by the given name
746
    *
747
	*	For a complexType typeDef = array(
748
	*	'restrictionBase' => '',
749
	*	'phpType' => '',
750
	*	'compositor' => '(sequence|all)',
751
	*	'elements' => array(), // refs to elements array
752
	*	'attrs' => array() // refs to attributes array
753
	*	... and so on (see addComplexType)
754
	*	)
755
	*
756
	*   For simpleType or element, the array has different keys.
757
    *
758
    * @param string $type
759
    * @return mixed
760
    * @access public
761
    * @see addComplexType
762
    * @see addSimpleType
763
    * @see addElement
764
    */
765
	function getTypeDef($type){
766
		//$this->debug("in getTypeDef for type $type");
767
		if (substr($type, -1) == '^') {
768
			$is_element = 1;
769
			$type = substr($type, 0, -1);
770
		} else {
771
			$is_element = 0;
772
		}
773
774
		if((! $is_element) && isset($this->complexTypes[$type])){
775
			$this->xdebug("in getTypeDef, found complexType $type");
776
			return $this->complexTypes[$type];
777
		} elseif((! $is_element) && isset($this->simpleTypes[$type])){
778
			$this->xdebug("in getTypeDef, found simpleType $type");
779
			if (!isset($this->simpleTypes[$type]['phpType'])) {
780
				// get info for type to tack onto the simple type
781
				// TODO: can this ever really apply (i.e. what is a simpleType really?)
782
				$uqType = substr($this->simpleTypes[$type]['type'], strrpos($this->simpleTypes[$type]['type'], ':') + 1);
783
				$ns = substr($this->simpleTypes[$type]['type'], 0, strrpos($this->simpleTypes[$type]['type'], ':'));
784
				$etype = $this->getTypeDef($uqType);
785
				if ($etype) {
786
					$this->xdebug("in getTypeDef, found type for simpleType $type:");
787
					$this->xdebug($this->varDump($etype));
788
					if (isset($etype['phpType'])) {
789
						$this->simpleTypes[$type]['phpType'] = $etype['phpType'];
790
					}
791
					if (isset($etype['elements'])) {
792
						$this->simpleTypes[$type]['elements'] = $etype['elements'];
793
					}
794
				}
795
			}
796
			return $this->simpleTypes[$type];
797
		} elseif(isset($this->elements[$type])){
798
			$this->xdebug("in getTypeDef, found element $type");
799
			if (!isset($this->elements[$type]['phpType'])) {
800
				// get info for type to tack onto the element
801
				$uqType = substr($this->elements[$type]['type'], strrpos($this->elements[$type]['type'], ':') + 1);
802
				$ns = substr($this->elements[$type]['type'], 0, strrpos($this->elements[$type]['type'], ':'));
803
				$etype = $this->getTypeDef($uqType);
804
				if ($etype) {
805
					$this->xdebug("in getTypeDef, found type for element $type:");
806
					$this->xdebug($this->varDump($etype));
807
					if (isset($etype['phpType'])) {
808
						$this->elements[$type]['phpType'] = $etype['phpType'];
809
					}
810
					if (isset($etype['elements'])) {
811
						$this->elements[$type]['elements'] = $etype['elements'];
812
					}
813
					if (isset($etype['extensionBase'])) {
814
						$this->elements[$type]['extensionBase'] = $etype['extensionBase'];
815
					}
816
				} elseif ($ns == 'http://www.w3.org/2001/XMLSchema') {
817
					$this->xdebug("in getTypeDef, element $type is an XSD type");
818
					$this->elements[$type]['phpType'] = 'scalar';
819
				}
820
			}
821
			return $this->elements[$type];
822
		} elseif(isset($this->attributes[$type])){
823
			$this->xdebug("in getTypeDef, found attribute $type");
824
			return $this->attributes[$type];
825
		} elseif (preg_match('/_ContainedType$/', $type)) {
826
			$this->xdebug("in getTypeDef, have an untyped element $type");
827
			$typeDef['typeClass'] = 'simpleType';
828
			$typeDef['phpType'] = 'scalar';
829
			$typeDef['type'] = 'http://www.w3.org/2001/XMLSchema:string';
830
			return $typeDef;
831
		}
832
		$this->xdebug("in getTypeDef, did not find $type");
833
		return false;
834
	}
835
836
	/**
837
    * returns a sample serialization of a given type, or false if no type by the given name
838
    *
839
    * @param string $type name of type
840
    * @return mixed
841
    * @access public
842
    * @deprecated
843
    */
844
    function serializeTypeDef($type){
845
    	//print "in sTD() for type $type<br>";
846
	if($typeDef = $this->getTypeDef($type)){
847
		$str .= '<'.$type;
848
	    if(is_array($typeDef['attrs'])){
849
		foreach($typeDef['attrs'] as $attName => $data){
850
		    $str .= " $attName=\"{type = ".$data['type']."}\"";
851
		}
852
	    }
853
	    $str .= " xmlns=\"".$this->schema['targetNamespace']."\"";
854
	    if(count($typeDef['elements']) > 0){
855
		$str .= ">";
856
		foreach($typeDef['elements'] as $element => $eData){
857
		    $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...
858
		}
859
		$str .= "</$type>";
860
	    } elseif($typeDef['typeClass'] == 'element') {
861
		$str .= "></$type>";
862
	    } else {
863
		$str .= "/>";
864
	    }
865
			return $str;
866
	}
867
    	return false;
868
    }
869
870
    /**
871
    * returns HTML form elements that allow a user
872
    * to enter values for creating an instance of the given type.
873
    *
874
    * @param string $name name for type instance
875
    * @param string $type name of type
876
    * @return string
877
    * @access public
878
    * @deprecated
879
	*/
880
	function typeToForm($name,$type){
881
		// get typedef
882
		if($typeDef = $this->getTypeDef($type)){
883
			// if struct
884
			if($typeDef['phpType'] == 'struct'){
885
				$buffer .= '<table>';
886
				foreach($typeDef['elements'] as $child => $childDef){
887
					$buffer .= "
888
					<tr><td align='right'>$childDef[name] (type: ".$this->getLocalPart($childDef['type'])."):</td>
889
					<td><input type='text' name='parameters[".$name."][$childDef[name]]'></td></tr>";
890
				}
891
				$buffer .= '</table>';
892
			// if array
893
			} elseif($typeDef['phpType'] == 'array'){
894
				$buffer .= '<table>';
895
				for($i=0;$i < 3; $i++){
896
					$buffer .= "
897
					<tr><td align='right'>array item (type: $typeDef[arrayType]):</td>
898
					<td><input type='text' name='parameters[".$name."][]'></td></tr>";
899
				}
900
				$buffer .= '</table>';
901
			// if scalar
902
			} else {
903
				$buffer .= "<input type='text' name='parameters[$name]'>";
904
			}
905
		} else {
906
			$buffer .= "<input type='text' name='parameters[$name]'>";
907
		}
908
		return $buffer;
909
	}
910
	
911
	/**
912
	* adds a complex type to the schema
913
	* 
914
	* example: array
915
	* 
916
	* addType(
917
	* 	'ArrayOfstring',
918
	* 	'complexType',
919
	* 	'array',
920
	* 	'',
921
	* 	'SOAP-ENC:Array',
922
	* 	array('ref'=>'SOAP-ENC:arrayType','wsdl:arrayType'=>'string[]'),
923
	* 	'xsd:string'
924
	* );
925
	* 
926
	* example: PHP associative array ( SOAP Struct )
927
	* 
928
	* addType(
929
	* 	'SOAPStruct',
930
	* 	'complexType',
931
	* 	'struct',
932
	* 	'all',
933
	* 	array('myVar'=> array('name'=>'myVar','type'=>'string')
934
	* );
935
	* 
936
	* @param name
937
	* @param typeClass (complexType|simpleType|attribute)
938
	* @param phpType: currently supported are array and struct (php assoc array)
939
	* @param compositor (all|sequence|choice)
940
	* @param restrictionBase namespace:name (http://schemas.xmlsoap.org/soap/encoding/:Array)
941
	* @param elements = array ( name = array(name=>'',type=>'') )
942
	* @param attrs = array(
943
	* 	array(
944
	*		'ref' => "http://schemas.xmlsoap.org/soap/encoding/:arrayType",
945
	*		"http://schemas.xmlsoap.org/wsdl/:arrayType" => "string[]"
946
	* 	)
947
	* )
948
	* @param arrayType: namespace:name (http://www.w3.org/2001/XMLSchema:string)
949
	* @access public
950
	* @see getTypeDef
951
	*/
952
	function addComplexType($name,$typeClass='complexType',$phpType='array',$compositor='',$restrictionBase='',$elements=array(),$attrs=array(),$arrayType=''){
953
		$this->complexTypes[$name] = array(
954
	    'name'		=> $name,
955
	    'typeClass'	=> $typeClass,
956
	    'phpType'	=> $phpType,
957
		'compositor'=> $compositor,
958
	    'restrictionBase' => $restrictionBase,
959
		'elements'	=> $elements,
960
	    'attrs'		=> $attrs,
961
	    'arrayType'	=> $arrayType
962
		);
963
		
964
		$this->xdebug("addComplexType $name:");
965
		$this->appendDebug($this->varDump($this->complexTypes[$name]));
966
	}
967
	
968
	/**
969
	* adds a simple type to the schema
970
	*
971
	* @param string $name
972
	* @param string $restrictionBase namespace:name (http://schemas.xmlsoap.org/soap/encoding/:Array)
973
	* @param string $typeClass (should always be simpleType)
974
	* @param string $phpType (should always be scalar)
975
	* @param array $enumeration array of values
976
	* @access public
977
	* @see nusoap_xmlschema
978
	* @see getTypeDef
979
	*/
980
	function addSimpleType($name, $restrictionBase='', $typeClass='simpleType', $phpType='scalar', $enumeration=array()) {
981
		$this->simpleTypes[$name] = array(
982
	    'name'			=> $name,
983
	    'typeClass'		=> $typeClass,
984
	    'phpType'		=> $phpType,
985
	    'type'			=> $restrictionBase,
986
	    'enumeration'	=> $enumeration
987
		);
988
		
989
		$this->xdebug("addSimpleType $name:");
990
		$this->appendDebug($this->varDump($this->simpleTypes[$name]));
991
	}
992
993
	/**
994
	* adds an element to the schema
995
	*
996
	* @param array $attrs attributes that must include name and type
997
	* @see nusoap_xmlschema
998
	* @access public
999
	*/
1000
	function addElement($attrs) {
1001
		if (! $this->getPrefix($attrs['type'])) {
1002
			$attrs['type'] = $this->schemaTargetNamespace . ':' . $attrs['type'];
1003
		}
1004
		$this->elements[ $attrs['name'] ] = $attrs;
1005
		$this->elements[ $attrs['name'] ]['typeClass'] = 'element';
1006
		
1007
		$this->xdebug("addElement " . $attrs['name']);
1008
		$this->appendDebug($this->varDump($this->elements[ $attrs['name'] ]));
1009
	}
1010
}
1011
1012
/**
1013
 * Backward compatibility
1014
 */
1015
class XMLSchema extends nusoap_xmlschema {
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...
1016
}
1017
1018
1019
?>