GitHub Access Token became invalid

It seems like the GitHub access token used for retrieving details about this repository from GitHub became invalid. This might prevent certain types of inspections from being run (in particular, everything related to pull requests).
Please ask an admin of your repository to re-new the access token on this website.

nusoap_base::serialize_val()   F
last analyzed

Complexity

Conditions 77
Paths 2269

Size

Total Lines 170
Code Lines 160

Duplication

Lines 0
Ratio 0 %
Metric Value
dl 0
loc 170
rs 2
cc 77
eloc 160
nc 2269
nop 7

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
/**
3
 * NuSOAP - Web Services Toolkit for PHP
4
 *
5
 * @author: Dietrich Ayala
6
 */
7
8
/*
9
Copyright (c) 2002 NuSphere Corporation
10
11
This library is free software; you can redistribute it and/or
12
modify it under the terms of the GNU Lesser General Public
13
License as published by the Free Software Foundation; either
14
version 2.1 of the License, or (at your option) any later version.
15
16
This library is distributed in the hope that it will be useful,
17
but WITHOUT ANY WARRANTY; without even the implied warranty of
18
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
19
Lesser General Public License for more details.
20
21
You should have received a copy of the GNU Lesser General Public
22
License along with this library; if not, write to the Free Software
23
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
24
25
If you have any questions or comments, please email:
26
27
Dietrich Ayala
28
[email protected]
29
http://dietrich.ganx4.com/nusoap
30
31
NuSphere Corporation
32
http://www.nusphere.com
33
34
*/
35
36
/* load classes
37
38
// necessary classes
39
require_once('class.soapclient.php');
40
require_once('class.soap_val.php');
41
require_once('class.soap_parser.php');
42
require_once('class.soap_fault.php');
43
44
// transport classes
45
require_once('class.soap_transport_http.php');
46
47
// optional add-on classes
48
require_once('class.xmlschema.php');
49
require_once('class.wsdl.php');
50
51
// server class
52
require_once('class.soap_server.php');*/
53
54
/**
55
*
56
* nusoap_base
57
*
58
* @author   Dietrich Ayala <[email protected]>
59
* @version  v 0.6.3
60
* @access   public
61
*/
62
class nusoap_base {
63
64
    var $title = 'NuSOAP';
65
    var $version = '0.6.3';
66
    var $error_str = false;
67
    var $debug_str = '';
68
    // toggles automatic encoding of special characters
69
    var $charencoding = true;
70
71
    /**
72
     *  set schema version
73
     *
74
     * @var      XMLSchemaVersion
75
     * @access   public
76
     */
77
    var $XMLSchemaVersion = 'http://www.w3.org/2001/XMLSchema';
78
	
79
    /**
80
     *  set default encoding
81
     *
82
     * @var      soap_defencoding
83
     * @access   public
84
     */
85
    //var $soap_defencoding = 'UTF-8';
86
    var $soap_defencoding = 'ISO-8859-1';
87
88
    /**
89
     *  load namespace uris into an array of uri => prefix
90
     *
91
     * @var      namespaces
92
     * @access   public
93
     */
94
    var $namespaces = array(
95
                            'SOAP-ENV' => 'http://schemas.xmlsoap.org/soap/envelope/',
96
                            'xsd' => 'http://www.w3.org/2001/XMLSchema',
97
                            'xsi' => 'http://www.w3.org/2001/XMLSchema-instance',
98
                            'SOAP-ENC' => 'http://schemas.xmlsoap.org/soap/encoding/',
99
                            'si' => 'http://soapinterop.org/xsd');
100
    /**
101
     * load types into typemap array
102
     * is this legacy yet?
103
     * no, this is used by the xmlschema class to verify type => namespace mappings.
104
     * @var      typemap
105
     * @access   public
106
     */
107
    var $typemap = 
108
        array(
109
              'http://www.w3.org/2001/XMLSchema' => 
110
              array(
111
                    'string'=>'string','boolean'=>'boolean','float'=>'double','double'=>'double','decimal'=>'double',
112
                    'duration'=>'','dateTime'=>'string','time'=>'string','date'=>'string','gYearMonth'=>'',
113
                    'gYear'=>'','gMonthDay'=>'','gDay'=>'','gMonth'=>'','hexBinary'=>'string','base64Binary'=>'string',
114
                    // derived datatypes
115
                    'normalizedString'=>'string','token'=>'string','language'=>'','NMTOKEN'=>'','NMTOKENS'=>'','Name'=>'','NCName'=>'','ID'=>'',
116
                    'IDREF'=>'','IDREFS'=>'','ENTITY'=>'','ENTITIES'=>'','integer'=>'integer','nonPositiveInteger'=>'integer',
117
                    'negativeInteger'=>'integer','long'=>'integer','int'=>'integer','short'=>'integer','byte'=>'integer','nonNegativeInteger'=>'integer',
118
                    'unsignedLong'=>'','unsignedInt'=>'','unsignedShort'=>'','unsignedByte'=>'','positiveInteger'=>''),
119
              'http://www.w3.org/1999/XMLSchema' => 
120
              array(
121
                    'i4'=>'','int'=>'integer','boolean'=>'boolean','string'=>'string','double'=>'double',
122
                    'float'=>'double','dateTime'=>'string',
123
                    'timeInstant'=>'string','base64Binary'=>'string','base64'=>'string','ur-type'=>'array'),
124
              'http://soapinterop.org/xsd' => array('SOAPStruct'=>'struct'),
125
              'http://schemas.xmlsoap.org/soap/encoding/' => array('base64'=>'string','array'=>'array','Array'=>'array'),
126
              'http://xml.apache.org/xml-soap' => array('Map')
127
              );
128
    
129
    /**
130
     *  entities to convert
131
     *
132
     * @var      xmlEntities
133
     * @access   public
134
     */
135
    var $xmlEntities = array('quot' => '"','amp' => '&',
136
                             'lt' => '<','gt' => '>','apos' => "'");
137
138
    /**
139
     * adds debug data to the class level debug string
140
     *
141
     * @param    string $string debug data
142
     * @access   private
143
     */
144
    function debug($string){
145
        $this->debug_str .= get_class($this).": $string\n";
146
    }
147
148
    /**
149
     * returns error string if present
150
     *
151
     * @return   boolean $string error string
152
     * @access   public
153
     */
154
    function getError(){
155
        if($this->error_str != ''){
156
            return $this->error_str;
157
        }
158
        return false;
159
    }
160
161
    /**
162
     * sets error string
163
     *
164
     * @return   boolean $string error string
165
     * @access   private
166
     */
167
    function setError($str){
168
        $this->error_str = $str;
169
    }
170
171
    /**
172
     * serializes PHP values in accordance w/ section 5. Type information is
173
     * not serialized if $use == 'literal'.
174
     *
175
     * @return	string
176
     * @access	public
177
     */
178
    function serialize_val($val,$name=false,$type=false,$name_ns=false,
179
                           $type_ns=false,$attributes=false,$use='encoded') {
180
    	if(is_object($val) && strtolower(get_class($val)) == 'soapval'){
181
            return $val->serialize($use);
182
        }
183
        $this->debug( "in serialize_val: $val, $name, $type, $name_ns, $type_ns, $attributes, $use");
184
        // if no name, use item
185
        $name = (!$name|| is_numeric($name)) ? 'soapVal' : $name;
186
        // if name has ns, add ns prefix to name
187
        $xmlns = '';
188
        if($name_ns){
189
            $prefix = 'nu'.rand(1000,9999);
190
            $name = $prefix.':'.$name;
191
            $xmlns .= " xmlns:$prefix=\"$name_ns\"";
192
        }
193
        // if type is prefixed, create type prefix
194
        if($type_ns != '' && $type_ns == $this->namespaces['xsd']){
195
            // need to fix this. shouldn't default to xsd if no ns specified
196
            // w/o checking against typemap
197
            $type_prefix = 'xsd';
198
        } elseif($type_ns){
199
            $type_prefix = 'ns'.rand(1000,9999);
200
            $xmlns .= " xmlns:$type_prefix=\"$type_ns\"";
201
        }
202
        // serialize attributes if present
203
        if($attributes){
204
            foreach($attributes as $k => $v){
0 ignored issues
show
Bug introduced by
The expression $attributes of type boolean is not traversable.
Loading history...
205
                $atts .= " $k=\"$v\"";
206
            }
207
        }
208
        // serialize if an xsd built-in primitive type
209
        if ($type != '' && isset($this->typemap[$this->XMLSchemaVersion][$type])){
210
            if ($use == 'literal') {
211
                return "<$name$xmlns>$val</$name>";
212
            } else {
213
                return "<$name$xmlns xsi:type=\"xsd:$type\">$val</$name>";
214
            }
215
        }
216
        // detect type and serialize
217
        $xml = '';
218
        $atts = '';
219
        switch(true) {
220
        case ($type == '' && is_null($val)):
221
            if ($use == 'literal') {
222
                // TODO: depends on nillable
223
                $xml .= "<$name$xmlns/>";
224
            } else {
225
                $xml .= "<$name$xmlns xsi:type=\"xsd:nil\"/>";
226
            }
227
            break;
228
        case (is_bool($val) || $type == 'boolean'):
229
            if(!$val){
230
                $val = 0;
231
            }
232
            if ($use == 'literal') {
233
                $xml .= "<$name$xmlns $atts>$val</$name>";
234
            } else {
235
                $xml .= "<$name$xmlns xsi:type=\"xsd:boolean\"$atts>$val</$name>";
236
            }
237
            break;
238
        case (is_int($val) || is_long($val) || $type == 'int'):
239
            if ($use == 'literal') {
240
                $xml .= "<$name$xmlns $atts>$val</$name>";
241
            } else {
242
                $xml .= "<$name$xmlns xsi:type=\"xsd:int\"$atts>$val</$name>";
243
            }
244
            break;
245
        case (is_float($val)|| is_double($val) || $type == 'float'):
246
            if ($use == 'literal') {
247
                $xml .= "<$name$xmlns $atts>$val</$name>";
248
            } else {
249
                $xml .= "<$name$xmlns xsi:type=\"xsd:float\"$atts>$val</$name>";
250
            }
251
            break;
252
        case (is_string($val) || $type == 'string'):
253
            if($this->charencoding){
254
                $val = htmlspecialchars($val, ENT_QUOTES);
255
            }
256
            if ($use == 'literal') {
257
                $xml .= "<$name$xmlns $atts>$val</$name>";
258
            } else {
259
                $xml .= "<$name$xmlns xsi:type=\"xsd:string\"$atts>$val</$name>";
260
            }
261
            break;
262
        case is_object($val):
263
            $name = strtolower(get_class($val));
264
            foreach(get_object_vars($val) as $k => $v){
265
                $pXml = isset($pXml) ? $pXml.$this->serialize_val($v,$k,false,false,false,false,$use) : $this->serialize_val($v,$k,false,false,false,false,$use);
266
            }
267
            $xml .= '<'.$name.'>'.$pXml.'</'.$name.'>';
268
            break;
269
            break;
0 ignored issues
show
Unused Code introduced by
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...
270
        case (is_array($val) || $type):
271
            // detect if struct or array
272
            $keyList = array_keys($val);
273
            $valueType = 'arraySimple';
274
            foreach($keyList as $keyListValue){
275
                if(!is_int($keyListValue)){
276
                    $valueType = 'arrayStruct';
277
                    break;
278
                }
279
            }
280
            if($valueType=='arraySimple' || ereg('^ArrayOf',$type)){
281
                $i = 0;
282
                if(is_array($val) && count($val)> 0){
283
                    foreach($val as $v){
284
                        if(is_object($v) && strtolower(get_class($v)) == 'soapval'){
285
                            $tt = $v->type;
286
                        } else {
287
                            $tt = gettype($v);
288
                        }
289
                        $array_types[$tt] = 1;
290
                        $xml .= $this->serialize_val($v,'item',false,false,false,false,$use);
291
                        if(is_array($v) && is_numeric(key($v))){
292
                            $i += sizeof($v);
293
                        } else {
294
                            ++$i;
295
                        }
296
                    }
297
                    if(count($array_types) > 1){
298
                        $array_typename = 'xsd:ur-type';
299
                    } elseif(isset($tt) && isset($this->typemap[$this->XMLSchemaVersion][$tt])) {
300
                        $array_typename = 'xsd:'.$tt;
301
                    } elseif($tt == 'array' || $tt == 'Array'){
302
                        $array_typename = 'SOAP-ENC:Array';
303
                    } else {
304
                        $array_typename = $tt;
305
                    }
306
                    if(isset($array_types['array'])){
307
                        $array_type = $i.",".$i;
308
                    } else {
309
                        $array_type = $i;
310
                    }
311
                    if ($use == 'literal') {
312
                        $xml = "<$name $atts>".$xml."</$name>";
313
                    } else {
314
                        $xml = "<$name xsi:type=\"SOAP-ENC:Array\" SOAP-ENC:arrayType=\"".$array_typename."[$array_type]\"$atts>".$xml."</$name>";
315
                    }
316
                    // empty array
317
                } else {
318
                    if ($use == 'literal') {
319
                        $xml = "<$name $atts>".$xml."</$name>";;
320
                    } else {
321
                        $xml = "<$name xsi:type=\"SOAP-ENC:Array\" $atts>".$xml."</$name>";;
322
                    }
323
                }
324
            } else {
325
                // got a struct
326
                if(isset($type) && isset($type_prefix)){
327
                    $type_str = " xsi:type=\"$type_prefix:$type\"";
328
                } else {
329
                    $type_str = '';
330
                }
331
                if ($use == 'literal') {
332
                    $xml .= "<$name$xmlns $atts>";
333
                } else {
334
                    $xml .= "<$name$xmlns$type_str$atts>";
335
                }
336
                foreach($val as $k => $v){
337
                    $xml .= $this->serialize_val($v,$k,false,false,false,false,$use);
338
                }
339
                $xml .= "</$name>";
340
            }
341
            break;
342
        default:
343
            $xml .= 'not detected, got '.gettype($val).' for '.$val;
344
            break;
345
        }
346
        return $xml;
347
    }
348
    
349
    /**
350
    * serialize message
351
    *
352
    * @param string body
353
    * @param string headers
354
    * @param array namespaces
355
    * @param string style
356
    * @return string message
357
    * @access public
358
    */
359
    function serializeEnvelope($body,$headers=false,$namespaces=array(),$style='rpc'){
360
	// serialize namespaces
361
        $ns_string = '';
362
	foreach(array_merge($this->namespaces,$namespaces) as $k => $v){
363
		$ns_string .= "  xmlns:$k=\"$v\"";
364
	}
365
	if($style == 'rpc') {
366
            $ns_string = ' SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"' . $ns_string;
367
	}
368
369
	// serialize headers
370
	if($headers){
371
            $headers = "<SOAP-ENV:Header>".$headers."</SOAP-ENV:Header>";
372
	}
373
	// serialize envelope
374
	return
375
            '<?xml version="1.0" encoding="'.$this->soap_defencoding .'"?'.">".
376
            '<SOAP-ENV:Envelope'.$ns_string.">".
377
            $headers.
378
            "<SOAP-ENV:Body>".
379
            $body.
380
            "</SOAP-ENV:Body>".
381
            "</SOAP-ENV:Envelope>";
382
    }
383
384
    function formatDump($str){
385
        $str = htmlspecialchars($str);
386
        return nl2br($str);
387
    }
388
389
    /**
390
     * returns the local part of a prefixed string
391
     * returns the original string, if not prefixed
392
     *
393
     * @param string
394
     * @return string
395
     * @access public
396
     */
397
    function getLocalPart($str){
398
        if($sstr = strrchr($str,':')){
399
            // get unqualified name
400
            return substr( $sstr, 1 );
401
        } else {
402
            return $str;
403
        }
404
    }
405
    
406
    /**
407
     * returns the prefix part of a prefixed string
408
     * returns false, if not prefixed
409
     *
410
     * @param string
411
     * @return mixed
412
     * @access public
413
     */
414
    function getPrefix($str){
415
        if($pos = strrpos($str,':')){
416
            // get prefix
417
            return substr($str,0,$pos);
418
        }
419
        return false;
420
    }
421
422
    function varDump($data) {
423
        ob_start();
424
        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...
425
        $ret_val = ob_get_contents();
426
        ob_end_clean();
427
        return $ret_val;
428
    }
429
}
430
431
// XML Schema Datatype Helper Functions
432
433
//xsd:dateTime helpers
434
435
/**
436
* convert unix timestamp to ISO 8601 compliant date string
437
*
438
* @param    string $timestamp Unix time stamp
439
* @access   public
440
*/
441
function timestamp_to_iso8601($timestamp,$utc=true){
442
    $datestr = date('Y-m-d\TH:i:sO',$timestamp);
443
    if($utc){
444
        $eregStr =
445
            '([0-9]{4})-'.	// centuries & years CCYY-
446
            '([0-9]{2})-'.	// months MM-
447
            '([0-9]{2})'.	// days DD
448
            'T'.			// separator T
449
            '([0-9]{2}):'.	// hours hh:
450
            '([0-9]{2}):'.	// minutes mm:
451
            '([0-9]{2})(\.[0-9]*)?'. // seconds ss.ss...
452
            '(Z|[+\-][0-9]{2}:?[0-9]{2})?'; // Z to indicate UTC, -/+HH:MM:SS.SS... for local tz's
453
        
454
        if(ereg($eregStr,$datestr,$regs)){
455
            return sprintf('%04d-%02d-%02dT%02d:%02d:%02dZ',$regs[1],$regs[2],$regs[3],$regs[4],$regs[5],$regs[6]);
456
        }
457
        return false;
458
    } else {
459
        return $datestr;
460
    }
461
}
462
463
/**
464
* convert ISO 8601 compliant date string to unix timestamp
465
*
466
* @param    string $datestr ISO 8601 compliant date string
467
* @access   public
468
*/
469
function iso8601_to_timestamp($datestr){
470
    $eregStr =
471
	'([0-9]{4})-'.	// centuries & years CCYY-
472
	'([0-9]{2})-'.	// months MM-
473
	'([0-9]{2})'.	// days DD
474
	'T'.			// separator T
475
	'([0-9]{2}):'.	// hours hh:
476
	'([0-9]{2}):'.	// minutes mm:
477
	'([0-9]{2})(\.[0-9]+)?'. // seconds ss.ss...
478
	'(Z|[+\-][0-9]{2}:?[0-9]{2})?'; // Z to indicate UTC, -/+HH:MM:SS.SS... for local tz's
479
    if(ereg($eregStr,$datestr,$regs)){
480
        // not utc
481
        if($regs[8] != 'Z'){
482
            $op = substr($regs[8],0,1);
483
            $h = substr($regs[8],1,2);
484
            $m = substr($regs[8],strlen($regs[8])-2,2);
485
            if($op == '-'){
486
                $regs[4] = $regs[4] + $h;
487
                $regs[5] = $regs[5] + $m;
488
            } elseif($op == '+'){
489
                $regs[4] = $regs[4] - $h;
490
                $regs[5] = $regs[5] - $m;
491
            }
492
        }
493
        return strtotime("$regs[1]-$regs[2]-$regs[3] $regs[4]:$regs[5]:$regs[6]Z");
494
    } else {
495
        return false;
496
    }
497
}
498
499
?><?php
500
501
/**
502
 * soap_fault class, allows for creation of faults
503
 * mainly used for returning faults from deployed functions
504
 * in a server instance.
505
 * @author   Dietrich Ayala <[email protected]>
506
 * @version  v 0.6.3
507
 * @access public
508
 */
509
class soap_fault extends nusoap_base {
510
511
    var $faultcode;
512
    var $faultactor;
513
    var $faultstring;
514
    var $faultdetail;
515
    
516
    /**
517
     * constructor
518
     *
519
     * @param string $faultcode (client | server)
520
     * @param string $faultactor only used when msg routed between multiple actors
521
     * @param string $faultstring human readable error message
522
     * @param string $faultdetail
523
     */
524
    function soap_fault($faultcode,$faultactor='',$faultstring='',$faultdetail=''){
525
        $this->faultcode = $faultcode;
526
        $this->faultactor = $faultactor;
527
        $this->faultstring = $faultstring;
528
        $this->faultdetail = $faultdetail;
529
    }
530
    
531
    /**
532
     * serialize a fault
533
     *
534
     * @access   public
535
     */
536
    function serialize(){
537
        $ns_string = '';
538
        foreach($this->namespaces as $k => $v){
539
            $ns_string .= "\n  xmlns:$k=\"$v\"";
540
        }
541
        $return_msg =
542
            '<?xml version="1.0"?'.">\n".
543
            '<SOAP-ENV:Envelope SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"'.$ns_string.">\n".
544
            '<SOAP-ENV:Body>'.
545
            '<SOAP-ENV:Fault>'.
546
		'<faultcode>'.$this->faultcode.'</faultcode>'.
547
		'<faultactor>'.$this->faultactor.'</faultactor>'.
548
		'<faultstring>'.$this->faultstring.'</faultstring>'.
549
		'<detail>'.$this->serialize_val($this->faultdetail).'</detail>'.
550
	    '</SOAP-ENV:Fault>'.
551
            '</SOAP-ENV:Body>'.
552
            '</SOAP-ENV:Envelope>';
553
        return $return_msg;
554
    }
555
}
556
557
?><?php
558
559
/**
560
* parses an XML Schema, allows access to it's data, other utility methods
561
* no validation... yet.
562
* very experimental and limited. As is discussed on XML-DEV, I'm one of the people
563
* that just doesn't have time to read the spec(s) thoroughly, and just have a couple of trusty
564
* tutorials I refer to :)
565
*
566
* @author   Dietrich Ayala <[email protected]>
567
* @version  v 0.6.3
568
* @access   public
569
*/
570
class XMLSchema extends nusoap_base  {
571
	
572
	// files
573
	var $schema = '';
574
	var $xml = '';
575
	// define internal arrays of bindings, ports, operations, messages, etc.
576
	var $complexTypes = array();
577
	// target namespace
578
	var $schemaTargetNamespace = '';
579
	// parser vars
580
	var $parser;
581
	var $position;
582
	var $depth = 0;
583
	var $depth_array = array();
584
    
585
	/**
586
	* constructor
587
	*
588
	* @param    string $schema schema document URI
589
	* @param    string $xml xml document URI
590
	* @access   public
591
	*/
592
	function XMLSchema($schema='',$xml=''){
593
594
		$this->debug('xmlschema class instantiated, inside constructor');
595
		// files
596
		$this->schema = $schema;
597
		$this->xml = $xml;
598
599
		// parse schema file
600
		if($schema != ''){
601
			$this->debug('initial schema file: '.$schema);
602
			$this->parseFile($schema);
0 ignored issues
show
Bug introduced by
The call to parseFile() misses a required argument $type.

This check looks for function calls that miss required arguments.

Loading history...
603
		}
604
605
		// parse xml file
606
		if($xml != ''){
607
			$this->debug('initial xml file: '.$xml);
608
			$this->parseFile($xml);
0 ignored issues
show
Bug introduced by
The call to parseFile() misses a required argument $type.

This check looks for function calls that miss required arguments.

Loading history...
609
		}
610
611
	}
612
613
        /**
614
         * parse an XML file
615
         *
616
         * @param string $xml, path/URL to XML file
0 ignored issues
show
Bug introduced by
There is no parameter named $xml,. Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

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

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

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

Loading history...
617
         * @param string $type, (schema | xml)
0 ignored issues
show
Bug introduced by
There is no parameter named $type,. Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

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

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

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

Loading history...
618
         * @return boolean
619
         * @access public
620
         */
621
	function parseFile($xml,$type){
622
		// parse xml file
623
		if($xml != ""){
624
			$this->debug('parsing $xml');
625
			$xmlStr = @join("",@file($xml));
626
			if($xmlStr == ""){
627
				$this->setError('No file at the specified URL: '.$xml);
628
			return false;
629
			} else {
630
				$this->parseString($xmlStr,$type);
631
			return true;
632
			}
633
		}
634
		return false;
635
	}
636
637
	/**
638
         * parse an XML string
639
         *
640
         * @param    string $xml path or URL
641
         * @param string $type, (schema|xml)
0 ignored issues
show
Bug introduced by
There is no parameter named $type,. Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

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

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

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

Loading history...
642
         * @access   private
643
         */
644
	function parseString($xml,$type){
645
		// parse xml string
646
		if($xml != ""){
647
648
	    	// Create an XML parser.
649
	    	$this->parser = xml_parser_create();
650
	    	// Set the options for parsing the XML data.
651
	    	xml_parser_set_option($this->parser, XML_OPTION_CASE_FOLDING, 0);
652
653
	    	// Set the object for the parser.
654
	    	xml_set_object($this->parser, $this);
655
656
	    	// Set the element handlers for the parser.
657
			if($type == "schema"){
658
		    	xml_set_element_handler($this->parser, 'schemaStartElement','schemaEndElement');
659
		    	xml_set_character_data_handler($this->parser,'schemaCharacterData');
660
			} elseif($type == "xml"){
661
				xml_set_element_handler($this->parser, 'xmlStartElement','xmlEndElement');
662
		    	xml_set_character_data_handler($this->parser,'xmlCharacterData');
663
			}
664
665
		    // Parse the XML file.
666
		    if(!xml_parse($this->parser,$xml,true)){
667
			// Display an error message.
668
				$errstr = sprintf('XML error on line %d: %s',
669
				xml_get_current_line_number($this->parser),
670
				xml_error_string(xml_get_error_code($this->parser))
671
				);
672
				$this->debug('XML parse error: '.$errstr);
673
				$this->setError('Parser error: '.$errstr);
674
	    	}
675
            
676
			xml_parser_free($this->parser);
677
		} else{
678
			$this->debug('no xml passed to parseString()!!');
679
			$this->setError('no xml passed to parseString()!!');
680
		}
681
	}
682
683
	/**
684
	* start-element handler
685
	*
686
	* @param    string $parser XML parser object
687
	* @param    string $name element name
688
	* @param    string $attrs associative array of attributes
689
	* @access   private
690
	*/
691
	function schemaStartElement($parser, $name, $attrs) {
692
		
693
            // position in the total number of elements, starting from 0
694
            $pos = $this->position++;
695
            $depth = $this->depth++;
696
            // set self as current value for this depth
697
            $this->depth_array[$depth] = $pos;
698
699
            // get element prefix
700
            if($prefix = $this->getPrefix($name)){
701
                // get unqualified name
702
                $name = $this->getLocalPart($name);
703
            } else {
704
        	$prefix = '';
705
            }
706
		
707
            // loop thru attributes, expanding, and registering namespace declarations
708
            if(count($attrs) > 0){
709
                foreach($attrs as $k => $v){
0 ignored issues
show
Bug introduced by
The expression $attrs of type string is not traversable.
Loading history...
710
                    // if ns declarations, add to class level array of valid namespaces
711
                    if(ereg("^xmlns",$k)){
712
                	//$this->xdebug("$k: $v");
713
                	//$this->xdebug('ns_prefix: '.$this->getPrefix($k));
714
                	if($ns_prefix = substr(strrchr($k,':'),1)){
715
                            $this->namespaces[$ns_prefix] = $v;
716
                        } else {
717
                            $this->namespaces['ns'.(count($this->namespaces)+1)] = $v;
718
                        }
719
                        if($v == 'http://www.w3.org/2001/XMLSchema' || $v == 'http://www.w3.org/1999/XMLSchema'){
720
                            $this->XMLSchemaVersion = $v;
721
                            $this->namespaces['xsi'] = $v.'-instance';
722
                        }
723
                    }
724
        	}
725
        	foreach($attrs as $k => $v) {
0 ignored issues
show
Bug introduced by
The expression $attrs of type string is not traversable.
Loading history...
726
                    // expand each attribute
727
                    $k = strpos($k,':') ? $this->expandQname($k) : $k;
728
                    $v = strpos($v,':') ? $this->expandQname($v) : $v;
729
                    $eAttrs[$k] = $v;
730
        	}
731
        	$attrs = $eAttrs;
732
            } else {
733
        	$attrs = array();
734
            }
735
            // find status, register data
736
            switch($name) {
737
            case ('all'|'choice'|'sequence'):
738
                //$this->complexTypes[$this->currentComplexType]['compositor'] = 'all';
739
                $this->complexTypes[$this->currentComplexType]['compositor'] = $name;
740
                if($name == 'all') {
741
                    $this->complexTypes[$this->currentComplexType]['phpType'] = 'struct';
742
                }
743
                break;
744
            case 'attribute':
745
            	//$this->xdebug("parsing attribute $attrs[name] $attrs[ref] of value: ".$attrs['http://schemas.xmlsoap.org/wsdl/:arrayType']);
746
                if(isset($attrs['name'])){
747
					$this->attributes[$attrs['name']] = $attrs;
748
					$aname = $attrs['name'];
749
                } elseif(isset($attrs['ref']) && $attrs['ref'] == 'http://schemas.xmlsoap.org/soap/encoding/:arrayType'){
750
                    $aname = $attrs['http://schemas.xmlsoap.org/wsdl/:arrayType'];
751
                } elseif(isset($attrs['ref'])){
752
                    $aname = $attrs['ref'];
753
                    $this->attributes[$attrs['ref']] = $attrs;
754
                }
755
                
756
                if(isset($this->currentComplexType)){
757
                    $this->complexTypes[$this->currentComplexType]['attrs'][$aname] = $attrs;
758
                } elseif(isset($this->currentElement)){
759
                    $this->elements[$this->currentElement]['attrs'][$aname] = $attrs;
760
                }
761
                // arrayType attribute
762
                if(isset($attrs['http://schemas.xmlsoap.org/wsdl/:arrayType']) || $this->getLocalPart($aname) == 'arrayType'){
763
                    $this->complexTypes[$this->currentComplexType]['phpType'] = 'array';
764
                    $prefix = $this->getPrefix($aname);
765
                    if(isset($attrs['http://schemas.xmlsoap.org/wsdl/:arrayType'])){
766
                        $v = $attrs['http://schemas.xmlsoap.org/wsdl/:arrayType'];
767
                    } else {
768
                        $v = '';
769
                    }
770
                    if(strpos($v,'[,]')){
771
                        $this->complexTypes[$this->currentComplexType]['multidimensional'] = true;
772
                    }
773
                    $v = substr($v,0,strpos($v,'[')); // clip the []
774
                    if(!strpos($v,':') && isset($this->typemap[$this->XMLSchemaVersion][$v])){
775
                        $v = $this->XMLSchemaVersion.':'.$v;
776
                    }
777
                    $this->complexTypes[$this->currentComplexType]['arrayType'] = $v;
778
                }
779
                break;
780
            case 'complexType':
781
                if(isset($attrs['name'])){
782
                    $this->currentElement = false;
783
                    $this->currentComplexType = $attrs['name'];
784
                    $this->complexTypes[$this->currentComplexType] = $attrs;
785
                    $this->complexTypes[$this->currentComplexType]['typeClass'] = 'complexType';
786
                    if(isset($attrs['base']) && ereg(':Array$',$attrs['base'])){
787
                        $this->complexTypes[$this->currentComplexType]['phpType'] = 'array';
788
                    } else {
789
                        $this->complexTypes[$this->currentComplexType]['phpType'] = 'struct';
790
                    }
791
                    $this->xdebug('processing complexType '.$attrs['name']);
792
                }
793
                break;
794
            case 'element':
795
                if(isset($attrs['type'])){
796
                    $this->xdebug("processing element ".$attrs['name']);
797
                    $this->currentElement = $attrs['name'];
798
                    $this->elements[ $attrs['name'] ] = $attrs;
799
                    $this->elements[ $attrs['name'] ]['typeClass'] = 'element';
800
                    $ename = $attrs['name'];
801
                } elseif(isset($attrs['ref'])){
802
                    $ename = $attrs['ref'];
803
                } else {
804
                    $this->xdebug('adding complexType '.$attrs['name']);
805
                    $this->currentComplexType = $attrs['name'];
806
                    $this->complexTypes[ $attrs['name'] ] = $attrs;
807
                    $this->complexTypes[ $attrs['name'] ]['element'] = 1;
808
                    $this->complexTypes[$this->currentComplexType]['phpType'] = 'struct';
809
                }
810
                if(isset($ename) && $this->currentComplexType){
811
                    $this->complexTypes[$this->currentComplexType]['elements'][$ename] = $attrs;
812
                }
813
                break;
814
            case 'restriction':
815
                $this->xdebug("in restriction for ct: $this->currentComplexType and ce: $this->currentElement");
816
                if($this->currentElement){
817
                    $this->elements[$this->currentElement]['type'] = $attrs['base'];
818
                } elseif($this->currentComplexType){
819
                    $this->complexTypes[$this->currentComplexType]['restrictionBase'] = $attrs['base'];
820
                    if(strstr($attrs['base'],':') == ':Array'){
821
                        $this->complexTypes[$this->currentComplexType]['phpType'] = 'array';
822
                    }
823
                }
824
                break;
825
            case 'schema':
826
                $this->schema = $attrs;
827
                $this->schema['schemaVersion'] = $this->getNamespaceFromPrefix($prefix);
828
                break;
829
            case 'simpleType':
830
                $this->currentElement = $attrs['name'];
831
                $this->elements[ $attrs['name'] ] = $attrs;
832
                $this->elements[ $attrs['name'] ]['typeClass'] = 'element';
833
                break;
834
            }
835
	}
836
837
	/**
838
         * end-element handler
839
         *
840
         * @param    string $parser XML parser object
841
         * @param    string $name element name
842
         * @access   private
843
         */
844
	function schemaEndElement($parser, $name) {
845
            // position of current element is equal to the last value left in depth_array for my depth
846
            if(isset($this->depth_array[$this->depth])){
847
        	$pos = $this->depth_array[$this->depth];
848
            }
849
            // bring depth down a notch
850
            $this->depth--;
851
            // move on...
852
            if($name == 'complexType'){
853
                $this->currentComplexType = false;
854
                $this->currentElement = false;
855
            }
856
            if($name == 'element'){
857
                $this->currentElement = false;
858
            }
859
	}
860
861
	/**
862
         * element content handler
863
         *
864
         * @param    string $parser XML parser object
865
         * @param    string $data element content
866
         * @access   private
867
         */
868
	function schemaCharacterData($parser, $data){
869
            $pos = $this->depth_array[$this->depth];
870
            $this->message[$pos]['cdata'] .= $data;
871
	}
872
873
	/**
874
         * serialize the schema
875
         *
876
         * @access   public
877
         */
878
	function serializeSchema(){
879
            
880
            $schemaPrefix = $this->getPrefixFromNamespace($this->XMLSchemaVersion);
881
            $xml = '';
882
            // complex types
883
            foreach($this->complexTypes as $typeName => $attrs){
884
                $contentStr = '';
885
                // serialize child elements
886
                if(count($attrs['elements']) > 0){
887
                    foreach($attrs['elements'] as $element => $eParts){
888
                        if(isset($eParts['ref'])){
889
                            $contentStr .= "<element ref=\"$element\"/>";
890
                        } else {
891
                            $contentStr .= "<element name=\"$element\" type=\"$eParts[type]\"/>";
892
                        }
893
                    }
894
                }
895
                // attributes
896
                if(count($attrs['attrs']) >= 1){
897
                    foreach($attrs['attrs'] as $attr => $aParts){
898
                        $contentStr .= '<attribute ref="'.$aParts['ref'].'"';
899
                        if(isset($aParts['wsdl:arrayType'])){
900
                            $contentStr .= ' wsdl:arrayType="'.$aParts['wsdl:arrayType'].'"';
901
                        }
902
                        $contentStr .= '/>';
903
                    }
904
                }
905
                // if restriction
906
                if( isset($attrs['restrictionBase']) && $attrs['restrictionBase'] != ''){
907
                    $contentStr = "<$schemaPrefix:restriction base=\"".$attrs['restrictionBase']."\">".$contentStr."</$schemaPrefix:restriction>";
908
                }
909
                // "all" compositor obviates complex/simple content
910
                if(isset($attrs['compositor']) && $attrs['compositor'] == 'all'){
911
                    $contentStr = "<$schemaPrefix:$attrs[compositor]>".$contentStr."</$schemaPrefix:$attrs[compositor]>";
912
                }
913
                // complex or simple content
914
                elseif( count($attrs['elements']) > 0 || count($attrs['attrs']) > 0){
915
                    $contentStr = "<$schemaPrefix:complexContent>".$contentStr."</$schemaPrefix:complexContent>";
916
                }
917
                // compositors
918
                if(isset($attrs['compositor']) && $attrs['compositor'] != '' && $attrs['compositor'] != 'all'){
919
                    $contentStr = "<$schemaPrefix:$attrs[compositor]>".$contentStr."</$schemaPrefix:$attrs[compositor]>";
920
                }
921
                // finalize complex type
922
                if($contentStr != ''){
923
                    $contentStr = "<$schemaPrefix:complexType name=\"$typeName\">".$contentStr."</$schemaPrefix:complexType>";
924
                } else {
925
                    $contentStr = "<$schemaPrefix:complexType name=\"$typeName\"/>";
926
                }
927
                $xml .= $contentStr;
928
            }
929
            // elements
930
            if(isset($this->elements) && count($this->elements) > 0){
931
                foreach($this->elements as $element => $eParts){
932
                    $xml .= "<$schemaPrefix:element name=\"$element\" type=\"".$eParts['type']."\"/>";
933
                }
934
            }
935
            // attributes
936
            if(isset($this->attributes) && count($this->attributes) > 0){
937
                foreach($this->attributes as $attr => $aParts){
938
                    $xml .= "<$schemaPrefix:attribute name=\"$attr\" type=\"".$aParts['type']."\"/>";
939
                }
940
            }
941
            // finish 'er up
942
            $xml = "<$schemaPrefix:schema xmlns=\"$this->XMLSchemaVersion\" targetNamespace=\"$this->schemaTargetNamespace\">".$xml."</$schemaPrefix:schema>";
943
            return $xml;
944
	}
945
946
	/**
947
	* expands a qualified name
948
	*
949
	* @param    string $string qname
0 ignored issues
show
Bug introduced by
There is no parameter named $string. Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

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

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

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

Loading history...
950
	* @return	string expanded qname
951
	* @access   private
952
	*/
953
	function expandQname($qname){
954
            // get element prefix
955
            if(strpos($qname,':') && !ereg('^http://',$qname)){
956
                // get unqualified name
957
                $name = substr(strstr($qname,':'),1);
958
                // get ns prefix
959
                $prefix = substr($qname,0,strpos($qname,':'));
960
                if(isset($this->namespaces[$prefix])){
961
                    return $this->namespaces[$prefix].':'.$name;
962
                } else {
963
                    return $qname;
964
                }
965
            } else {
966
                return $qname;
967
            }
968
	}
969
970
	/**
971
         * adds debug data to the clas level debug string
972
         *
973
         * @param    string $string debug data
974
         * @access   private
975
         */
976
	function xdebug($string){
977
            $this->debug(' xmlschema: '.$string);
978
	}
979
980
        /**
981
         * get the PHP type of a user defined type in the schema
982
         * PHP type is kind of a misnomer since it actually returns 'struct' for assoc. arrays
983
         * returns false if no type exists, or not w/ the given namespace
984
         * else returns a string that is either a native php type, or 'struct'
985
         *
986
         * @param string $type, name of defined type
0 ignored issues
show
Bug introduced by
There is no parameter named $type,. Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

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

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

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

Loading history...
987
         * @param string $ns, namespace of type
0 ignored issues
show
Bug introduced by
There is no parameter named $ns,. Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

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

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

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

Loading history...
988
         * @return mixed
989
         * @access public
990
         */
991
	function getPHPType($type,$ns){
992
            global $typemap;
993
            if(isset($typemap[$ns][$type])){
994
                //print "found type '$type' and ns $ns in typemap<br>";
995
                return $typemap[$ns][$type];
996
            } elseif(isset($this->complexTypes[$type])){
997
                //print "getting type '$type' and ns $ns from complexTypes array<br>";
998
                return $this->complexTypes[$type]['phpType'];
999
            }
1000
            return false;
1001
	}
1002
1003
        /**
1004
         * returns the local part of a prefixed string
1005
         * returns the original string, if not prefixed
1006
         *
1007
         * @param string
1008
         * @return string
1009
         * @access public
1010
         */
1011
	function getLocalPart($str){
1012
            if($sstr = strrchr($str,':')){
1013
                // get unqualified name
1014
                return substr( $sstr, 1 );
1015
            } else {
1016
                return $str;
1017
            }
1018
	}
1019
1020
	/**
1021
         * returns the prefix part of a prefixed string
1022
         * returns false, if not prefixed
1023
         *
1024
         * @param string
1025
         * @return mixed
1026
         * @access public
1027
         */
1028
	function getPrefix($str){
1029
            if($pos = strrpos($str,':')){
1030
                // get prefix
1031
                return substr($str,0,$pos);
1032
            }
1033
            return false;
1034
	}
1035
1036
	/**
1037
         * pass it a prefix, it returns a namespace
1038
         * returns false if no namespace registered with the given prefix
1039
         *
1040
         * @param string
1041
         * @return mixed
1042
         * @access public
1043
         */
1044
	function getNamespaceFromPrefix($prefix){
1045
            if(isset($this->namespaces[$prefix])){
1046
                return $this->namespaces[$prefix];
1047
            }
1048
            //$this->setError("No namespace registered for prefix '$prefix'");
1049
            return false;
1050
	}
1051
        
1052
	/**
1053
         * returns the prefix for a given namespace (or prefix)
1054
         * or false if no prefixes registered for the given namespace
1055
         *
1056
         * @param string
1057
         * @return mixed
1058
         * @access public
1059
         */
1060
	function getPrefixFromNamespace($ns){
1061
            foreach($this->namespaces as $p => $n){
1062
                if($ns == $n || $ns == $p){
1063
                    $this->usedNamespaces[$p] = $n;
1064
                    return $p;
1065
                }
1066
            }
1067
            return false;
1068
	}
1069
1070
	/**
1071
         * returns an array of information about a given type
1072
         * returns false if no type exists by the given name
1073
         *
1074
         *	 typeDef = array(
1075
         *	 'elements' => array(), // refs to elements array
1076
         *	'restrictionBase' => '',
1077
         *	'phpType' => '',
1078
         *	'order' => '(sequence|all)',
1079
         *	'attrs' => array() // refs to attributes array
1080
         *	)
1081
         *
1082
         * @param string
1083
         * @return mixed
1084
         * @access public
1085
         */
1086
	function getTypeDef($type){
1087
            if(isset($this->complexTypes[$type])){
1088
                return $this->complexTypes[$type];
1089
            } elseif(isset($this->elements[$type])){
1090
                return $this->elements[$type];
1091
            } elseif(isset($this->attributes[$type])){
1092
                return $this->attributes[$type];
1093
            }
1094
            return false;
1095
	}
1096
1097
	/**
1098
         * returns a sample serialization of a given type, or false if no type by the given name
1099
         *
1100
         * @param string $type, name of type
0 ignored issues
show
Bug introduced by
There is no parameter named $type,. Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

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

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

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

Loading history...
1101
         * @return mixed
1102
         * @access public
1103
         */
1104
        function serializeTypeDef($type){
1105
            //print "in sTD() for type $type<br>";
1106
            if($typeDef = $this->getTypeDef($type)){
1107
		$str .= '<'.$type;
0 ignored issues
show
Bug introduced by
The variable $str does not exist. Did you forget to declare it?

This check marks access to variables or properties that have not been declared yet. While PHP has no explicit notion of declaring a variable, accessing it before a value is assigned to it is most likely a bug.

Loading history...
1108
                if(is_array($typeDef['attrs'])){
1109
                    foreach($attrs as $attName => $data){
0 ignored issues
show
Bug introduced by
The variable $attrs does not exist. Did you forget to declare it?

This check marks access to variables or properties that have not been declared yet. While PHP has no explicit notion of declaring a variable, accessing it before a value is assigned to it is most likely a bug.

Loading history...
1110
                        $str .= " $attName=\"{type = ".$data['type']."}\"";
1111
                    }
1112
                }
1113
                $str .= " xmlns=\"".$this->schema['targetNamespace']."\"";
1114
                if(count($typeDef['elements']) > 0){
1115
                    $str .= ">";
1116
                    foreach($typeDef['elements'] as $element => $eData){
1117
                        $str .= $this->serializeTypeDef($element);
1118
                    }
1119
                    $str .= "</$type>";
1120
                } elseif($typeDef['typeClass'] == 'element') {
1121
                    $str .= "></$type>";
1122
                } else {
1123
                    $str .= "/>";
1124
                }
1125
                return $str;
1126
            }
1127
            return false;
1128
        }
1129
1130
        /**
1131
         * returns HTML form elements that allow a user
1132
         * to enter values for creating an instance of the given type.
1133
         *
1134
         * @param string $name, name for type instance
0 ignored issues
show
Bug introduced by
There is no parameter named $name,. Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

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

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

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

Loading history...
1135
         * @param string $type, name of type
0 ignored issues
show
Bug introduced by
There is no parameter named $type,. Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

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

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

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

Loading history...
1136
         * @return string
1137
         * @access public
1138
         */
1139
	function typeToForm($name,$type){
1140
            // get typedef
1141
            if($typeDef = $this->getTypeDef($type)){
1142
                // if struct
1143
                if($typeDef['phpType'] == 'struct'){
1144
                    $buffer .= '<table>';
0 ignored issues
show
Bug introduced by
The variable $buffer does not exist. Did you forget to declare it?

This check marks access to variables or properties that have not been declared yet. While PHP has no explicit notion of declaring a variable, accessing it before a value is assigned to it is most likely a bug.

Loading history...
1145
                    foreach($typeDef['elements'] as $child => $childDef){
1146
                        $buffer .= "<tr><td align='right'>$childDef[name] (type: ".$this->getLocalPart($childDef['type'])."):</td>".
1147
                                   "<td><input type='text' name='parameters[".$name."][$childDef[name]]'></td></tr>";
1148
                    }
1149
                    $buffer .= '</table>';
1150
                    // if array
1151
                } elseif($typeDef['phpType'] == 'array'){
1152
                    $buffer .= '<table>';
1153
                    for($i=0;$i < 3; $i++){
1154
                        $buffer .= "<tr><td align='right'>array item (type: $typeDef[arrayType]):</td>".
1155
                                   "<td><input type='text' name='parameters[".$name."][]'></td></tr>";
1156
                    }
1157
                    $buffer .= '</table>';
1158
                    // if scalar
1159
                } else {
1160
                    $buffer .= "<input type='text' name='parameters[$name]'>";
1161
                }
1162
            } else {
1163
                $buffer .= "<input type='text' name='parameters[$name]'>";
1164
            }
1165
            return $buffer;
1166
	}
1167
	
1168
	/**
1169
	* adds an XML Schema complex type to the WSDL types
1170
	* 
1171
	* example: array
1172
	* 
1173
	* addType(
1174
	* 	'ArrayOfstring',
1175
	* 	'complexType',
1176
	* 	'array',
1177
	* 	'',
1178
	* 	'SOAP-ENC:Array',
1179
	* 	array('ref'=>'SOAP-ENC:arrayType','wsdl:arrayType'=>'string[]'),
1180
	* 	'xsd:string'
1181
	* );
1182
	* 
1183
	* example: PHP associative array ( SOAP Struct )
1184
	* 
1185
	* addType(
1186
	* 	'SOAPStruct',
1187
	* 	'complexType',
1188
	* 	'struct',
1189
	* 	'all',
1190
	* 	array('myVar'=> array('name'=>'myVar','type'=>'string')
1191
	* );
1192
	* 
1193
	* @param name
1194
	* @param typeClass (complexType|simpleType|attribute)
1195
	* @param phpType: currently supported are array and struct (php assoc array)
1196
	* @param compositor (all|sequence|choice)
1197
	* @param restrictionBase namespace:name (http://schemas.xmlsoap.org/soap/encoding/:Array)
1198
	* @param elements = array ( name = array(name=>'',type=>'') )
1199
	* @param attrs = array(
1200
	* 	array(
1201
	*		'ref' => "http://schemas.xmlsoap.org/soap/encoding/:arrayType",
1202
	*		"http://schemas.xmlsoap.org/wsdl/:arrayType" => "string[]"
1203
	* 	)
1204
	* )
1205
	* @param arrayType: namespace:name (http://www.w3.org/2001/XMLSchema:string)
1206
	*
1207
	*/
1208
	function addComplexType($name,$typeClass='complexType',$phpType='array',$compositor='',$restrictionBase='',$elements=array(),$attrs=array(),$arrayType=''){
1209
            $this->complexTypes[$name] = array(
1210
                                               'name'		=> $name,
1211
                                               'typeClass'	=> $typeClass,
1212
                                               'phpType'	=> $phpType,
1213
                                               'compositor'=> $compositor,
1214
                                               'restrictionBase' => $restrictionBase,
1215
                                               'elements'	=> $elements,
1216
                                               'attrs'		=> $attrs,
1217
                                               'arrayType'	=> $arrayType
1218
                                               );
1219
	}
1220
}
1221
1222
?><?php
1223
1224
/**
1225
* for creating serializable abstractions of native PHP types
1226
* NOTE: this is only really used when WSDL is not available.
1227
*
1228
* @author   Dietrich Ayala <[email protected]>
1229
* @version  v 0.6.3
1230
* @access   public
1231
*/
1232
class soapval extends nusoap_base {
1233
    /**
1234
     * constructor
1235
     *
1236
     * @param    string $name optional name
1237
     * @param    string $type optional type name
1238
     * @param	mixed $value optional value
1239
     * @param	string $namespace optional namespace of value
0 ignored issues
show
Bug introduced by
There is no parameter named $namespace. Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

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

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

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

Loading history...
1240
     * @param	string $type_namespace optional namespace of type
0 ignored issues
show
Bug introduced by
There is no parameter named $type_namespace. Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

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

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

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

Loading history...
1241
     * @param	array $attributes associative array of attributes to add to element serialization
1242
     * @access   public
1243
     */
1244
    function soapval($name='soapval',$type=false,$value=-1,$element_ns=false,$type_ns=false,$attributes=false) {
1245
        $this->name = $name;
1246
        $this->value = $value;
1247
        $this->type = $type;
1248
        $this->element_ns = $element_ns;
1249
        $this->type_ns = $type_ns;
1250
        $this->attributes = $attributes;
1251
    }
1252
1253
    /**
1254
     * return serialized value
1255
     *
1256
     * @return	string XML data
1257
     * @access   private
1258
     */
1259
    function serialize($use='encoded') {
1260
        return $this->serialize_val($this->value,$this->name,$this->type,$this->element_ns,$this->type_ns,$this->attributes,$use);
1261
    }
1262
1263
    /**
1264
     * decodes a soapval object into a PHP native type
1265
     *
1266
     * @param	object $soapval optional SOAPx4 soapval object, else uses self
0 ignored issues
show
Bug introduced by
There is no parameter named $soapval. Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

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

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

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

Loading history...
1267
     * @return	mixed
1268
     * @access   public
1269
     */
1270
    function decode(){
1271
        return $this->value;
1272
    }
1273
}
1274
1275
?><?php
1276
1277
/**
1278
* transport class for sending/receiving data via HTTP and HTTPS
1279
* NOTE: PHP must be compiled with the CURL extension for HTTPS support
1280
*
1281
* @author   Dietrich Ayala <[email protected]>
1282
* @version  v 0.6.3
1283
* @access public
1284
*/
1285
class soap_transport_http extends nusoap_base {
1286
1287
    var $username = '';
1288
    var $password = '';
1289
    var $url = '';
1290
    var $proxyhost = '';
1291
    var $proxyport = '';
1292
    var $scheme = '';
1293
    var $request_method = 'POST';
1294
    var $protocol_version = '1.0';
1295
    var $encoding = '';
1296
    var $outgoing_headers = array();
1297
    var $incoming_headers = array();
1298
    var $outgoing_payload = '';
1299
    var $incoming_payload = '';
1300
    var $useSOAPAction = true;
1301
	
1302
    /**
1303
     * constructor
1304
     */
1305
    function soap_transport_http($url){
1306
        $this->url = $url;
1307
        $u = parse_url($url);
1308
        foreach($u as $k => $v){
0 ignored issues
show
Bug introduced by
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...
1309
            $this->debug("$k = $v");
1310
            $this->$k = $v;
1311
        }
1312
        if(isset($u['query']) && $u['query'] != ''){
1313
            $this->path .= '?' . $u['query'];
1314
        }
1315
        if(!isset($u['port']) && $u['scheme'] == 'http'){
1316
            $this->port = 80;
1317
        }
1318
    }
1319
    
1320
    function connect($timeout){
1321
	
1322
        // proxy
1323
        if($this->proxyhost != '' && $this->proxyport != ''){
1324
            $host = $this->proxyhost;
1325
            $port = $this->proxyport;
1326
            $this->debug("using http proxy: $host, $port");
1327
        } else {
1328
            $host = $this->host;
1329
            $port = $this->port;
1330
        }
1331
        // ssl
1332
        if($this->scheme == 'https'){
1333
            $host = 'ssl://'.$host;
1334
            $port = 443;
1335
        }
1336
	
1337
        $this->debug("connection params: $host, $port");
1338
        // timeout
1339
        if($timeout > 0){
1340
            $fp = fsockopen($host, $port, $this->errno, $this->error_str, $timeout);
1341
        } else {
1342
            $fp = fsockopen($host, $port, $this->errno, $this->error_str);
1343
        }
1344
	
1345
        // test pointer
1346
        if(!$fp) {
1347
            $this->debug('Couldn\'t open socket connection to server '.$this->url.', Error: '.$this->error_str);
1348
            $this->setError('Couldn\'t open socket connection to server: '.$this->url.', Error: '.$this->error_str);
1349
            return false;
1350
        }
1351
        return $fp;
1352
    }
1353
	
1354
    /**
1355
     * send the SOAP message via HTTP
1356
     *
1357
     * @param    string $data message data
1358
     * @param    integer $timeout set timeout in seconds
1359
     * @return	string data
1360
     * @access   public
1361
     */
1362
    function send($data, $timeout=0) {
1363
        $this->debug('entered send() with data of length: '.strlen($data));
1364
        // get connnection
1365
        if(!$fp = $this->connect($timeout)){
1366
            return false;
1367
        }
1368
        $this->debug('socket connected');
1369
	
1370
        // start building outgoing payload:
1371
        // swap url for path if going through a proxy
1372
        if($this->proxyhost != '' && $this->proxyport != ''){
1373
            $this->outgoing_payload = "$this->request_method $this->url ".strtoupper($this->scheme)."/$this->protocol_version\r\n";
1374
        } else {
1375
            $this->outgoing_payload = "$this->request_method $this->path ".strtoupper($this->scheme)."/$this->protocol_version\r\n";
1376
        }
1377
        // make payload
1378
        $this->outgoing_payload .=
1379
            "User-Agent: $this->title/$this->version\r\n".
1380
            "Host: ".$this->host."\r\n";
1381
        // http auth
1382
        $credentials = '';
1383
        if($this->username != '') {
1384
            $this->debug('setting http auth credentials');
1385
            $this->outgoing_payload .= 'Authorization: Basic '.base64_encode("$this->username:$this->password")."\r\n";
1386
        }
1387
        // set content type
1388
        $this->outgoing_payload .= 'Content-Type: text/xml; charset='.$this->soap_defencoding."\r\nContent-Length: ".strlen($data)."\r\n";
1389
        // http encoding
1390
        if($this->encoding != '' && function_exists('gzdeflate')){
1391
            $this->outgoing_payload .= "Accept-Encoding: $this->encoding\r\n".
1392
                "Connection: close\r\n";
1393
            set_magic_quotes_runtime(0);
1394
        }
1395
        // set soapaction
1396
        if($this->useSOAPAction){
1397
            $this->outgoing_payload .= "SOAPAction: \"$this->soapaction\""."\r\n";
1398
        }
1399
        $this->outgoing_payload .= "\r\n";
1400
        // add data
1401
        $this->outgoing_payload .= $data;
1402
		
1403
        // send payload
1404
        if(!fputs($fp, $this->outgoing_payload, strlen($this->outgoing_payload))) {
1405
            $this->setError('couldn\'t write message data to socket');
1406
            $this->debug('Write error');
1407
        }
1408
        $this->debug('wrote data to socket');
1409
		
1410
        // get response
1411
        $this->incoming_payload = '';
1412
        //$strlen = 0;
1413
        while( $data = fread($fp, 32768) ){
1414
            $this->incoming_payload .= $data;
1415
            //$strlen += strlen($data);
1416
        }
1417
        $this->debug('received '.strlen($this->incoming_payload).' bytes of data from server');
1418
	
1419
        // close filepointer
1420
        fclose($fp);
1421
        $this->debug('closed socket');
1422
		
1423
        // connection was closed unexpectedly
1424
        if($this->incoming_payload == ''){
1425
            $this->setError('no response from server');
1426
            return false;
1427
        }
1428
		
1429
        $this->debug('received incoming payload: '.strlen($this->incoming_payload));
1430
        $data = $this->incoming_payload."\r\n\r\n\r\n\r\n";
1431
		
1432
        // remove 100 header
1433
        if(ereg('^HTTP/1.1 100',$data)){
1434
            if($pos = strpos($data,"\r\n\r\n") ){
1435
                $data = ltrim(substr($data,$pos));
1436
            } elseif($pos = strpos($data,"\n\n") ){
1437
                $data = ltrim(substr($data,$pos));
1438
            }
1439
        }//
1440
		
1441
        // separate content from HTTP headers
1442
        if( $pos = strpos($data,"\r\n\r\n") ){
1443
            $lb = "\r\n";
1444
        } elseif( $pos = strpos($data,"\n\n") ){
1445
            $lb = "\n";
1446
        } else {
1447
            $this->setError('no proper separation of headers and document');
1448
            return false;
1449
        }
1450
        $header_data = trim(substr($data,0,$pos));
1451
        $header_array = explode($lb,$header_data);
1452
        $data = ltrim(substr($data,$pos));
1453
        $this->debug('found proper separation of headers and document');
1454
        $this->debug('cleaned data, stringlen: '.strlen($data));
1455
        // clean headers
1456
        foreach($header_array as $header_line){
1457
            $arr = explode(':',$header_line);
1458
            if(count($arr) >= 2){
1459
                $headers[trim($arr[0])] = trim($arr[1]);
1460
            }
1461
        }
1462
        //print "headers: <pre>$header_data</pre><br>";
1463
        //print "data: <pre>$data</pre><br>";
1464
		
1465
        // decode transfer-encoding
1466
        if(isset($headers['Transfer-Encoding']) && $headers['Transfer-Encoding'] == 'chunked'){
1467
            //$timer->setMarker('starting to decode chunked content');
1468
            if(!$data = $this->decodeChunked($data)){
1469
                $this->setError('Decoding of chunked data failed');
1470
                return false;
1471
            }
1472
            //$timer->setMarker('finished decoding of chunked content');
1473
            //print "<pre>\nde-chunked:\n---------------\n$data\n\n---------------\n</pre>";
1474
        }
1475
		
1476
        // decode content-encoding
1477
        if(isset($headers['Content-Encoding']) && $headers['Content-Encoding'] != ''){
1478
            if($headers['Content-Encoding'] == 'deflate' || $headers['Content-Encoding'] == 'gzip'){
1479
                // if decoding works, use it. else assume data wasn't gzencoded
1480
                if(function_exists('gzinflate')){
1481
                    //$timer->setMarker('starting decoding of gzip/deflated content');
1482
                    if($headers['Content-Encoding'] == 'deflate' && $degzdata = @gzinflate($data)){
1483
                        $data = $degzdata;
1484
                    } elseif($headers['Content-Encoding'] == 'gzip' && $degzdata = gzinflate(substr($data, 10))){
1485
                        $data = $degzdata;
1486
                    } else {
1487
                        $this->setError('Errors occurred when trying to decode the data');
1488
                    }
1489
                    //$timer->setMarker('finished decoding of gzip/deflated content');
1490
                    //print "<xmp>\nde-inflated:\n---------------\n$data\n-------------\n</xmp>";
1491
                } else {
1492
                    $this->setError('The server sent deflated data. Your php install must have the Zlib extension compiled in to support this.');
1493
                }
1494
            }
1495
        }
1496
		
1497
        if(strlen($data) == 0){
1498
            $this->debug('no data after headers!');
1499
            $this->setError('no data present after HTTP headers');
1500
            return false;
1501
        }
1502
        $this->debug('end of send()');
1503
        return $data;
1504
    }
1505
1506
    
1507
    /**
1508
     * send the SOAP message via HTTPS 1.0 using CURL
1509
     *
1510
     * @param    string $msg message data
0 ignored issues
show
Bug introduced by
There is no parameter named $msg. Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

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

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

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

Loading history...
1511
     * @param    integer $timeout set timeout in seconds
1512
     * @return	string data
1513
     * @access   public
1514
     */
1515
    function sendHTTPS($data, $timeout=0) {
1516
        //global $t;
1517
        //$t->setMarker('inside sendHTTPS()');
1518
        $this->debug('entered sendHTTPS() with data of length: '.strlen($data));
1519
        // init CURL
1520
        $ch = curl_init();
1521
        //$t->setMarker('got curl handle');
1522
        // set proxy
1523
        if($this->proxyhost && $this->proxyport){
1524
            $host = $this->proxyhost;
1525
            $port = $this->proxyport;
1526
        } else {
1527
            $host = $this->host;
1528
            $port = $this->port;
1529
        }
1530
        // set url
1531
        $hostURL = ($port != '') ? "https://$host:$port" : "https://$host";
1532
        // add path
1533
        $hostURL .= $this->path;
1534
        curl_setopt($ch, CURLOPT_URL, $hostURL);
1535
        // set other options
1536
        curl_setopt($ch, CURLOPT_HEADER, 1);
1537
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
1538
        // encode
1539
        if(function_exists('gzinflate')){
1540
            curl_setopt($ch, CURLOPT_ENCODING, 'deflate');
1541
        }
1542
        // persistent connection
1543
        //curl_setopt($ch, CURL_HTTP_VERSION_1_1, true);
1544
		
1545
        // set timeout
1546
        if($timeout != 0){
1547
            curl_setopt($ch, CURLOPT_TIMEOUT, $timeout);
1548
        }
1549
		
1550
        $credentials = '';
1551
        if($this->username != '') {
1552
            $credentials = 'Authorization: Basic '.base64_encode("$this->username:$this->password").'\r\n';
1553
        }
1554
		
1555
        if($this->encoding != ''){
1556
            if(function_exists('gzdeflate')){
1557
                $encoding_headers = "Accept-Encoding: $this->encoding\r\n".
1558
                    "Connection: close\r\n";
1559
                set_magic_quotes_runtime(0);
1560
            }
1561
        }
1562
		
1563
        if($this->proxyhost && $this->proxyport){
1564
            $this->outgoing_payload = "POST $this->url HTTP/$this->protocol_version\r\n";
1565
        } else {
1566
            $this->outgoing_payload = "POST $this->path HTTP/$this->protocol_version\r\n";
1567
        }
1568
		
1569
        $this->outgoing_payload .=
1570
            "User-Agent: $this->title v$this->version\r\n".
1571
            "Host: ".$this->host."\r\n".
1572
            $encoding_headers.
1573
            $credentials.
1574
            "Content-Type: text/xml; charset=\"$this->soap_defencoding\"\r\n".
1575
            "Content-Length: ".strlen($data)."\r\n".
1576
            "SOAPAction: \"$this->soapaction\""."\r\n\r\n".
1577
            $data;
1578
        
1579
        // set payload
1580
        curl_setopt($ch, CURLOPT_CUSTOMREQUEST, $this->outgoing_payload);
1581
        //$t->setMarker('set curl options, executing...');
1582
        // send and receive
1583
        $this->incoming_payload = curl_exec($ch);
1584
        //$t->setMarker('executed transfer');
1585
        $data = $this->incoming_payload;
1586
1587
        $cErr = curl_error($ch);
1588
1589
        if($cErr != ''){
1590
            $err = 'cURL ERROR: '.curl_errno($ch).': '.$cErr.'<br>';
1591
            foreach(curl_getinfo($ch) as $k => $v){
1592
                $err .= "$k: $v<br>";
1593
            }
1594
            $this->setError($err);
1595
            curl_close($ch);
1596
            return false;
1597
        } else {
1598
            //echo '<pre>';
1599
            //var_dump(curl_getinfo($ch));
1600
            //echo '</pre>';
1601
        }
1602
        // close curl
1603
        curl_close($ch);
1604
        //$t->setMarker('closed curl');
1605
		
1606
        // remove 100 header
1607
        if(ereg('^HTTP/1.1 100',$data)){
1608
            if($pos = strpos($data,"\r\n\r\n") ){
1609
                $data = ltrim(substr($data,$pos));
1610
            } elseif($pos = strpos($data,"\n\n") ){
1611
                $data = ltrim(substr($data,$pos));
1612
            }
1613
        }//
1614
		
1615
        // separate content from HTTP headers
1616
        if( $pos = strpos($data,"\r\n\r\n") ){
1617
            $lb = "\r\n";
1618
        } elseif( $pos = strpos($data,"\n\n") ){
1619
            $lb = "\n";
1620
        } else {
1621
            $this->setError('no proper separation of headers and document');
1622
            return false;
1623
        }
1624
        $header_data = trim(substr($data,0,$pos));
1625
        $header_array = explode($lb,$header_data);
1626
        $data = ltrim(substr($data,$pos));
1627
        $this->debug('found proper separation of headers and document');
1628
        $this->debug('cleaned data, stringlen: '.strlen($data));
1629
        // clean headers
1630
        foreach($header_array as $header_line){
1631
            $arr = explode(':',$header_line);
1632
            $headers[trim($arr[0])] = trim($arr[1]);
1633
        }
1634
        if(strlen($data) == 0){
1635
            $this->debug('no data after headers!');
1636
            $this->setError('no data present after HTTP headers.');
1637
            return false;
1638
        }
1639
		
1640
        // decode transfer-encoding
1641
        if($headers['Transfer-Encoding'] == 'chunked'){
1642
            if(!$data = $this->decodeChunked($data)){
1643
                $this->setError('Decoding of chunked data failed');
1644
                return false;
1645
            }
1646
        }
1647
        // decode content-encoding
1648
        if($headers['Content-Encoding'] != ''){
1649
            if($headers['Content-Encoding'] == 'deflate' || $headers['Content-Encoding'] == 'gzip'){
1650
                // if decoding works, use it. else assume data wasn't gzencoded
1651
                if(function_exists('gzinflate')){
1652
                    if($headers['Content-Encoding'] == 'deflate' && $degzdata = @gzinflate($data)){
1653
                        $data = $degzdata;
1654
                    } elseif($headers['Content-Encoding'] == 'gzip' && $degzdata = gzinflate(substr($data, 10))){
1655
                        $data = $degzdata;
1656
                    } else {
1657
                        $this->setError('Errors occurred when trying to decode the data');
1658
                    }
1659
                } else {
1660
                    $this->setError('The server sent deflated data. Your php install must have the Zlib extension compiled in to support this.');
1661
                }
1662
            }
1663
        }
1664
        // set decoded payload
1665
        $this->incoming_payload = $header_data."\r\n\r\n".$data;
1666
        return $data;
1667
    }
1668
	
1669
    /**
1670
     * if authenticating, set user credentials here
1671
     *
1672
     * @param    string $user
0 ignored issues
show
Bug introduced by
There is no parameter named $user. Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

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

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

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

Loading history...
1673
     * @param    string $pass
0 ignored issues
show
Bug introduced by
There is no parameter named $pass. Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

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

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

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

Loading history...
1674
     * @access   public
1675
     */
1676
    function setCredentials($username, $password) {
1677
        $this->username = $username;
1678
        $this->password = $password;
1679
    }
1680
	
1681
    /**
1682
     * set the soapaction value
1683
     *
1684
     * @param    string $soapaction
1685
     * @access   public
1686
     */
1687
    function setSOAPAction($soapaction) {
1688
        $this->soapaction = $soapaction;
1689
    }
1690
	
1691
    /**
1692
     * use http encoding
1693
     *
1694
     * @param    string $enc encoding style. supported values: gzip, deflate, or both
1695
     * @access   public
1696
     */
1697
    function setEncoding($enc='gzip, deflate'){
1698
        $this->encoding = $enc;
1699
        $this->protocol_version = '1.1';
1700
    }
1701
	
1702
    /**
1703
     * set proxy info here
1704
     *
1705
     * @param    string $proxyhost
1706
     * @param    string $proxyport
1707
     * @access   public
1708
     */
1709
    function setProxy($proxyhost, $proxyport) {
1710
        $this->proxyhost = $proxyhost;
1711
        $this->proxyport = $proxyport;
1712
    }
1713
	
1714
    /**
1715
     * decode a string that is encoded w/ "chunked' transfer encoding
1716
     * as defined in RFC2068 19.4.6
1717
     *
1718
     * @param    string $buffer
1719
     * @returns	string
1720
     * @access   public
1721
     */
1722
    function decodeChunked($buffer){
1723
        // length := 0
1724
        $length = 0;
1725
        $new = '';
1726
	
1727
        // read chunk-size, chunk-extension (if any) and CRLF
1728
        // get the position of the linebreak
1729
        $chunkend = strpos($buffer,"\r\n") + 2;
1730
        $temp = substr($buffer,0,$chunkend);
1731
        $chunk_size = hexdec( trim($temp) );
1732
        $chunkstart = $chunkend;
1733
        // while (chunk-size > 0) {
1734
        while ($chunk_size > 0) {
1735
			
1736
            $chunkend = strpos( $buffer, "\r\n", $chunkstart + $chunk_size);
1737
            
1738
            // Just in case we got a broken connection
1739
            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...
1740
                $chunk = substr($buffer,$chunkstart);
1741
                // append chunk-data to entity-body
1742
                $new .= $chunk;
1743
                $length += strlen($chunk);
1744
                break;
1745
            }
1746
			
1747
            // read chunk-data and CRLF
1748
            $chunk = substr($buffer,$chunkstart,$chunkend-$chunkstart);
1749
            // append chunk-data to entity-body
1750
            $new .= $chunk;
1751
            // length := length + chunk-size
1752
            $length += strlen($chunk);
1753
            // read chunk-size and CRLF
1754
            $chunkstart = $chunkend + 2;
1755
			
1756
            $chunkend = strpos($buffer,"\r\n",$chunkstart)+2;
1757
            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...
1758
                break; //Just in case we got a broken connection
1759
            }
1760
            $temp = substr($buffer,$chunkstart,$chunkend-$chunkstart);
1761
            $chunk_size = hexdec( trim($temp) );
1762
            $chunkstart = $chunkend;
1763
        }
1764
        // Update headers
1765
        //$this->Header['content-length'] = $length;
1766
        //unset($this->Header['transfer-encoding']);
1767
        return $new;
1768
    }
1769
1770
}
1771
1772
?><?php
1773
1774
/**
1775
*
1776
* soap_server allows the user to create a SOAP server
1777
* that is capable of receiving messages and returning responses
1778
*
1779
* NOTE: WSDL functionality is experimental
1780
*
1781
* @author   Dietrich Ayala <[email protected]>
1782
* @version  v 0.6.3
1783
* @access   public
1784
*/
1785
class soap_server extends nusoap_base {
1786
1787
    var $service = ''; // service name
1788
    var $operations = array(); // assoc array of operations => opData
1789
    var $responseHeaders = false;
1790
    var $headers = '';
1791
    var $request = '';
1792
    var $charset_encoding = 'UTF-8';
1793
    var $fault = false;
1794
    var $result = 'successful';
1795
    var $wsdl = false;
1796
    var $externalWSDLURL = false;
1797
    var $debug_flag = true;
1798
	
1799
    /**
1800
     * constructor
1801
     * the optional parameter is a path to a WSDL file that you'd like to bind the server instance to.
1802
     *
1803
     * @param string $wsdl path or URL to a WSDL file
1804
     * @access   public
1805
     */
1806
    function soap_server($wsdl=false){
1807
        
1808
        // turn on debugging?
1809
        global $debug;
1810
        if(isset($debug)){
1811
            $this->debug_flag = 1;
0 ignored issues
show
Documentation Bug introduced by
The property $debug_flag was declared of type boolean, but 1 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...
1812
        }
1813
1814
        // wsdl
1815
        if($wsdl){
0 ignored issues
show
Bug Best Practice introduced by
The expression $wsdl of type false|string is loosely compared to true; this is ambiguous if the string can be empty. You might want to explicitly use !== false instead.

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

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
1816
            $this->wsdl = new wsdl($wsdl);
1817
            $this->externalWSDLURL = $wsdl;
0 ignored issues
show
Documentation Bug introduced by
The property $externalWSDLURL was declared of type boolean, but $wsdl 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...
1818
            if($err = $this->wsdl->getError()){
1819
                die('WSDL ERROR: '.$err);
0 ignored issues
show
Coding Style Compatibility introduced by
The method soap_server() contains an exit expression.

An exit expression should only be used in rare cases. For example, if you write a short command line script.

In most cases however, using an exit expression makes the code untestable and often causes incompatibilities with other libraries. Thus, unless you are absolutely sure it is required here, we recommend to refactor your code to avoid its usage.

Loading history...
1820
            }
1821
        }
1822
    }
1823
    
1824
    /**
1825
     * processes request and returns response
1826
     *
1827
     * @param    string $data usually is the value of $HTTP_RAW_POST_DATA
1828
     * @access   public
1829
     */
1830
    function service($data){
1831
        // print wsdl
1832
        global $QUERY_STRING, $HTTP_SERVER_VARS;
1833
        if(isset($HTTP_SERVER_VARS['QUERY_STRING'])){
1834
            $qs = $HTTP_SERVER_VARS['QUERY_STRING'];
1835
        } elseif(isset($GLOBALS['QUERY_STRING'])){
1836
            $qs = $GLOBALS['QUERY_STRING'];
1837
        } elseif(isset($QUERY_STRING) && $QUERY_STRING != ''){
1838
            $qs = $QUERY_STRING;
1839
        }
1840
        // gen wsdl
1841
        if(isset($qs) && ereg('wsdl', $qs) ){
1842
            if($this->externalWSDLURL){
1843
                header('Location: '.$this->externalWSDLURL);
1844
                exit();
0 ignored issues
show
Coding Style Compatibility introduced by
The method service() contains an exit expression.

An exit expression should only be used in rare cases. For example, if you write a short command line script.

In most cases however, using an exit expression makes the code untestable and often causes incompatibilities with other libraries. Thus, unless you are absolutely sure it is required here, we recommend to refactor your code to avoid its usage.

Loading history...
1845
            } else {
1846
                header("Content-Type: text/xml\r\n");
1847
                print $this->wsdl->serialize();
1848
                exit();
0 ignored issues
show
Coding Style Compatibility introduced by
The method service() contains an exit expression.

An exit expression should only be used in rare cases. For example, if you write a short command line script.

In most cases however, using an exit expression makes the code untestable and often causes incompatibilities with other libraries. Thus, unless you are absolutely sure it is required here, we recommend to refactor your code to avoid its usage.

Loading history...
1849
            }
1850
        }
1851
		
1852
        // print web interface
1853
        if($data == '' && $this->wsdl){
1854
            print $this->webDescription();
1855
        } else {
1856
			
1857
            // $response is the serialized response message
1858
            $response = $this->parse_request($data);
1859
            $this->debug('server sending...');
1860
            $payload = $response;
1861
            // add debug data if in debug mode
1862
            if(isset($this->debug_flag) && $this->debug_flag == 1){
1863
            	$payload .= "<!--\n".str_replace('--','- -',$this->debug_str)."\n-->";
1864
            }
1865
            // print headers
1866
            if($this->fault){
1867
                $header[] = "HTTP/1.0 500 Internal Server Error\r\n";
1868
                $header[] = "Status: 500 Internal Server Error\r\n";
1869
            } else {
1870
                $header[] = "Status: 200 OK\r\n";
1871
            }
1872
            $header[] = "Server: $this->title Server v$this->version\r\n";
1873
            $header[] = "Connection: Close\r\n";
1874
            $header[] = "Content-Type: text/xml; charset=$this->charset_encoding\r\n";
1875
            $header[] = "Content-Length: ".strlen($payload)."\r\n\r\n";
1876
            reset($header);
1877
            foreach($header as $hdr){
1878
                header($hdr);
1879
            }
1880
            $this->response = join("\r\n",$header).$payload;
1881
            print $payload;
1882
        }
1883
    }
1884
1885
    /**
1886
     * parses request and posts response
1887
     *
1888
     * @param    string $data XML string
1889
     * @return	string XML response msg
1890
     * @access   private
1891
     */
1892
    function parse_request($data='') {
1893
        if (!isset($_SERVER))
1894
            $_SERVER =& $GLOBALS['HTTP_SERVER_VARS'];
1895
        $this->debug('entering parseRequest() on '.date('H:i Y-m-d'));
1896
        $dump = '';
1897
        // get headers
1898
        if(function_exists('getallheaders')){
1899
            $this->headers = getallheaders();
1900
            foreach($this->headers as $k=>$v){
1901
                $dump .= "$k: $v\r\n";
1902
                $this->debug("$k: $v");
1903
            }
1904
            // get SOAPAction header
1905
            if(isset($this->headers['SOAPAction'])){
1906
                $this->SOAPAction = str_replace('"','',$this->headers['SOAPAction']);
1907
            }
1908
            // get the character encoding of the incoming request
1909
            if(strpos($this->headers['Content-Type'],'=')){
1910
                $enc = str_replace('"','',substr(strstr($this->headers["Content-Type"],'='),1));
1911
                if(eregi('^(ISO-8859-1|US-ASCII|UTF-8)$',$enc)){
1912
                    $this->xml_encoding = $enc;
1913
                } else {
1914
                    $this->xml_encoding = 'us-ascii';
1915
                }
1916
            }
1917
            $this->debug('got encoding: '.$this->charset_encoding);
1918
        } elseif(is_array($_SERVER)){
1919
            $this->headers['User-Agent'] = $_SERVER['HTTP_USER_AGENT'];
1920
            $this->SOAPAction = isset($_SERVER['SOAPAction']) ? $_SERVER['SOAPAction'] : '';
1921
        }
1922
        $this->request = $dump."\r\n\r\n".$data;
1923
        // parse response, get soap parser obj
1924
        $parser = new soap_parser($data,$this->charset_encoding);
1925
        // if fault occurred during message parsing
1926
        if($err = $parser->getError()){
1927
            // parser debug
1928
            $this->debug("parser debug: \n".$parser->debug_str);
1929
            $this->result = 'fault: error in msg parsing: '.$err;
1930
            $this->fault('Server',"error in msg parsing:\n".$err);
1931
            // return soapresp
1932
            return $this->fault->serialize();
1933
            // else successfully parsed request into soapval object
1934
        } else {
1935
            // get/set methodname
1936
            $this->methodname = $parser->root_struct_name;
1937
            $this->debug('method name: '.$this->methodname);
1938
            // does method exist?
1939
            if(!function_exists($this->methodname)){
1940
                // "method not found" fault here
1941
                $this->debug("method '$this->methodname' not found!");
1942
                $this->debug("parser debug: \n".$parser->debug_str);
1943
                $this->result = 'fault: method not found';
1944
                $this->fault('Server',"method '$this->methodname' not defined in service '$this->service'");
1945
                return $this->fault->serialize();
1946
            }
1947
            if($this->wsdl){
1948
                if(!$this->opData = $this->wsdl->getOperationData($this->methodname)){
1949
                    //if(
1950
                    $this->fault('Server',"Operation '$this->methodname' is not defined in the WSDL for this service");
1951
                    return $this->fault->serialize();
1952
                }
1953
            }
1954
            $this->debug("method '$this->methodname' exists");
1955
            // evaluate message, getting back parameters
1956
            $this->debug('calling parser->get_response()');
1957
            $request_data = $parser->get_response();
1958
            // parser debug
1959
            $this->debug("parser debug: \n".$parser->debug_str);
1960
            // verify that request parameters match the method's signature
1961
            if($this->verify_method($this->methodname,$request_data)){
1962
                // if there are parameters to pass
1963
                $this->debug('params var dump '.$this->varDump($request_data));
1964
                if($request_data){
1965
                    $this->debug("calling '$this->methodname' with params");
1966
                    if (! function_exists('call_user_func_array')) {
1967
                        $this->debug('calling method using eval()');
1968
                        $funcCall = $this->methodname.'(';
1969
                        foreach($request_data as $param) {
1970
                            $funcCall .= "\"$param\",";
1971
                        }
1972
                        $funcCall = substr($funcCall, 0, -1).')';
1973
                        $this->debug('function call:<br>'.$funcCall);
1974
                        @eval("\$method_response = $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...
Coding Style introduced by
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...
1975
                    } else {
1976
                        $this->debug('calling method using call_user_func_array()');
1977
                        $method_response = call_user_func_array("$this->methodname",$request_data);
1978
                    }
1979
                    $this->debug('response var dump'.$this->varDump($method_response));
1980
                } else {
1981
                    // call method w/ no parameters
1982
                    $this->debug("calling $this->methodname w/ no params");
1983
                    $m = $this->methodname;
1984
                    $method_response = @$m();
1985
                }
1986
                $this->debug("done calling method: $this->methodname, received $method_response of type".gettype($method_response));
1987
                // if we got nothing back. this might be ok (echoVoid)
1988
                if(isset($method_response) && $method_response != '' || is_bool($method_response)) {
1989
                    // if fault
1990
                    if(strtolower(get_class($method_response)) == 'soap_fault'){
1991
                        $this->debug('got a fault object from method');
1992
                        $this->fault = $method_response;
1993
                        return $method_response->serialize();
1994
                        // if return val is soapval object
1995
                    } elseif(strtolower(get_class($method_response)) == 'soapval'){
1996
                        $this->debug('got a soapval object from method');
1997
                        $return_val = $method_response->serialize();
1998
                        // returned other
1999
                    } else {
2000
                        $this->debug('got a(n) '.gettype($method_response).' from method');
2001
                        $this->debug('serializing return value');
2002
                        if($this->wsdl){
2003
                            // weak attempt at supporting multiple output params
2004
                            if(sizeof($this->opData['output']['parts']) > 1){
2005
                                $opParams = $method_response;
2006
                            } else {
2007
                                $opParams = array($method_response);
2008
                            }
2009
                            $return_val = $this->wsdl->serializeRPCParameters($this->methodname,'output',$opParams);
2010
                        } else {
2011
                            $return_val = $this->serialize_val($method_response);
2012
                        }
2013
                    }
2014
                    $this->debug('return val:'.$this->varDump($return_val));
2015
                } else {
2016
                    $return_val = '';
2017
                    $this->debug('got no response from method');
2018
                }
2019
                $this->debug('serializing response');
2020
                $payload = '<'.$this->methodname."Response>".$return_val.'</'.$this->methodname."Response>";
2021
                $this->result = 'successful';
2022
                if($this->wsdl){
2023
                    //if($this->debug_flag){
2024
                    $this->debug("WSDL debug data:\n".$this->wsdl->debug_str);
2025
                    //	}
2026
                    // Added: In case we use a WSDL, return a serialized env. WITH the usedNamespaces.
2027
                    return $this->serializeEnvelope($payload,$this->responseHeaders,$this->wsdl->usedNamespaces,$this->opData['style']);
2028
                } else {
2029
                    return $this->serializeEnvelope($payload,$this->responseHeaders);
2030
                }
2031
            } else {
2032
                // debug
2033
                $this->debug('ERROR: request not verified against method signature');
2034
                $this->result = 'fault: request failed validation against method signature';
2035
                // return fault
2036
                $this->fault('Server',"Operation '$this->methodname' not defined in service.");
2037
                return $this->fault->serialize();
2038
            }
2039
        }
2040
    }
2041
2042
    /**
2043
     * takes the value that was created by parsing the request
2044
     * and compares to the method's signature, if available.
2045
     *
2046
     * @param	mixed
2047
     * @return	boolean
2048
     * @access   private
2049
     */
2050
    function verify_method($operation,$request){
2051
        if(isset($this->wsdl) && is_object($this->wsdl)){
2052
            if($this->wsdl->getOperationData($operation)){
2053
                return true;
2054
            }
2055
        } elseif(isset($this->operations[$operation])){
2056
            return true;
2057
        }
2058
        return false;
2059
    }
2060
2061
    /**
2062
     * add a method to the dispatch map
2063
     *
2064
     * @param    string $methodname
2065
     * @param    string $in array of input values
2066
     * @param    string $out array of output values
2067
     * @access   public
2068
     */
2069
    function add_to_map($methodname,$in,$out){
2070
        $this->operations[$methodname] = array('name' => $methodname,'in' => $in,'out' => $out);
2071
    }
2072
2073
    /**
2074
     * register a service with the server
2075
     *
2076
     * @param    string $methodname
0 ignored issues
show
Bug introduced by
There is no parameter named $methodname. Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

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

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

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

Loading history...
2077
     * @param    string $in assoc array of input values: key = param name, value = param type
2078
     * @param    string $out assoc array of output values: key = param name, value = param type
2079
     * @param	string $namespace
2080
     * @param	string $soapaction
2081
     * @param	string $style (rpc|literal)
2082
     * @access   public
2083
     */
2084
    function register($name,$in=false,$out=false,$namespace=false,$soapaction=false,$style=false,$use=false){
2085
        if($this->externalWSDLURL){
2086
            die('You cannot bind to an external WSDL file, and register methods outside of it! Please choose either WSDL or no WSDL.');
0 ignored issues
show
Coding Style Compatibility introduced by
The method register() contains an exit expression.

An exit expression should only be used in rare cases. For example, if you write a short command line script.

In most cases however, using an exit expression makes the code untestable and often causes incompatibilities with other libraries. Thus, unless you are absolutely sure it is required here, we recommend to refactor your code to avoid its usage.

Loading history...
2087
        }
2088
        if(false == $in) {
0 ignored issues
show
Bug introduced by
It seems like you are loosely comparing $in of type false|string against false; this is ambiguous if the string can be empty. Consider using a strict comparison === instead.
Loading history...
2089
        }
2090
        if(false == $out) {
0 ignored issues
show
Bug introduced by
It seems like you are loosely comparing $out of type false|string against false; this is ambiguous if the string can be empty. Consider using a strict comparison === instead.
Loading history...
2091
        }
2092
        if(false == $namespace) {
0 ignored issues
show
Bug introduced by
It seems like you are loosely comparing $namespace of type false|string against false; this is ambiguous if the string can be empty. Consider using a strict comparison === instead.
Loading history...
2093
        }
2094
        if(false == $soapaction) {
0 ignored issues
show
Bug introduced by
It seems like you are loosely comparing $soapaction of type false|string against false; this is ambiguous if the string can be empty. Consider using a strict comparison === instead.
Loading history...
2095
            global $SERVER_NAME, $SCRIPT_NAME;
2096
            $soapaction = "http://$SERVER_NAME$SCRIPT_NAME";
2097
        }
2098
        if(false == $style) {
0 ignored issues
show
Bug introduced by
It seems like you are loosely comparing $style of type false|string against false; this is ambiguous if the string can be empty. Consider using a strict comparison === instead.
Loading history...
2099
            $style = "rpc";
2100
        }
2101
        if(false == $use) {
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...
2102
            $use = "encoded";
2103
        }
2104
		
2105
        $this->operations[] = array($name => array());
2106
        $this->operations[$name] = array(
2107
                                         'name' => $name,
2108
                                         'in' => $in,
2109
                                         'out' => $out,
2110
                                         'namespace' => $namespace,
2111
                                         'soapaction' => $soapaction,
2112
                                         'style' => $style);
2113
        if($this->wsdl){
2114
            $this->wsdl->addOperation($name,$in,$out,$namespace,$soapaction,$style,$use);
2115
        }
2116
        return true;
2117
    }
2118
2119
    /**
2120
     * create a fault. this also acts as a flag to the server that a fault has occured.
2121
     *
2122
     * @param	string faultcode
2123
     * @param	string faultactor
2124
     * @param	string faultstring
2125
     * @param	string faultdetail
2126
     * @access   public
2127
     */
2128
    function fault($faultcode,$faultactor,$faultstring='',$faultdetail=''){
2129
        $this->fault = new soap_fault($faultcode,$faultactor,$faultstring,$faultdetail);
2130
    }
2131
2132
    /**
2133
    * prints html description of services
2134
    *
2135
    * @access private
2136
    */
2137
    function webDescription(){
2138
		$b = '
2139
		<html><head><title>NuSOAP: '.$this->wsdl->serviceName.'</title>
2140
		<style type="text/css">
2141
		    body    { font-family: arial; color: #000000; background-color: #ffffff; margin: 0px 0px 0px 0px; }
2142
		    p       { font-family: arial; color: #000000; margin-top: 0px; margin-bottom: 12px; }
2143
		    pre { background-color: silver; padding: 5px; font-family: Courier New; font-size: x-small; color: #000000;}
2144
		    ul      { margin-top: 10px; margin-left: 20px; }
2145
		    li      { list-style-type: none; margin-top: 10px; color: #000000; }
2146
		    .content{
2147
			margin-left: 0px; padding-bottom: 2em; }
2148
		    .nav {
2149
			padding-top: 10px; padding-bottom: 10px; padding-left: 15px; font-size: .70em;
2150
			margin-top: 10px; margin-left: 0px; color: #000000;
2151
			background-color: #ccccff; width: 20%; margin-left: 20px; margin-top: 20px; }
2152
		    .title {
2153
			font-family: arial; font-size: 26px; color: #ffffff;
2154
			background-color: #999999; width: 105%; margin-left: 0px;
2155
			padding-top: 10px; padding-bottom: 10px; padding-left: 15px;}
2156
		    .hidden {
2157
			position: absolute; visibility: hidden; z-index: 200; left: 250px; top: 100px;
2158
			font-family: arial; overflow: hidden; width: 600;
2159
			padding: 20px; font-size: 10px; background-color: #999999;
2160
			layer-background-color:#FFFFFF; }
2161
		    a,a:active  { color: charcoal; font-weight: bold; }
2162
		    a:visited   { color: #666666; font-weight: bold; }
2163
		    a:hover     { color: cc3300; font-weight: bold; }
2164
		</style>
2165
		<script language="JavaScript" type="text/javascript">
2166
		<!--
2167
		// POP-UP CAPTIONS...
2168
		function lib_bwcheck(){ //Browsercheck (needed)
2169
		    this.ver=navigator.appVersion
2170
		    this.agent=navigator.userAgent
2171
		    this.dom=document.getElementById?1:0
2172
		    this.opera5=this.agent.indexOf("Opera 5")>-1
2173
		    this.ie5=(this.ver.indexOf("MSIE 5")>-1 && this.dom && !this.opera5)?1:0;
2174
		    this.ie6=(this.ver.indexOf("MSIE 6")>-1 && this.dom && !this.opera5)?1:0;
2175
		    this.ie4=(document.all && !this.dom && !this.opera5)?1:0;
2176
		    this.ie=this.ie4||this.ie5||this.ie6
2177
		    this.mac=this.agent.indexOf("Mac")>-1
2178
		    this.ns6=(this.dom && parseInt(this.ver) >= 5) ?1:0;
2179
		    this.ns4=(document.layers && !this.dom)?1:0;
2180
		    this.bw=(this.ie6 || this.ie5 || this.ie4 || this.ns4 || this.ns6 || this.opera5)
2181
		    return this
2182
		}
2183
		var bw = new lib_bwcheck()
2184
		//Makes crossbrowser object.
2185
		function makeObj(obj){
2186
		    this.evnt=bw.dom? document.getElementById(obj):bw.ie4?document.all[obj]:bw.ns4?document.layers[obj]:0;
2187
		    if(!this.evnt) return false
2188
		    this.css=bw.dom||bw.ie4?this.evnt.style:bw.ns4?this.evnt:0;
2189
		    this.wref=bw.dom||bw.ie4?this.evnt:bw.ns4?this.css.document:0;
2190
		    this.writeIt=b_writeIt;
2191
		    return this
2192
		}
2193
		// A unit of measure that will be added when setting the position of a layer.
2194
		//var px = bw.ns4||window.opera?"":"px";
2195
		function b_writeIt(text){
2196
		    if (bw.ns4){this.wref.write(text);this.wref.close()}
2197
		    else this.wref.innerHTML = text
2198
		}
2199
		//Shows the messages
2200
		var oDesc;
2201
		function popup(divid){
2202
		    if(oDesc = new makeObj(divid)){
2203
			oDesc.css.visibility = "visible"
2204
		    }
2205
		}
2206
		function popout(){ // Hides message
2207
		    if(oDesc) oDesc.css.visibility = "hidden"
2208
		}
2209
		//-->
2210
		</script>
2211
		</head>
2212
		<body>
2213
		<div class=content>
2214
			<br><br>
2215
			<div class=title>'.$this->wsdl->serviceName.'</div>
2216
			<div class=nav>
2217
				<p>View the <a href="?wsdl">WSDL</a> for the service.
2218
				Click on an operation name to view it&apos;s details.</p>
2219
				<ul>';
2220
				foreach($this->wsdl->getOperations() as $op => $data){
2221
				    $b .= "<li><a href='#' onclick=\"popup('$op')\">$op</a></li>";
2222
				    // create hidden div
2223
				    $b .= "<div id='$op' class='hidden'>
2224
				    <a href='#' onclick='popout()'><font color='#ffffff'>Close</font></a><br><br>";
2225
				    foreach($data as $donnie => $marie){ // loop through opdata
2226
                                        if($donnie == 'input' || $donnie == 'output'){ // show input/output data
2227
                                            $b .= "<font color='white'>".ucfirst($donnie).':</font><br>';
2228
                                            foreach($marie as $captain => $tenille){ // loop through data
2229
                                                if($captain == 'parts'){ // loop thru parts
2230
                                                    $b .= "&nbsp;&nbsp;$captain:<br>";
2231
                                                    //if(is_array($tenille)){
2232
                                                    foreach($tenille as $joanie => $chachi){
2233
                                                        $b .= "&nbsp;&nbsp;&nbsp;&nbsp;$joanie: $chachi<br>";
2234
                                                    }
2235
                                                    //}
2236
                                                } else {
2237
                                                    $b .= "&nbsp;&nbsp;$captain: $tenille<br>";
2238
                                                }
2239
                                            }
2240
                                        } else {
2241
                                            $b .= "<font color='white'>".ucfirst($donnie).":</font> $marie<br>";
2242
                                        }
2243
				    }
2244
                                    $b .= '</div>';
2245
				}
2246
				$b .= '
2247
				<ul>
2248
			</div>
2249
		</div></body></html>';
2250
                return $b;
2251
    }
2252
2253
    /**
2254
    * sets up wsdl object
2255
    * this acts as a flag to enable internal WSDL generation
2256
    * NOTE: NOT FUNCTIONAL
2257
    *
2258
    * @param string $serviceName, name of the service
0 ignored issues
show
Documentation introduced by
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...
2259
    * @param string $namespace, tns namespace
0 ignored issues
show
Documentation introduced by
There is no parameter named $namespace,. Did you maybe mean $namespace?

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...
2260
    */
2261
    function configureWSDL($serviceName,$namespace = false,$endpoint = false,$style='rpc', $transport = 'http://schemas.xmlsoap.org/soap/http') {
2262
        if (!isset($_SERVER))
2263
            $_SERVER =& $GLOBALS['HTTP_SERVER_VARS'];
2264
        $SERVER_NAME = isset($_SERVER['SERVER_NAME']) ? $_SERVER['SERVER_NAME'] : $GLOBALS['SERVER_NAME'];
2265
        $SCRIPT_NAME = isset($_SERVER['SCRIPT_NAME']) ? $_SERVER['SCRIPT_NAME'] : $GLOBALS['SCRIPT_NAME'];
2266
        if(false == $namespace) {
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...
2267
            $namespace = "http://$SERVER_NAME/soap/$serviceName";
2268
        }
2269
        
2270
        if(false == $endpoint) {
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...
2271
            $endpoint = "http://$SERVER_NAME$SCRIPT_NAME";
2272
        }
2273
        
2274
        $this->wsdl = new wsdl;
2275
        $this->wsdl->serviceName = $serviceName;
0 ignored issues
show
Bug introduced by
The property serviceName does not seem to exist in wsdl.

An attempt at access to an undefined property has been detected. This may either be a typographical error or the property has been renamed but there are still references to its old name.

If you really want to allow access to undefined properties, you can define magic methods to allow access. See the php core documentation on Overloading.

Loading history...
2276
        $this->wsdl->endpoint = $endpoint;
2277
        $this->wsdl->namespaces['tns'] = $namespace;
2278
        $this->wsdl->namespaces['soap'] = 'http://schemas.xmlsoap.org/wsdl/soap/';
2279
        $this->wsdl->namespaces['wsdl'] = 'http://schemas.xmlsoap.org/wsdl/';
2280
        $this->wsdl->bindings[$serviceName.'Binding'] = array(
2281
                                                              'name'=>$serviceName.'Binding',
2282
                                                              'style'=>$style,
2283
                                                              'transport'=>$transport,
2284
                                                              'portType'=>$serviceName.'PortType');
2285
        $this->wsdl->ports[$serviceName.'Port'] = array(
2286
                                                        'binding'=>$serviceName.'Binding',
2287
                                                        'location'=>$endpoint,
2288
                                                        'bindingType'=>'http://schemas.xmlsoap.org/wsdl/soap/');
2289
    }
2290
}
2291
2292
?><?php
2293
2294
/**
2295
 * parses a WSDL file, allows access to it's data, other utility methods
2296
 * 
2297
 * @author   Dietrich Ayala <[email protected]>
2298
 * @version  v 0.6.3
2299
 * @access public 
2300
 */
2301
class wsdl extends XMLSchema {
2302
    var $wsdl; 
2303
    // define internal arrays of bindings, ports, operations, messages, etc.
2304
    var $message = array();
2305
    var $complexTypes = array();
2306
    var $messages = array();
2307
    var $currentMessage;
2308
    var $currentOperation;
2309
    var $portTypes = array();
2310
    var $currentPortType;
2311
    var $bindings = array();
2312
    var $currentBinding;
2313
    var $ports = array();
2314
    var $currentPort;
2315
    var $opData = array();
2316
    var $status = '';
2317
    var $documentation = false;
2318
    var $endpoint = ''; 
2319
    // array of wsdl docs to import
2320
    var $import = array(); 
2321
    // parser vars
2322
    var $parser;
2323
    var $position = 0;
2324
    var $depth = 0;
2325
    var $depth_array = array();
2326
    var $usedNamespaces = array();
2327
    // for getting wsdl
2328
    var $proxyhost = '';
2329
    var $proxyport = '';
2330
    
2331
    /**
2332
     * constructor
2333
     * 
2334
     * @param string $wsdl WSDL document URL
2335
     * @access public 
2336
     */
2337
    function wsdl($wsdl = '',$proxyhost=false,$proxyport=false){
2338
        $this->wsdl = $wsdl;
2339
        $this->proxyhost = $proxyhost;
0 ignored issues
show
Documentation Bug introduced by
The property $proxyhost was declared of type string, but $proxyhost is of type boolean. 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...
2340
        $this->proxyport = $proxyport;
0 ignored issues
show
Documentation Bug introduced by
The property $proxyport was declared of type string, but $proxyport is of type boolean. 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...
2341
        
2342
        // parse wsdl file
2343
        if ($wsdl != "") {
2344
            $this->debug('initial wsdl file: ' . $wsdl);
2345
            $this->parseWSDL($wsdl);
2346
        } 
2347
        // imports
2348
        if (sizeof($this->import) > 0) {
2349
            foreach($this->import as $ns => $url) {
2350
                $this->debug('importing wsdl from ' . $url);
2351
                $this->parseWSDL($url);
2352
            } 
2353
        } 
2354
    } 
2355
2356
    /**
2357
     * parses the wsdl document
2358
     * 
2359
     * @param string $wsdl path or URL
2360
     * @access private 
2361
     */
2362
    function parseWSDL($wsdl = '')
2363
    {
2364
        if ($wsdl == '') {
2365
            $this->debug('no wsdl passed to parseWSDL()!!');
2366
            $this->setError('no wsdl passed to parseWSDL()!!');
2367
            return false;
2368
        } 
2369
2370
        $this->debug('getting ' . $wsdl);
2371
        
2372
        // parse $wsdl for url format
2373
        $wsdl_props = parse_url($wsdl);
2374
2375
        if (isset($wsdl_props['host'])) {
2376
        	
2377
            // get wsdl
2378
            $tr = new soap_transport_http($wsdl);
2379
            $tr->request_method = 'GET';
2380
            $tr->useSOAPAction = false;
2381
            if($this->proxyhost && $this->proxyport){
2382
                $tr->setProxy($this->proxyhost,$this->proxyport);
2383
            }
2384
            if (isset($wsdl_props['user'])) {
2385
                $tr->setCredentials($wsdl_props['user'],$wsdl_props['pass']);
2386
            }
2387
            $wsdl_string = $tr->send('');
2388
            // catch errors
2389
            if($err = $tr->getError() ){
2390
                $this->debug('HTTP ERROR: '.$err);
2391
                $this->setError('HTTP ERROR: '.$err);
2392
                return false;
2393
            }
2394
            unset($tr);
2395
            /* $wsdl seems to be a valid url, not a file path, do an fsockopen/HTTP GET
2396
            $fsockopen_timeout = 30; 
2397
            // check if a port value is supplied in url
2398
            if (isset($wsdl_props['port'])) {
2399
                // yes
2400
                $wsdl_url_port = $wsdl_props['port'];
2401
            } else {
2402
                // no, assign port number, based on url protocol (scheme)
2403
                switch ($wsdl_props['scheme']) {
2404
                    case ('https') :
2405
                    case ('ssl') :
2406
                    case ('tls') :
2407
                        $wsdl_url_port = 443;
2408
                        break;
2409
                    case ('http') :
2410
                    default :
2411
                        $wsdl_url_port = 80;
2412
                } 
2413
            } 
2414
            // FIXME: should implement SSL/TLS support here if CURL is available
2415
            if ($fp = fsockopen($wsdl_props['host'], $wsdl_url_port, $fsockopen_errnum, $fsockopen_errstr, $fsockopen_timeout)) {
2416
                // perform HTTP GET for WSDL file
2417
                // 10.9.02 - added poulter fix for doing this properly
2418
                $sHeader = "GET " . $wsdl_props['path'];
2419
                if (isset($wsdl_props['query'])) {
2420
                    $sHeader .= "?" . $wsdl_props['query'];
2421
                } 
2422
                $sHeader .= " HTTP/1.0\r\n";
2423
2424
                if (isset($wsdl_props['user'])) {
2425
                    $base64auth = base64_encode($wsdl_props['user'] . ":" . $wsdl_props['pass']);
2426
                    $sHeader .= "Authorization: Basic $base64auth\r\n";
2427
                }
2428
				$sHeader .= "Host: " . $wsdl_props['host'] . ( isset($wsdl_props['port']) ? ":".$wsdl_props['port'] : "" ) . "\r\n\r\n";
2429
                fputs($fp, $sHeader);
2430
2431
                while (fgets($fp, 1024) != "\r\n") {
2432
                    // do nothing, just read/skip past HTTP headers
2433
                    // FIXME: should actually detect HTTP response code, and act accordingly if error
2434
                    // HTTP headers end with extra CRLF before content body
2435
                } 
2436
                // read in WSDL just like regular fopen()
2437
                $wsdl_string = '';
2438
                while ($data = fread($fp, 32768)) {
2439
                    $wsdl_string .= $data;
2440
                } 
2441
                fclose($fp);
2442
            } else {
2443
                $this->setError('bad path to WSDL file.');
2444
                return false;
2445
            }
2446
            */
2447
        } else {
2448
            // $wsdl seems to be a non-url file path, do the regular fopen
2449
            if ($fp = @fopen($wsdl, 'r')) {
2450
                $wsdl_string = '';
2451
                while ($data = fread($fp, 32768)) {
2452
                    $wsdl_string .= $data;
2453
                } 
2454
                fclose($fp);
2455
            } else {
2456
                $this->setError('bad path to WSDL file.');
2457
                return false;
2458
            } 
2459
        }
2460
        // end new code added
2461
        // Create an XML parser.
2462
        $this->parser = xml_parser_create(); 
2463
        // Set the options for parsing the XML data.
2464
        // xml_parser_set_option($parser, XML_OPTION_SKIP_WHITE, 1);
2465
        xml_parser_set_option($this->parser, XML_OPTION_CASE_FOLDING, 0); 
2466
        // Set the object for the parser.
2467
        xml_set_object($this->parser, $this); 
2468
        // Set the element handlers for the parser.
2469
        xml_set_element_handler($this->parser, 'start_element', 'end_element');
2470
        xml_set_character_data_handler($this->parser, 'character_data');
2471
        // Parse the XML file.
2472
        if (!xml_parse($this->parser, $wsdl_string, true)) {
2473
            // Display an error message.
2474
            $errstr = sprintf(
2475
                              'XML error on line %d: %s',
2476
                              xml_get_current_line_number($this->parser),
2477
                              xml_error_string(xml_get_error_code($this->parser))
2478
                              );
2479
            $this->debug('XML parse error: ' . $errstr);
2480
            $this->setError('Parser error: ' . $errstr);
2481
            return false;
2482
        } 
2483
        // free the parser
2484
        xml_parser_free($this->parser);
2485
        // catch wsdl parse errors
2486
        if($this->getError()){
2487
            return false;
2488
        }
2489
        // add new data to operation data
2490
        foreach($this->bindings as $binding => $bindingData) {
2491
            if (isset($bindingData['operations']) && is_array($bindingData['operations'])) {
2492
                foreach($bindingData['operations'] as $operation => $data) {
2493
                    $this->debug('post-parse data gathering for ' . $operation);
2494
                    $this->bindings[$binding]['operations'][$operation]['input'] = 
2495
						isset($this->bindings[$binding]['operations'][$operation]['input']) ? 
2496
						array_merge($this->bindings[$binding]['operations'][$operation]['input'], $this->portTypes[ $bindingData['portType'] ][$operation]['input']) :
2497
						$this->portTypes[ $bindingData['portType'] ][$operation]['input'];
2498
                    $this->bindings[$binding]['operations'][$operation]['output'] = 
2499
						isset($this->bindings[$binding]['operations'][$operation]['output']) ?
2500
						array_merge($this->bindings[$binding]['operations'][$operation]['output'], $this->portTypes[ $bindingData['portType'] ][$operation]['output']) :
2501
						$this->portTypes[ $bindingData['portType'] ][$operation]['output'];
2502
                    if(isset($this->messages[ $this->bindings[$binding]['operations'][$operation]['input']['message'] ])){
2503
						$this->bindings[$binding]['operations'][$operation]['input']['parts'] = $this->messages[ $this->bindings[$binding]['operations'][$operation]['input']['message'] ];
2504
					}
2505
					if(isset($this->messages[ $this->bindings[$binding]['operations'][$operation]['output']['message'] ])){
2506
                   		$this->bindings[$binding]['operations'][$operation]['output']['parts'] = $this->messages[ $this->bindings[$binding]['operations'][$operation]['output']['message'] ];
2507
                    }
2508
					if (isset($bindingData['style'])) {
2509
                        $this->bindings[$binding]['operations'][$operation]['style'] = $bindingData['style'];
2510
                    }
2511
                    $this->bindings[$binding]['operations'][$operation]['transport'] = isset($bindingData['transport']) ? $bindingData['transport'] : '';
2512
                    $this->bindings[$binding]['operations'][$operation]['documentation'] = isset($this->portTypes[ $bindingData['portType'] ][$operation]['documentation']) ? $this->portTypes[ $bindingData['portType'] ][$operation]['documentation'] : '';
2513
                    $this->bindings[$binding]['operations'][$operation]['endpoint'] = isset($bindingData['endpoint']) ? $bindingData['endpoint'] : '';
2514
                } 
2515
            } 
2516
        }
2517
        return true;
2518
    } 
2519
2520
    /**
2521
     * start-element handler
2522
     * 
2523
     * @param string $parser XML parser object
2524
     * @param string $name element name
2525
     * @param string $attrs associative array of attributes
2526
     * @access private 
2527
     */
2528
    function start_element($parser, $name, $attrs)
2529
    {
2530
        if ($this->status == 'schema' || ereg('schema$', $name)) {
2531
            // $this->debug("startElement for $name ($attrs[name]). status = $this->status (".$this->getLocalPart($name).")");
2532
            $this->status = 'schema';
2533
            $this->schemaStartElement($parser, $name, $attrs);
2534
        } else {
2535
            // position in the total number of elements, starting from 0
2536
            $pos = $this->position++;
2537
            $depth = $this->depth++; 
2538
            // set self as current value for this depth
2539
            $this->depth_array[$depth] = $pos;
2540
            $this->message[$pos] = array('cdata' => ''); 
2541
            // get element prefix
2542
            if (ereg(':', $name)) {
2543
                // get ns prefix
2544
                $prefix = substr($name, 0, strpos($name, ':')); 
2545
                // get ns
2546
                $namespace = isset($this->namespaces[$prefix]) ? $this->namespaces[$prefix] : ''; 
2547
                // get unqualified name
2548
                $name = substr(strstr($name, ':'), 1);
2549
            } 
2550
2551
            if (count($attrs) > 0) {
2552
                foreach($attrs as $k => $v) {
0 ignored issues
show
Bug introduced by
The expression $attrs of type string is not traversable.
Loading history...
2553
                    // if ns declarations, add to class level array of valid namespaces
2554
                    if (ereg("^xmlns", $k)) {
2555
                        if ($ns_prefix = substr(strrchr($k, ':'), 1)) {
2556
                            $this->namespaces[$ns_prefix] = $v;
2557
                        } else {
2558
                            $this->namespaces['ns' . (count($this->namespaces) + 1)] = $v;
2559
                        } 
2560
                        if ($v == 'http://www.w3.org/2001/XMLSchema' || $v == 'http://www.w3.org/1999/XMLSchema') {
2561
                            $this->XMLSchemaVersion = $v;
2562
                            $this->namespaces['xsi'] = $v . '-instance';
2563
                        } 
2564
                    } //  
2565
                    // expand each attribute
2566
                    $k = strpos($k, ':') ? $this->expandQname($k) : $k;
2567
                    if ($k != 'location' && $k != 'soapAction' && $k != 'namespace') {
2568
                        $v = strpos($v, ':') ? $this->expandQname($v) : $v;
2569
                    } 
2570
                    $eAttrs[$k] = $v;
2571
                } 
2572
                $attrs = $eAttrs;
2573
            } else {
2574
                $attrs = array();
2575
            } 
2576
            // find status, register data
2577
            switch ($this->status) {
2578
                case 'message':
2579
                    if ($name == 'part') {
2580
                    	if (isset($attrs['type'])) {
2581
		                    $this->debug("msg " . $this->currentMessage . ": found part $attrs[name]: " . implode(',', $attrs));
2582
		                    $this->messages[$this->currentMessage][$attrs['name']] = $attrs['type'];
2583
            			} 
2584
			            if (isset($attrs['element'])) {
2585
			                $this->messages[$this->currentMessage][$attrs['name']] = $attrs['element'];
2586
			            } 
2587
        			} 
2588
        			break;
2589
			    case 'portType':
2590
			        switch ($name) {
2591
			            case 'operation':
2592
			                $this->currentPortOperation = $attrs['name'];
2593
			                $this->debug("portType $this->currentPortType operation: $this->currentPortOperation");
2594
			                if (isset($attrs['parameterOrder'])) {
2595
			                	$this->portTypes[$this->currentPortType][$attrs['name']]['parameterOrder'] = $attrs['parameterOrder'];
2596
			        		} 
2597
			        		break;
2598
					    case 'documentation':
2599
					        $this->documentation = true;
2600
					        break; 
2601
					    // merge input/output data
2602
					    default:
2603
					        $m = isset($attrs['message']) ? $this->getLocalPart($attrs['message']) : '';
2604
					        $this->portTypes[$this->currentPortType][$this->currentPortOperation][$name]['message'] = $m;
2605
					        break;
2606
					} 
2607
			    	break;
2608
				case 'binding':
2609
				    switch ($name) {
2610
				        case 'binding': 
2611
				            // get ns prefix
2612
				            if (isset($attrs['style'])) {
2613
				            $this->bindings[$this->currentBinding]['prefix'] = $prefix;
2614
					    	} 
2615
					    	$this->bindings[$this->currentBinding] = array_merge($this->bindings[$this->currentBinding], $attrs);
2616
					    	break;
2617
						case 'header':
2618
						    $this->bindings[$this->currentBinding]['operations'][$this->currentOperation][$this->opStatus]['headers'][] = $attrs;
2619
						    break;
2620
						case 'operation':
2621
						    if (isset($attrs['soapAction'])) {
2622
						        $this->bindings[$this->currentBinding]['operations'][$this->currentOperation]['soapAction'] = $attrs['soapAction'];
2623
						    } 
2624
						    if (isset($attrs['style'])) {
2625
						        $this->bindings[$this->currentBinding]['operations'][$this->currentOperation]['style'] = $attrs['style'];
2626
						    } 
2627
						    if (isset($attrs['name'])) {
2628
						        $this->currentOperation = $attrs['name'];
2629
						        $this->debug("current binding operation: $this->currentOperation");
2630
						        $this->bindings[$this->currentBinding]['operations'][$this->currentOperation]['name'] = $attrs['name'];
2631
						        $this->bindings[$this->currentBinding]['operations'][$this->currentOperation]['binding'] = $this->currentBinding;
2632
						        $this->bindings[$this->currentBinding]['operations'][$this->currentOperation]['endpoint'] = isset($this->bindings[$this->currentBinding]['endpoint']) ? $this->bindings[$this->currentBinding]['endpoint'] : '';
2633
						    } 
2634
						    break;
2635
						case 'input':
2636
						    $this->opStatus = 'input';
2637
						    break;
2638
						case 'output':
2639
						    $this->opStatus = 'output';
2640
						    break;
2641
						case 'body':
2642
						    if (isset($this->bindings[$this->currentBinding]['operations'][$this->currentOperation][$this->opStatus])) {
2643
						        $this->bindings[$this->currentBinding]['operations'][$this->currentOperation][$this->opStatus] = array_merge($this->bindings[$this->currentBinding]['operations'][$this->currentOperation][$this->opStatus], $attrs);
2644
						    } else {
2645
						        $this->bindings[$this->currentBinding]['operations'][$this->currentOperation][$this->opStatus] = $attrs;
2646
						    } 
2647
						    break;
2648
					} 
2649
					break;
2650
				case 'service':
2651
					switch ($name) {
2652
					    case 'port':
2653
					        $this->currentPort = $attrs['name'];
2654
					        $this->debug('current port: ' . $this->currentPort);
2655
					        $this->ports[$this->currentPort]['binding'] = $this->getLocalPart($attrs['binding']);
2656
					
2657
					        break;
2658
					    case 'address':
2659
					        $this->ports[$this->currentPort]['location'] = $attrs['location'];
2660
					        $this->ports[$this->currentPort]['bindingType'] = $namespace;
2661
					        $this->bindings[ $this->ports[$this->currentPort]['binding'] ]['bindingType'] = $namespace;
2662
					        $this->bindings[ $this->ports[$this->currentPort]['binding'] ]['endpoint'] = $attrs['location'];
2663
					        break;
2664
					} 
2665
					break;
2666
			} 
2667
		// set status
2668
		switch ($name) {
2669
			case "import":
2670
			    if (isset($attrs['location'])) {
2671
			    	$this->import[$attrs['namespace']] = $attrs['location'];
2672
				} 
2673
				break;
2674
			case 'types':
2675
				$this->status = 'schema';
2676
				break;
2677
			case 'message':
2678
				$this->status = 'message';
2679
				$this->messages[$attrs['name']] = array();
2680
				$this->currentMessage = $attrs['name'];
2681
				break;
2682
			case 'portType':
2683
				$this->status = 'portType';
2684
				$this->portTypes[$attrs['name']] = array();
2685
				$this->currentPortType = $attrs['name'];
2686
				break;
2687
			case "binding":
2688
				if (isset($attrs['name'])) {
2689
				// get binding name
2690
					if (strpos($attrs['name'], ':')) {
2691
			    		$this->currentBinding = $this->getLocalPart($attrs['name']);
2692
					} else {
2693
			    		$this->currentBinding = $attrs['name'];
2694
					} 
2695
					$this->status = 'binding';
2696
					$this->bindings[$this->currentBinding]['portType'] = $this->getLocalPart($attrs['type']);
2697
					$this->debug("current binding: $this->currentBinding of portType: " . $attrs['type']);
2698
				} 
2699
				break;
2700
			case 'service':
2701
				$this->serviceName = $attrs['name'];
2702
				$this->status = 'service';
2703
				$this->debug('current service: ' . $this->serviceName);
2704
				break;
2705
			case 'definitions':
2706
				foreach ($attrs as $name => $value) {
2707
					$this->wsdl_info[$name] = $value;
2708
				} 
2709
				break;
2710
			} 
2711
		} 
2712
	} 
2713
2714
    /**
2715
     * end-element handler
2716
     * 
2717
     * @param string $parser XML parser object
2718
     * @param string $name element name
2719
     * @access private 
2720
     */
2721
    function end_element($parser, $name){ 
2722
        // unset schema status
2723
        if (ereg('types$', $name) || ereg('schema$', $name)) {
2724
            $this->status = "";
2725
        } 
2726
        if ($this->status == 'schema') {
2727
            $this->schemaEndElement($parser, $name);
2728
        } else {
2729
            // bring depth down a notch
2730
            $this->depth--;
2731
        } 
2732
        // end documentation
2733
        if ($this->documentation) {
2734
            $this->portTypes[$this->currentPortType][$this->currentPortOperation]['documentation'] = $this->documentation;
2735
            $this->documentation = false;
2736
        } 
2737
    } 
2738
2739
    /**
2740
     * element content handler
2741
     * 
2742
     * @param string $parser XML parser object
2743
     * @param string $data element content
2744
     * @access private 
2745
     */
2746
    function character_data($parser, $data)
2747
    {
2748
        $pos = isset($this->depth_array[$this->depth]) ? $this->depth_array[$this->depth] : 0;
2749
        if (isset($this->message[$pos]['cdata'])) {
2750
            $this->message[$pos]['cdata'] .= $data;
2751
        } 
2752
        if ($this->documentation) {
2753
            $this->documentation .= $data;
2754
        } 
2755
    } 
2756
	
2757
    function getBindingData($binding)
2758
    {
2759
        if (is_array($this->bindings[$binding])) {
2760
            return $this->bindings[$binding];
2761
        } 
2762
    }
2763
	
2764
    /**
2765
     * returns an assoc array of operation names => operation data
2766
     * NOTE: currently only supports multiple services of differing binding types
2767
     * This method needs some work
2768
     * 
2769
     * @param string $bindingType eg: soap, smtp, dime (only soap is currently supported)
2770
     * @return array 
2771
     * @access public 
2772
     */
2773
    function getOperations($bindingType = 'soap')
2774
    {
2775
        if ($bindingType == 'soap') {
2776
            $bindingType = 'http://schemas.xmlsoap.org/wsdl/soap/';
2777
        }
2778
        // loop thru ports
2779
        foreach($this->ports as $port => $portData) {
2780
            // binding type of port matches parameter
2781
            if ($portData['bindingType'] == $bindingType) {
2782
                // get binding
2783
                return $this->bindings[ $portData['binding'] ]['operations'];
2784
            }
2785
        } 
2786
        return array();
2787
    } 
2788
	
2789
    /**
2790
     * returns an associative array of data necessary for calling an operation
2791
     * 
2792
     * @param string $operation , name of operation
2793
     * @param string $bindingType , type of binding eg: soap
2794
     * @return array 
2795
     * @access public 
2796
     */
2797
    function getOperationData($operation, $bindingType = 'soap')
2798
    {
2799
        if ($bindingType == 'soap') {
2800
            $bindingType = 'http://schemas.xmlsoap.org/wsdl/soap/';
2801
        }
2802
        // loop thru ports
2803
        foreach($this->ports as $port => $portData) {
2804
            // binding type of port matches parameter
2805
            if ($portData['bindingType'] == $bindingType) {
2806
                // get binding
2807
                //foreach($this->bindings[ $portData['binding'] ]['operations'] as $bOperation => $opData) {
2808
                foreach(array_keys($this->bindings[ $portData['binding'] ]['operations']) as $bOperation) {
2809
                    if ($operation == $bOperation) {
2810
                        $opData = $this->bindings[ $portData['binding'] ]['operations'][$operation];
2811
                        return $opData;
2812
                    } 
2813
                } 
2814
            }
2815
        } 
2816
    }
2817
	
2818
    /**
2819
     * serialize the parsed wsdl
2820
     * 
2821
     * @return string , serialization of WSDL
2822
     * @access public 
2823
     */
2824
    function serialize()
2825
    {
2826
        $xml = '<?xml version="1.0"?><definitions';
2827
        foreach($this->namespaces as $k => $v) {
2828
            $xml .= " xmlns:$k=\"$v\"";
2829
        } 
2830
        // 10.9.02 - add poulter fix for wsdl and tns declarations
2831
        if (isset($this->namespaces['wsdl'])) {
2832
            $xml .= " xmlns=\"" . $this->namespaces['wsdl'] . "\"";
2833
        } 
2834
        if (isset($this->namespaces['tns'])) {
2835
            $xml .= " targetNamespace=\"" . $this->namespaces['tns'] . "\"";
2836
        } 
2837
        $xml .= '>'; 
2838
        // imports
2839
        if (sizeof($this->import) > 0) {
2840
            foreach($this->import as $ns => $url) {
2841
                $xml .= '<import location="' . $url . '" namespace="' . $ns . '" />';
2842
            } 
2843
        } 
2844
        // types
2845
        if (count($this->complexTypes)>=1) {
2846
            $xml .= '<types>';
2847
            $xml .= $this->serializeSchema();
2848
            $xml .= '</types>';
2849
        } 
2850
        // messages
2851
        if (count($this->messages) >= 1) {
2852
            foreach($this->messages as $msgName => $msgParts) {
2853
                $xml .= '<message name="' . $msgName . '">';
2854
                foreach($msgParts as $partName => $partType) {
2855
                    // print 'serializing '.$partType.', sv: '.$this->XMLSchemaVersion.'<br>';
2856
                    if (strpos($partType, ':')) {
2857
                        $typePrefix = $this->getPrefixFromNamespace($this->getPrefix($partType));
2858
                    } elseif (isset($this->typemap[$this->namespaces['xsd']][$partType])) {
2859
                        // print 'checking typemap: '.$this->XMLSchemaVersion.'<br>';
2860
                        $typePrefix = 'xsd';
2861
                    } else {
2862
                        foreach($this->typemap as $ns => $types) {
2863
                            if (isset($types[$partType])) {
2864
                                $typePrefix = $this->getPrefixFromNamespace($ns);
2865
                            } 
2866
                        } 
2867
                        if (!isset($typePrefix)) {
2868
                            die("$partType has no namespace!");
0 ignored issues
show
Coding Style Compatibility introduced by
The method serialize() contains an exit expression.

An exit expression should only be used in rare cases. For example, if you write a short command line script.

In most cases however, using an exit expression makes the code untestable and often causes incompatibilities with other libraries. Thus, unless you are absolutely sure it is required here, we recommend to refactor your code to avoid its usage.

Loading history...
2869
                        } 
2870
                    } 
2871
                    $xml .= '<part name="' . $partName . '" type="' . $typePrefix . ':' . $this->getLocalPart($partType) . '" />';
2872
                } 
2873
                $xml .= '</message>';
2874
            } 
2875
        } 
2876
        // bindings & porttypes
2877
        if (count($this->bindings) >= 1) {
2878
            $binding_xml = '';
2879
            $portType_xml = '';
2880
            foreach($this->bindings as $bindingName => $attrs) {
2881
                $binding_xml .= '<binding name="' . $bindingName . '" type="tns:' . $attrs['portType'] . '">';
2882
                $binding_xml .= '<soap:binding style="' . $attrs['style'] . '" transport="' . $attrs['transport'] . '"/>';
2883
                $portType_xml .= '<portType name="' . $attrs['portType'] . '">';
2884
                foreach($attrs['operations'] as $opName => $opParts) {
2885
                    $binding_xml .= '<operation name="' . $opName . '">';
2886
                    $binding_xml .= '<soap:operation soapAction="' . $opParts['soapAction'] . '" style="'. $attrs['style'] . '"/>';
2887
                    $binding_xml .= '<input><soap:body use="' . $opParts['input']['use'] . '" namespace="' . $opParts['input']['namespace'] . '" encodingStyle="' . $opParts['input']['encodingStyle'] . '"/></input>';
2888
                    $binding_xml .= '<output><soap:body use="' . $opParts['output']['use'] . '" namespace="' . $opParts['output']['namespace'] . '" encodingStyle="' . $opParts['output']['encodingStyle'] . '"/></output>';
2889
                    $binding_xml .= '</operation>';
2890
                    $portType_xml .= '<operation name="' . $opParts['name'] . '"';
2891
                    if (isset($opParts['parameterOrder'])) {
2892
                        $portType_xml .= ' parameterOrder="' . $opParts['parameterOrder'] . '"';
2893
                    } 
2894
                    $portType_xml .= '>';
2895
                    $portType_xml .= '<input message="tns:' . $opParts['input']['message'] . '"/>';
2896
                    $portType_xml .= '<output message="tns:' . $opParts['output']['message'] . '"/>';
2897
                    $portType_xml .= '</operation>';
2898
                } 
2899
                $portType_xml .= '</portType>';
2900
                $binding_xml .= '</binding>';
2901
            } 
2902
            $xml .= $portType_xml . $binding_xml;
2903
        } 
2904
        // services
2905
        $xml .= '<service name="' . $this->serviceName . '">';
2906
        if (count($this->ports) >= 1) {
2907
            foreach($this->ports as $pName => $attrs) {
2908
                $xml .= '<port name="' . $pName . '" binding="tns:' . $attrs['binding'] . '">';
2909
                $xml .= '<soap:address location="' . $attrs['location'] . '"/>';
2910
                $xml .= '</port>';
2911
            } 
2912
        } 
2913
        $xml .= '</service>';
2914
        return $xml . '</definitions>';
2915
    } 
2916
	
2917
    /**
2918
     * serialize a PHP value according to a WSDL message definition
2919
     * 
2920
     * TODO
2921
     * - multi-ref serialization
2922
     * - validate PHP values against type definitions, return errors if invalid
2923
     * 
2924
     * @param string $ type name
2925
     * @param mixed $ param value
2926
     * @return mixed new param or false if initial value didn't validate
2927
     */
2928
    function serializeRPCParameters($operation, $direction, $parameters)
2929
    {
2930
        $this->debug('in serializeRPCParameters with operation '.$operation.', direction '.$direction.' and '.count($parameters).' param(s), and xml schema version ' . $this->XMLSchemaVersion); 
2931
                
2932
        if ($direction != 'input' && $direction != 'output') {
2933
            $this->debug('The value of the \$direction argument needs to be either "input" or "output"');
2934
            $this->setError('The value of the \$direction argument needs to be either "input" or "output"');
2935
            return false;
2936
        } 
2937
        if (!$opData = $this->getOperationData($operation)) {
2938
            $this->debug('Unable to retrieve WSDL data for operation: ' . $operation);
2939
            $this->setError('Unable to retrieve WSDL data for operation: ' . $operation);
2940
            return false;
2941
        }
2942
        $this->debug($this->varDump($opData));
2943
        // set input params
2944
        $xml = '';
2945
        if (isset($opData[$direction]['parts']) && sizeof($opData[$direction]['parts']) > 0) {
2946
			
2947
            $use = $opData[$direction]['use'];
2948
            $this->debug("use=$use");
2949
            $this->debug('got ' . count($opData[$direction]['parts']) . ' part(s)');
2950
            foreach($opData[$direction]['parts'] as $name => $type) {
2951
                $this->debug('serializing part "'.$name.'" of type "'.$type.'"');
2952
                // NOTE: add error handling here
2953
                // if serializeType returns false, then catch global error and fault
2954
                if (isset($parameters[$name])) {
2955
                    $this->debug('calling serializeType w/ named param');
2956
                    $xml .= $this->serializeType($name, $type, $parameters[$name], $use);
2957
                } elseif(is_array($parameters)) {
2958
                    $this->debug('calling serializeType w/ unnamed param');
2959
                    $xml .= $this->serializeType($name, $type, array_shift($parameters), $use);
2960
                } else {
2961
                    $this->debug('no parameters passed.');
2962
                }
2963
            }
2964
        }
2965
        return $xml;
2966
    } 
2967
	
2968
    /**
2969
     * serializes a PHP value according a given type definition
2970
     * 
2971
     * @param string $name , name of type (part)
2972
     * @param string $type , type of type, heh (type or element)
2973
     * @param mixed $value , a native PHP value (parameter value)
2974
     * @param string $use , use for part (encoded|literal)
2975
     * @return string serialization
2976
     * @access public 
2977
     */
2978
    function serializeType($name, $type, $value, $use='encoded')
2979
    {
2980
        $this->debug("in serializeType: $name, $type, $value, $use");
2981
        $xml = '';
2982
        if (strpos($type, ':')) {
2983
            $uqType = substr($type, strrpos($type, ':') + 1);
2984
            $ns = substr($type, 0, strrpos($type, ':'));
2985
            $this->debug("got a prefixed type: $uqType, $ns");
2986
			
2987
            if($ns == $this->XMLSchemaVersion ||
2988
               ($this->getNamespaceFromPrefix($ns)) == $this->XMLSchemaVersion){
2989
				
2990
                if ($uqType == 'boolean' && !$value) {
2991
                    $value = 0;
2992
                } elseif ($uqType == 'boolean') {
2993
                    $value = 1;
2994
                } 
2995
                if ($this->charencoding && $uqType == 'string' && gettype($value) == 'string') {
2996
                    $value = htmlspecialchars($value);
2997
                } 
2998
                // it's a scalar
2999
                if ($use == 'literal') {
3000
                    return "<$name>$value</$name>";
3001
                } else {
3002
                    return "<$name xsi:type=\"" . $this->getPrefixFromNamespace($this->XMLSchemaVersion) . ":$uqType\">$value</$name>";
3003
                }
3004
            } 
3005
        } else {
3006
            $uqType = $type;
3007
        }
3008
        if(!$typeDef = $this->getTypeDef($uqType)){
3009
            $this->setError("$uqType is not a supported type.");
3010
            return false;
3011
        } else {
3012
            //foreach($typeDef as $k => $v) {
3013
            //$this->debug("typedef, $k: $v");
3014
            //}
3015
        }
3016
        $phpType = $typeDef['phpType'];
3017
        $this->debug("serializeType: uqType: $uqType, ns: $ns, phptype: $phpType, arrayType: " . (isset($typeDef['arrayType']) ? $typeDef['arrayType'] : '') ); 
3018
        // if php type == struct, map value to the <all> element names
3019
        if ($phpType == 'struct') {
3020
            if (isset($typeDef['element']) && $typeDef['element']) {
3021
                $elementName = $uqType;
3022
                // TODO: use elementFormDefault="qualified|unqualified" to determine
3023
                // how to scope the namespace
3024
                $elementNS = " xmlns=\"$ns\"";
3025
            } else {
3026
                $elementName = $name;
3027
                $elementNS = '';
3028
            }
3029
            if ($use == 'literal') {
3030
                $xml = "<$elementName$elementNS>";
3031
            } else {
3032
                $xml = "<$elementName$elementNS xsi:type=\"" . $this->getPrefixFromNamespace($ns) . ":$uqType\">";
3033
            }
3034
			
3035
            if (isset($this->complexTypes[$uqType]['elements']) && is_array($this->complexTypes[$uqType]['elements'])) {
3036
			
3037
                //if (is_array($this->complexTypes[$uqType]['elements'])) {
3038
                // toggle whether all elements are present - ideally should validate against schema
3039
                if(count($this->complexTypes[$uqType]['elements']) != count($value)){
3040
                    $optionals = true;
3041
                }
3042
                foreach($this->complexTypes[$uqType]['elements'] as $eName => $attrs) {
3043
                    // if user took advantage of a minOccurs=0, then only serialize named parameters
3044
                    if(isset($optionals) && !isset($value[$eName])){
3045
                        // do nothing
3046
                    } else {
3047
                        // get value
3048
                        if (isset($value[$eName])) {
3049
                            $v = $value[$eName];
3050
                        } elseif (is_array($value)) {
3051
                            $v = array_shift($value);
3052
                        }
3053
                        // serialize schema-defined type
3054
                        if (!isset($attrs['type'])) {
3055
                            $xml .= $this->serializeType($eName, $attrs['name'], $v, $use);
3056
                            // serialize generic type
3057
                        } else {
3058
                            $this->debug("calling serialize_val() for $eName, $v, " . $this->getLocalPart($attrs['type']), false, $use);
3059
                            $xml .= $this->serialize_val($v, $eName, $this->getLocalPart($attrs['type']), null, $this->getNamespaceFromPrefix($this->getPrefix($attrs['type'])), false, $use);
3060
                        }
3061
                    }
3062
                } 
3063
            }
3064
            $xml .= "</$elementName>";
3065
        } elseif ($phpType == 'array') {
3066
            $rows = sizeof($value);
3067
            if (isset($typeDef['multidimensional'])) {
3068
                $nv = array();
3069
                foreach($value as $v) {
3070
                    $cols = ',' . sizeof($v);
3071
                    $nv = array_merge($nv, $v);
3072
                } 
3073
                $value = $nv;
3074
            } else {
3075
                $cols = '';
3076
            } 
3077
            if (is_array($value) && sizeof($value) >= 1) {
3078
                $contents = '';
3079
                foreach($value as $k => $v) {
3080
                    $this->debug("serializing array element: $k, $v of type: $typeDef[arrayType]");
3081
                    //if (strpos($typeDef['arrayType'], ':') ) {
3082
                    if (!in_array($typeDef['arrayType'],$this->typemap['http://www.w3.org/2001/XMLSchema'])) {
3083
                        $contents .= $this->serializeType('item', $typeDef['arrayType'], $v, $use);
3084
                    } else {
3085
                        $contents .= $this->serialize_val($v, 'item', $typeDef['arrayType'], null, $this->XMLSchemaVersion, false, $use);
3086
                    } 
3087
                }
3088
                $this->debug('contents: '.$this->varDump($contents));
3089
            } else {
3090
                $contents = null;
3091
            }
3092
            if ($use == 'literal') {
3093
                $xml = "<$name>"
3094
                    .$contents
3095
                    ."</$name>";
3096
            } else {
3097
                $xml = "<$name xsi:type=\"".$this->getPrefixFromNamespace('http://schemas.xmlsoap.org/soap/encoding/').':Array" '.
3098
                    $this->getPrefixFromNamespace('http://schemas.xmlsoap.org/soap/encoding/')
3099
                    .':arrayType="'
3100
                    .$this->getPrefixFromNamespace($this->getPrefix($typeDef['arrayType']))
3101
                    .":".$this->getLocalPart($typeDef['arrayType'])."[$rows$cols]\">"
3102
                    .$contents
3103
                    ."</$name>";
3104
            }
3105
        }
3106
        $this->debug('returning: '.$this->varDump($xml));
3107
        return $xml;
3108
    }
3109
	
3110
    /**
3111
     * register a service with the server
3112
     * 
3113
     * @param string $methodname 
0 ignored issues
show
Bug introduced by
There is no parameter named $methodname. Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

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

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

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

Loading history...
3114
     * @param string $in assoc array of input values: key = param name, value = param type
3115
     * @param string $out assoc array of output values: key = param name, value = param type
3116
     * @param string $namespace 
3117
     * @param string $soapaction 
3118
     * @param string $style (rpc|literal)
3119
     * @access public 
3120
     */
3121
    function addOperation($name, $in = false, $out = false, $namespace = false, $soapaction = false, $style = 'rpc', $use = 'encoded', $documentation = '')
3122
    {
3123
	if ($style == 'rpc' && $use == 'encoded') {
3124
            $encodingStyle = 'http://schemas.xmlsoap.org/soap/encoding/';
3125
	} else {
3126
            $encodingStyle = '';
3127
	} 
3128
	// get binding
3129
	$this->bindings[ $this->serviceName . 'Binding' ]['operations'][$name] =
3130
	array(
3131
              'name' => $name,
3132
              'binding' => $this->serviceName . 'Binding',
3133
              'endpoint' => $this->endpoint,
3134
              'soapAction' => $soapaction,
3135
              'style' => $style,
3136
              'input' => array(
3137
                               'use' => $use,
3138
                               'namespace' => $namespace,
3139
                               'encodingStyle' => $encodingStyle,
3140
                               'message' => $name . 'Request',
3141
                               'parts' => $in),
3142
              'output' => array(
3143
                                'use' => $use,
3144
                                'namespace' => $namespace,
3145
                                'encodingStyle' => $encodingStyle,
3146
                                'message' => $name . 'Response',
3147
                                'parts' => $out),
3148
              'namespace' => $namespace,
3149
              'transport' => 'http://schemas.xmlsoap.org/soap/http',
3150
              'documentation' => $documentation); 
3151
	// add portTypes
3152
	// add messages
3153
        if($in)
0 ignored issues
show
Bug Best Practice introduced by
The expression $in of type false|string is loosely compared to true; this is ambiguous if the string can be empty. You might want to explicitly use !== false instead.

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

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
3154
            {
3155
                foreach($in as $pName => $pType)
0 ignored issues
show
Bug introduced by
The expression $in of type string is not traversable.
Loading history...
3156
                {
3157
                    if(strpos($pType,':')) {
3158
                        $pType = $this->getNamespaceFromPrefix($this->getPrefix($pType)).":".$this->getLocalPart($pType);
3159
                    }
3160
                    $this->messages[$name.'Request'][$pName] = $pType;
3161
                }
3162
            }
3163
        
3164
        if($out)
0 ignored issues
show
Bug Best Practice introduced by
The expression $out of type false|string is loosely compared to true; this is ambiguous if the string can be empty. You might want to explicitly use !== false instead.

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

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
3165
            {
3166
                foreach($out as $pName => $pType)
0 ignored issues
show
Bug introduced by
The expression $out of type string is not traversable.
Loading history...
3167
                {
3168
                    if(strpos($pType,':')) {
3169
                        $pType = $this->getNamespaceFromPrefix($this->getPrefix($pType)).":".$this->getLocalPart($pType);
3170
                    }
3171
                    $this->messages[$name.'Response'][$pName] = $pType;
3172
                }
3173
            }
3174
	return true;
3175
    } 
3176
} 
3177
3178
?><?php
3179
3180
/**
3181
 *
3182
 * soap_parser class parses SOAP XML messages into native PHP values
3183
 *
3184
 * @author   Dietrich Ayala <[email protected]>
3185
 * @version  v 0.6.3
3186
 * @access   public
3187
 */
3188
class soap_parser extends nusoap_base {
3189
3190
    var $xml = '';
3191
    var $xml_encoding = '';
3192
    var $method = '';
3193
    var $root_struct = '';
3194
    var $root_struct_name = '';
3195
    var $root_header = '';
3196
    var $document = '';
3197
    // determines where in the message we are (envelope,header,body,method)
3198
    var $status = '';
3199
    var $position = 0;
3200
    var $depth = 0;
3201
    var $default_namespace = '';
3202
    var $namespaces = array();
3203
    var $message = array();
3204
    var $parent = '';
3205
    var $fault = false;
3206
    var $fault_code = '';
3207
    var $fault_str = '';
3208
    var $fault_detail = '';
3209
    var $depth_array = array();
3210
    var $debug_flag = true;
3211
    var $soapresponse = NULL;
3212
    var $responseHeaders = '';
3213
    var $body_position = 0;
3214
    // for multiref parsing:
3215
    // array of id => pos
3216
    var $ids = array();
3217
    // array of id => hrefs => pos
3218
    var $multirefs = array();
3219
3220
    /**
3221
     * constructor
3222
     *
3223
     * @param    string $xml SOAP message
3224
     * @param    string $encoding character encoding scheme of message
3225
     * @access   public
3226
     */
3227
    function soap_parser($xml,$encoding='UTF-8',$method=''){
3228
		$this->xml = $xml;
3229
		$this->xml_encoding = $encoding;
3230
		$this->method = $method;
3231
3232
		// Check whether content has been read.
3233
		if(!empty($xml)){
3234
			$this->debug('Entering soap_parser()');
3235
			// Create an XML parser.
3236
			$this->parser = xml_parser_create($this->xml_encoding);
3237
			// Set the options for parsing the XML data.
3238
			//xml_parser_set_option($parser, XML_OPTION_SKIP_WHITE, 1);
3239
			xml_parser_set_option($this->parser, XML_OPTION_CASE_FOLDING, 0);
3240
			// Set the object for the parser.
3241
			xml_set_object($this->parser, $this);
3242
			// Set the element handlers for the parser.
3243
			xml_set_element_handler($this->parser, 'start_element','end_element');
3244
			xml_set_character_data_handler($this->parser,'character_data');
3245
3246
			// Parse the XML file.
3247
			if(!xml_parse($this->parser,$xml,true)){
3248
			    // Display an error message.
3249
			    $err = sprintf('XML error on line %d: %s',
3250
			    xml_get_current_line_number($this->parser),
3251
			    xml_error_string(xml_get_error_code($this->parser)));
3252
				$this->debug('parse error: '.$err);
3253
				$this->errstr = $err;
3254
			} else {
3255
				$this->debug('parsed successfully, found root struct: '.$this->root_struct.' of name '.$this->root_struct_name);
3256
				// get final value
3257
				$this->soapresponse = $this->message[$this->root_struct]['result'];
3258
				// get header value
3259
				if($this->root_header != '' && isset($this->message[$this->root_header]['result'])){
3260
					$this->responseHeaders = $this->message[$this->root_header]['result'];
3261
				}
3262
				// resolve hrefs/ids
3263
				if(sizeof($this->multirefs) > 0){
3264
					foreach($this->multirefs as $id => $hrefs){
3265
						$this->debug('resolving multirefs for id: '.$id);
3266
						$idVal = $this->buildVal($this->ids[$id]);
3267
						foreach($hrefs as $refPos => $ref){
3268
							$this->debug('resolving href at pos '.$refPos);
3269
							$this->multirefs[$id][$refPos] = $idVal;
3270
						}
3271
					}
3272
				}
3273
			}
3274
			xml_parser_free($this->parser);
3275
		} else {
3276
			$this->debug('xml was empty, didn\'t parse!');
3277
			$this->errstr = 'xml was empty, didn\'t parse!';
3278
		}
3279
	}
3280
3281
	/**
3282
	* start-element handler
3283
	*
3284
	* @param    string $parser XML parser object
3285
	* @param    string $name element name
3286
	* @param    string $attrs associative array of attributes
3287
	* @access   private
3288
	*/
3289
	function start_element($parser, $name, $attrs) {
3290
		// position in a total number of elements, starting from 0
3291
		// update class level pos
3292
		$pos = $this->position++;
3293
		// and set mine
3294
		$this->message[$pos] = array('pos' => $pos,'children'=>'','cdata'=>'');
3295
		// depth = how many levels removed from root?
3296
		// set mine as current global depth and increment global depth value
3297
		$this->message[$pos]['depth'] = $this->depth++;
3298
3299
		// else add self as child to whoever the current parent is
3300
		if($pos != 0){
3301
			$this->message[$this->parent]['children'] .= '|'.$pos;
3302
		}
3303
		// set my parent
3304
		$this->message[$pos]['parent'] = $this->parent;
3305
		// set self as current parent
3306
		$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...
3307
		// set self as current value for this depth
3308
		$this->depth_array[$this->depth] = $pos;
3309
		// get element prefix
3310
		if(strpos($name,':')){
3311
			// get ns prefix
3312
			$prefix = substr($name,0,strpos($name,':'));
3313
			// get unqualified name
3314
			$name = substr(strstr($name,':'),1);
3315
		}
3316
		// set status
3317
		if($name == 'Envelope'){
3318
			$this->status = 'envelope';
3319
		} elseif($name == 'Header'){
3320
			$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...
3321
			$this->status = 'header';
3322
		} elseif($name == 'Body'){
3323
			$this->status = 'body';
3324
			$this->body_position = $pos;
3325
		// set method
3326
		} elseif($this->status == 'body' && $pos == ($this->body_position+1)){
3327
			$this->status = 'method';
3328
			$this->root_struct_name = $name;
3329
			$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...
3330
			$this->message[$pos]['type'] = 'struct';
3331
			$this->debug("found root struct $this->root_struct_name, pos $this->root_struct");
3332
		}
3333
		// set my status
3334
		$this->message[$pos]['status'] = $this->status;
3335
		// set name
3336
		$this->message[$pos]['name'] = htmlspecialchars($name);
3337
		// set attrs
3338
		$this->message[$pos]['attrs'] = $attrs;
3339
3340
		// loop through atts, logging ns and type declarations
3341
        $attstr = '';
3342
		foreach($attrs as $key => $value){
0 ignored issues
show
Bug introduced by
The expression $attrs of type string is not traversable.
Loading history...
3343
        	$key_prefix = $this->getPrefix($key);
3344
			$key_localpart = $this->getLocalPart($key);
3345
			// if ns declarations, add to class level array of valid namespaces
3346
            if($key_prefix == 'xmlns'){
3347
				if(ereg('^http://www.w3.org/[0-9]{4}/XMLSchema$',$value)){
3348
					$this->XMLSchemaVersion = $value;
3349
					$this->namespaces['xsd'] = $this->XMLSchemaVersion;
3350
					$this->namespaces['xsi'] = $this->XMLSchemaVersion.'-instance';
3351
				}
3352
                $this->namespaces[$key_localpart] = $value;
3353
				// set method namespace
3354
				if($name == $this->root_struct_name){
3355
					$this->methodNamespace = $value;
3356
				}
3357
			// if it's a type declaration, set type
3358
            } elseif($key_localpart == 'type'){
3359
            	$value_prefix = $this->getPrefix($value);
3360
                $value_localpart = $this->getLocalPart($value);
3361
				$this->message[$pos]['type'] = $value_localpart;
3362
				$this->message[$pos]['typePrefix'] = $value_prefix;
3363
                if(isset($this->namespaces[$value_prefix])){
3364
                	$this->message[$pos]['type_namespace'] = $this->namespaces[$value_prefix];
3365
                } else if(isset($attrs['xmlns:'.$value_prefix])) {
3366
					$this->message[$pos]['type_namespace'] = $attrs['xmlns:'.$value_prefix];
3367
                }
3368
				// should do something here with the namespace of specified type?
3369
			} elseif($key_localpart == 'arrayType'){
3370
				$this->message[$pos]['type'] = 'array';
3371
				/* do arrayType ereg here
3372
				[1]    arrayTypeValue    ::=    atype asize
3373
				[2]    atype    ::=    QName rank*
3374
				[3]    rank    ::=    '[' (',')* ']'
3375
				[4]    asize    ::=    '[' length~ ']'
3376
				[5]    length    ::=    nextDimension* Digit+
3377
				[6]    nextDimension    ::=    Digit+ ','
3378
				*/
3379
				$expr = '([A-Za-z0-9_]+):([A-Za-z]+[A-Za-z0-9_]+)\[([0-9]+),?([0-9]*)\]';
3380
				if(ereg($expr,$value,$regs)){
3381
					$this->message[$pos]['typePrefix'] = $regs[1];
3382
					$this->message[$pos]['arraySize'] = $regs[3];
3383
					$this->message[$pos]['arrayCols'] = $regs[4];
3384
				}
3385
			}
3386
			// log id
3387
			if($key == 'id'){
3388
				$this->ids[$value] = $pos;
3389
			}
3390
			// root
3391
			if($key_localpart == 'root' && $value == 1){
3392
				$this->status = 'method';
3393
				$this->root_struct_name = $name;
3394
				$this->root_struct = $pos;
3395
				$this->debug("found root struct $this->root_struct_name, pos $pos");
3396
			}
3397
            // for doclit
3398
            $attstr .= " $key=\"$value\"";
3399
		}
3400
        // get namespace - must be done after namespace atts are processed
3401
		if(isset($prefix)){
3402
			$this->message[$pos]['namespace'] = $this->namespaces[$prefix];
3403
			$this->default_namespace = $this->namespaces[$prefix];
3404
		} else {
3405
			$this->message[$pos]['namespace'] = $this->default_namespace;
3406
		}
3407
        if($this->status == 'header'){
3408
        	$this->responseHeaders .= "<$name$attstr>";
3409
        } elseif($this->root_struct_name != ''){
3410
        	$this->document .= "<$name$attstr>";
3411
        }
3412
	}
3413
3414
	/**
3415
	* end-element handler
3416
	*
3417
	* @param    string $parser XML parser object
3418
	* @param    string $name element name
3419
	* @access   private
3420
	*/
3421
	function end_element($parser, $name) {
3422
		// position of current element is equal to the last value left in depth_array for my depth
3423
		$pos = $this->depth_array[$this->depth--];
3424
3425
        // get element prefix
3426
		if(strpos($name,':')){
3427
			// get ns prefix
3428
			$prefix = substr($name,0,strpos($name,':'));
3429
			// get unqualified name
3430
			$name = substr(strstr($name,':'),1);
3431
		}
3432
3433
		// build to native type
3434
		if(isset($this->body_position) && $pos > $this->body_position){
3435
			// deal w/ multirefs
3436
			if(isset($this->message[$pos]['attrs']['href'])){
3437
				// get id
3438
				$id = substr($this->message[$pos]['attrs']['href'],1);
3439
				// add placeholder to href array
3440
				$this->multirefs[$id][$pos] = "placeholder";
3441
				// add set a reference to it as the result value
3442
				$this->message[$pos]['result'] =& $this->multirefs[$id][$pos];
3443
            // build complex values
3444
			} elseif($this->message[$pos]['children'] != ""){
3445
				$this->message[$pos]['result'] = $this->buildVal($pos);
3446
			} else {
3447
            	$this->debug('adding data for scalar value '.$this->message[$pos]['name'].' of value '.$this->message[$pos]['cdata']);
3448
				if(is_numeric($this->message[$pos]['cdata']) ){
3449
                	if( strpos($this->message[$pos]['cdata'],'.') ){
3450
                		$this->message[$pos]['result'] = doubleval($this->message[$pos]['cdata']);
3451
                    } else {
3452
                    	$this->message[$pos]['result'] = intval($this->message[$pos]['cdata']);
3453
                    }
3454
                } else {
3455
                	$this->message[$pos]['result'] = $this->message[$pos]['cdata'];
3456
                }
3457
			}
3458
		}
3459
3460
		// switch status
3461
		if($pos == $this->root_struct){
3462
			$this->status = 'body';
3463
		} elseif($name == 'Body'){
3464
			$this->status = 'header';
3465
		 } elseif($name == 'Header'){
3466
			$this->status = 'envelope';
3467
		} elseif($name == 'Envelope'){
3468
			//
3469
		}
3470
		// set parent back to my parent
3471
		$this->parent = $this->message[$pos]['parent'];
3472
        // for doclit
3473
        if($this->status == 'header'){
3474
        	$this->responseHeaders .= "</$name>";
3475
        } elseif($pos >= $this->root_struct){
3476
        	$this->document .= "</$name>";
3477
        }
3478
	}
3479
3480
	/**
3481
	* element content handler
3482
	*
3483
	* @param    string $parser XML parser object
3484
	* @param    string $data element content
3485
	* @access   private
3486
	*/
3487
	function character_data($parser, $data){
3488
		$pos = $this->depth_array[$this->depth];
3489
		if ($this->xml_encoding=='UTF-8'){
3490
			$data = utf8_decode($data);
3491
		}
3492
        $this->message[$pos]['cdata'] .= $data;
3493
        // for doclit
3494
        if($this->status == 'header'){
3495
        	$this->responseHeaders .= $data;
3496
        } else {
3497
        	$this->document .= $data;
3498
        }
3499
	}
3500
3501
	/**
3502
	* get the parsed message
3503
	*
3504
	* @return	mixed
3505
	* @access   public
3506
	*/
3507
	function get_response(){
3508
		return $this->soapresponse;
3509
	}
3510
3511
	/**
3512
	* get the parsed headers
3513
	*
3514
	* @return	string XML or empty if no headers
3515
	* @access   public
3516
	*/
3517
	function getHeaders(){
3518
	    return $this->responseHeaders;
3519
	}
3520
3521
	/**
3522
	* decodes entities
3523
	*
3524
	* @param    string $text string to translate
3525
	* @access   private
3526
	*/
3527
	function decode_entities($text){
3528
		foreach($this->entities as $entity => $encoded){
3529
			$text = str_replace($encoded,$entity,$text);
3530
		}
3531
		return $text;
3532
	}
3533
3534
	/**
3535
	* builds response structures for compound values (arrays/structs)
3536
	*
3537
	* @param    string $pos position in node tree
3538
	* @access   private
3539
	*/
3540
	function buildVal($pos){
3541
		if(!isset($this->message[$pos]['type'])){
3542
			$this->message[$pos]['type'] = '';
3543
		}
3544
		$this->debug('inside buildVal() for '.$this->message[$pos]['name']."(pos $pos) of type ".$this->message[$pos]['type']);
3545
		// if there are children...
3546
		if($this->message[$pos]['children'] != ''){
3547
			$children = explode('|',$this->message[$pos]['children']);
3548
			array_shift($children); // knock off empty
3549
			// md array
3550
			if(isset($this->message[$pos]['arrayCols']) && $this->message[$pos]['arrayCols'] != ''){
3551
            	$r=0; // rowcount
3552
            	$c=0; // colcount
3553
            	foreach($children as $child_pos){
3554
					$this->debug("got an MD array element: $r, $c");
3555
					$params[$r][] = $this->message[$child_pos]['result'];
3556
				    $c++;
3557
				    if($c == $this->message[$pos]['arrayCols']){
3558
				    	$c = 0;
3559
						$r++;
3560
				    }
3561
                }
3562
            // array
3563
			} elseif($this->message[$pos]['type'] == 'array' || $this->message[$pos]['type'] == 'Array'){
3564
                $this->debug('adding array '.$this->message[$pos]['name']);
3565
                foreach($children as $child_pos){
3566
                	$params[] = &$this->message[$child_pos]['result'];
3567
                }
3568
            // apache Map type: java hashtable
3569
            } elseif($this->message[$pos]['type'] == 'Map' && $this->message[$pos]['type_namespace'] == 'http://xml.apache.org/xml-soap'){
3570
                foreach($children as $child_pos){
3571
                	$kv = explode("|",$this->message[$child_pos]['children']);
3572
                   	$params[$this->message[$kv[1]]['result']] = &$this->message[$kv[2]]['result'];
3573
                }
3574
            // generic compound type
3575
            //} elseif($this->message[$pos]['type'] == 'SOAPStruct' || $this->message[$pos]['type'] == 'struct') {
3576
            } else {
3577
            	// is array or struct? better way to do this probably
3578
            	foreach($children as $child_pos){
3579
            		if(isset($keys) && isset($keys[$this->message[$child_pos]['name']])){
3580
            			$struct = 1;
3581
            			break;
3582
            		}
3583
            		$keys[$this->message[$child_pos]['name']] = 1;
3584
            	}
3585
            	//
3586
            	foreach($children as $child_pos){
3587
            		if(isset($struct)){
3588
            			$params[] = &$this->message[$child_pos]['result'];
3589
            		} else {
3590
				    	$params[$this->message[$child_pos]['name']] = &$this->message[$child_pos]['result'];
3591
                	}
3592
                }
3593
			}
3594
			return is_array($params) ? $params : array();
3595
		} else {
3596
        	$this->debug('no children');
3597
            if(strpos($this->message[$pos]['cdata'],'&')){
3598
		    	return  strtr($this->message[$pos]['cdata'],array_flip($this->entities));
3599
            } else {
3600
            	return $this->message[$pos]['cdata'];
3601
            }
3602
		}
3603
	}
3604
}
3605
3606
3607
3608
?><?php
3609
3610
3611
3612
/**
3613
*
3614
* soapclient higher level class for easy usage.
3615
*
3616
* usage:
3617
*
3618
* // instantiate client with server info
3619
* $soapclient = new soapclient( string path [ ,boolean wsdl] );
3620
*
3621
* // call method, get results
3622
* echo $soapclient->call( string methodname [ ,array parameters] );
3623
*
3624
* // bye bye client
3625
* unset($soapclient);
3626
*
3627
* @author   Dietrich Ayala <[email protected]>
3628
* @version  v 0.6.3
3629
* @access   public
3630
*/
3631
class soapclient extends nusoap_base  {
3632
3633
    var $username = '';
3634
    var $password = '';
3635
    var $requestHeaders = false;
3636
    var $responseHeaders;
3637
    var $endpoint;
3638
    var $error_str = false;
3639
    var $proxyhost = '';
3640
    var $proxyport = '';
3641
    var $xml_encoding = '';
3642
    var $http_encoding = false;
3643
    var $timeout = 0;
3644
    var $endpointType = '';
3645
    var $persistentConnection = false;
3646
    var $defaultRpcParams = false;
3647
	
3648
    /**
3649
     * fault related variables
3650
     *
3651
     * @var      fault
3652
     * @var      faultcode
3653
     * @var      faultstring
3654
     * @var      faultdetail
3655
     * @access   public
3656
     */
3657
    var $fault, $faultcode, $faultstring, $faultdetail;
3658
3659
    /**
3660
     * constructor
3661
     *
3662
     * @param    string $endpoint SOAP server or WSDL URL
3663
     * @param    bool $wsdl optional, set to true if using WSDL
3664
     * @param	int $portName optional portName in WSDL document
0 ignored issues
show
Bug introduced by
There is no parameter named $portName. Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

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

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

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

Loading history...
3665
     * @access   public
3666
     */
3667
    function soapclient($endpoint,$wsdl = false){
3668
        $this->endpoint = $endpoint;
3669
3670
        // make values
3671
        if ($wsdl){
3672
            $this->endpointType = 'wsdl';
3673
            $this->wsdlFile = $this->endpoint;
3674
			
3675
            // instantiate wsdl object and parse wsdl file
3676
            $this->debug('instantiating wsdl class with doc: '.$endpoint);
3677
            $this->wsdl = new wsdl($this->wsdlFile,$this->proxyhost,$this->proxyport);
3678
            $this->debug("wsdl debug: \n".$this->wsdl->debug_str);
3679
            $this->wsdl->debug_str = '';
3680
            // catch errors
3681
            if($errstr = $this->wsdl->getError()){
3682
                $this->debug('got wsdl error: '.$errstr);
3683
                $this->setError('wsdl error: '.$errstr);
3684
            } elseif($this->operations = $this->wsdl->getOperations()){
3685
                $this->debug( 'got '.count($this->operations).' operations from wsdl '.$this->wsdlFile);
3686
            } else {
3687
                $this->debug( 'getOperations returned false');
3688
                $this->setError('no operations defined in the WSDL document!');
3689
            }
3690
        }
3691
    }
3692
3693
    /**
3694
     * calls method, returns PHP native type
3695
     *
3696
     * @param    string $method SOAP server URL or path
0 ignored issues
show
Bug introduced by
There is no parameter named $method. Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

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

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

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

Loading history...
3697
     * @param    array $params array of parameters, can be associative or not
3698
     * @param	string $namespace optional method namespace
3699
     * @param	string $soapAction optional SOAPAction value
3700
     * @param	boolean $headers optional array of soapval objects for headers
3701
     * @param	boolean $rpcParams optional treat params as RPC for use="literal"
3702
     *                   This can be used on a per-call basis to overrider defaultRpcParams.
3703
     * @return	mixed
3704
     * @access   public
3705
     */
3706
    function call($operation,$params=array(),$namespace='',$soapAction='',$headers=false,$rpcParams=null){
3707
        $this->operation = $operation;
3708
        $this->fault = false;
3709
        $this->error_str = '';
0 ignored issues
show
Documentation Bug introduced by
The property $error_str was declared of type boolean, but '' 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...
3710
        $this->request = '';
3711
        $this->response = '';
3712
        $this->faultstring = '';
3713
        $this->faultcode = '';
3714
        $this->opData = array();
3715
		
3716
        $this->debug("call: $operation, $params, $namespace, $soapAction, $headers, $rpcParams");
3717
        $this->debug("endpointType: $this->endpointType");
3718
        // if wsdl, get operation data and process parameters
3719
        if($this->endpointType == 'wsdl' && $opData = $this->getOperationData($operation)){
3720
3721
            $this->opData = $opData;
3722
            foreach($opData as $key => $value){
3723
                $this->debug("$key -> $value");
3724
            }
3725
            $soapAction = $opData['soapAction'];
3726
            $this->endpoint = $opData['endpoint'];
3727
            $namespace = isset($opData['input']['namespace']) ? $opData['input']['namespace'] :	'http://testuri.org';
3728
            $style = $opData['style'];
3729
            // add ns to ns array
3730
            if($namespace != '' && !isset($this->wsdl->namespaces[$namespace])){
3731
                $this->wsdl->namespaces['nu'] = $namespace;
3732
            }
3733
            // serialize payload
3734
			
3735
            if($opData['input']['use'] == 'literal') {
3736
                if (is_null($rpcParams)) {
3737
                    $rpcParams = $this->defaultRpcParams;
3738
                }
3739
                if ($rpcParams) {
3740
                    $this->debug("serializing literal params for operation $operation");
3741
                    $payload = $this->wsdl->serializeRPCParameters($operation,'input',$params);
3742
                    $defaultNamespace = $this->wsdl->wsdl_info['targetNamespace'];
3743
                } else {
3744
                    $this->debug("serializing literal document for operation $operation");
3745
                    $payload = is_array($params) ? array_shift($params) : $params;
3746
                }
3747
            } else {
3748
                $this->debug("serializing encoded params for operation $operation");
3749
                $payload = "<".$this->wsdl->getPrefixFromNamespace($namespace).":$operation>".
3750
                    $this->wsdl->serializeRPCParameters($operation,'input',$params).
3751
                    '</'.$this->wsdl->getPrefixFromNamespace($namespace).":$operation>";
3752
            }
3753
            $this->debug('payload size: '.strlen($payload));
3754
            // serialize envelope
3755
            $soapmsg = $this->serializeEnvelope($payload,$this->requestHeaders,$this->wsdl->usedNamespaces,$style);
3756
            $this->debug("wsdl debug: \n".$this->wsdl->debug_str);
3757
            $this->wsdl->debug_str = '';
3758
        } elseif($this->endpointType == 'wsdl') {
3759
            $this->setError( 'operation '.$operation.' not present.');
3760
            $this->debug("operation '$operation' not present.");
3761
            $this->debug("wsdl debug: \n".$this->wsdl->debug_str);
3762
            return false;
3763
            // no wsdl
3764
        } else {
3765
            // make message
3766
            if(!isset($style)){
0 ignored issues
show
Bug introduced by
The variable $style seems only to be defined at a later point. As such the call to isset() seems to always evaluate to false.

This check marks calls to isset(...) or empty(...) that are found before the variable itself is defined. These will always have the same result.

This is likely the result of code being shifted around. Consider removing these calls.

Loading history...
3767
                $style = 'rpc';
3768
            }
3769
            if($namespace == ''){
3770
            	$namespace = 'http://testuri.org';
3771
                $this->wsdl->namespaces['ns1'] = $namespace;
3772
            }
3773
            // serialize envelope
3774
            $payload = '';
3775
            foreach($params as $k => $v){
3776
                $payload .= $this->serialize_val($v,$k);
3777
            }
3778
            $payload = "<ns1:$operation xmlns:ns1=\"$namespace\">\n".$payload."</ns1:$operation>\n";
3779
            $soapmsg = $this->serializeEnvelope($payload,$this->requestHeaders);
3780
        }
3781
        $this->debug("endpoint: $this->endpoint, soapAction: $soapAction, namespace: $namespace");
3782
        // send
3783
        $this->debug('sending msg (len: '.strlen($soapmsg).") w/ soapaction '$soapAction'...");
3784
        $return = $this->send($soapmsg,$soapAction,$this->timeout);
3785
        if($errstr = $this->getError()){
3786
            $this->debug('Error: '.$errstr);
3787
            return false;
3788
        } else {
3789
            $this->return = $return;
3790
            $this->debug('sent message successfully and got a(n) '.gettype($return).' back');
3791
            
3792
            // fault?
3793
            if(is_array($return) && isset($return['faultcode'])){
3794
                $this->debug('got fault');
3795
                $this->setError($return['faultcode'].': '.$return['faultstring']);
3796
                $this->fault = true;
3797
                foreach($return as $k => $v){
3798
                    $this->$k = $v;
3799
                    $this->debug("$k = $v<br>");
3800
                }
3801
                return $return;
3802
            } else {
3803
                // array of return values
3804
                if(is_array($return)){
3805
                    // multiple 'out' parameters
3806
                    if(sizeof($return) > 1){
3807
                        return $return;
3808
                    }
3809
                    // single 'out' parameter
3810
                    return array_shift($return);
3811
                    // nothing returned (ie, echoVoid)
3812
                } else {
3813
                    return "";
3814
                }
3815
            }
3816
        }
3817
    }
3818
3819
	/**
3820
	* get available data pertaining to an operation
3821
	*
3822
	* @param    string $operation operation name
3823
	* @return	array array of data pertaining to the operation
3824
	* @access   public
3825
	*/
3826
	function getOperationData($operation){
3827
		if(isset($this->operations[$operation])){
3828
			return $this->operations[$operation];
3829
		}
3830
		$this->debug("No data for operation: $operation");
3831
	}
3832
3833
    /**
3834
    * send the SOAP message
3835
    *
3836
    * Note: if the operation has multiple return values
3837
    * the return value of this method will be an array
3838
    * of those values.
3839
    *
3840
	* @param    string $msg a SOAPx4 soapmsg object
3841
	* @param    string $soapaction SOAPAction value
3842
	* @param    integer $timeout set timeout in seconds
3843
	* @return	mixed native PHP types.
3844
	* @access   private
3845
	*/
3846
	function send($msg, $soapaction = '', $timeout=0) {
3847
		// detect transport
3848
		switch(true){
0 ignored issues
show
Bug Best Practice introduced by
It seems like you are loosely comparing ereg('^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...
3849
			// http(s)
3850
			case ereg('^http',$this->endpoint):
3851
				$this->debug('transporting via HTTP');
3852
				if($this->persistentConnection && is_object($this->persistentConnection)){
3853
					$http =& $this->persistentConnection;
3854
				} else {
3855
					$http = new soap_transport_http($this->endpoint);
3856
					// pass encoding into transport layer, so appropriate http headers are sent
3857
					$http->soap_defencoding = $this->soap_defencoding;
3858
				}
3859
				$http->setSOAPAction($soapaction);
3860
				if($this->proxyhost && $this->proxyport){
3861
					$http->setProxy($this->proxyhost,$this->proxyport);
3862
				}
3863
                                if($this->username != '' && $this->password != '') {
3864
					$http->setCredentials($this->username,$this->password);
3865
				}
3866
				if($this->http_encoding != ''){
3867
					$http->setEncoding($this->http_encoding);
3868
				}
3869
				$this->debug('sending message, length: '.strlen($msg));
3870
				if(ereg('^http:',$this->endpoint)){
3871
				//if(strpos($this->endpoint,'http:')){
3872
					$response = $http->send($msg,$timeout);
3873
				} elseif(ereg('^https',$this->endpoint)){
3874
				//} elseif(strpos($this->endpoint,'https:')){
3875
					//if(phpversion() == '4.3.0-dev'){
3876
						//$response = $http->send($msg,$timeout);
3877
                   		//$this->request = $http->outgoing_payload;
3878
						//$this->response = $http->incoming_payload;
3879
					//} else
3880
					if (extension_loaded('curl')) {
3881
						$response = $http->sendHTTPS($msg,$timeout);
3882
					} else {
3883
						$this->setError('CURL Extension, or OpenSSL extension w/ PHP version >= 4.3 is required for HTTPS');
3884
					}								
3885
				} else {
3886
					$this->setError('no http/s in endpoint url');
3887
				}
3888
				$this->request = $http->outgoing_payload;
3889
				$this->response = $http->incoming_payload;
3890
				$this->debug("transport debug data...\n".$http->debug_str);
3891
				// save transport object if using persistent connections
3892
				if($this->persistentConnection && !is_object($this->persistentConnection)){
3893
					$this->persistentConnection = $http;
3894
				}
3895
				if($err = $http->getError()){
3896
					$this->setError('HTTP Error: '.$err);
3897
					return false;
3898
				} elseif($this->getError()){
3899
					return false;
3900
				} else {
3901
					$this->debug('got response, length: '.strlen($response));
3902
					return $this->parseResponse($response);
3903
				}
3904
			break;
0 ignored issues
show
Unused Code introduced by
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...
3905
			default:
3906
				$this->setError('no transport found, or selected transport is not yet supported!');
3907
			return false;
3908
			break;
0 ignored issues
show
Unused Code introduced by
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...
3909
		}
3910
	}
3911
3912
	/**
3913
	* processes SOAP message returned from server
3914
	*
3915
	* @param	string unprocessed response data from server
3916
	* @return	mixed value of the message, decoded into a PHP type
3917
	* @access   private
3918
	*/
3919
    function parseResponse($data) {
3920
        $this->debug('Entering parseResponse(), about to create soap_parser instance');
3921
        $parser = new soap_parser($data,$this->xml_encoding,$this->operation);
3922
        // if parse errors
3923
        if($errstr = $parser->getError()){
3924
            $this->setError( $errstr);
3925
            // destroy the parser object
3926
            unset($parser);
3927
            return false;
3928
        } else {
3929
            // get SOAP headers
3930
            $this->responseHeaders = $parser->getHeaders();
3931
            // get decoded message
3932
            $return = $parser->get_response();
3933
            // add parser debug data to our debug
3934
            $this->debug($parser->debug_str);
3935
            // add document for doclit support
3936
            $this->document = $parser->document;
3937
            // destroy the parser object
3938
            unset($parser);
3939
            // return decode message
3940
            return $return;
3941
        }
3942
    }
3943
3944
    /**
3945
     * set the SOAP headers
3946
     *
3947
     * @param    $headers string XML
3948
     * @access   public
3949
     */
3950
    function setHeaders($headers){
3951
        $this->requestHeaders = $headers;
3952
    }
3953
3954
    /**
3955
     * get the response headers
3956
     *
3957
     * @return   mixed object SOAPx4 soapval object or empty if no headers
3958
     * @access   public
3959
     */
3960
    function getHeaders(){
3961
        if($this->responseHeaders != '') {
3962
            return $this->responseHeaders;
3963
        }
3964
    }
3965
3966
	/**
3967
         * set proxy info here
3968
         *
3969
         * @param    string $proxyhost
3970
         * @param    string $proxyport
3971
         * @access   public
3972
         */
3973
	function setHTTPProxy($proxyhost, $proxyport) {
3974
            $this->proxyhost = $proxyhost;
3975
            $this->proxyport = $proxyport;
3976
	}
3977
3978
	/**
3979
         * if authenticating, set user credentials here
3980
         *
3981
         * @param    string $username
3982
         * @param    string $password
3983
         * @access   public
3984
         */
3985
	function setCredentials($username, $password) {
3986
            $this->username = $username;
3987
            $this->password = $password;
3988
	}
3989
	
3990
	/**
3991
         * use HTTP encoding
3992
         *
3993
         * @param    string $enc
3994
         * @access   public
3995
         */
3996
	function setHTTPEncoding($enc='gzip, deflate'){
3997
            $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...
3998
	}
3999
	
4000
	/**
4001
         * use HTTP persistent connections if possible
4002
         *
4003
         * @access   public
4004
         */
4005
	function useHTTPPersistentConnection(){
4006
            $this->persistentConnection = true;
4007
	}
4008
	
4009
	/**
4010
         * gets the default RPC parameter setting.
4011
         * If true, default is that call params are like RPC even for document style.
4012
         * Each call() can override this value.
4013
         *
4014
         * @access public
4015
         */
4016
	function getDefaultRpcParams() {
4017
            return $this->defaultRpcParams;
4018
	}
4019
4020
	/**
4021
         * sets the default RPC parameter setting.
4022
         * If true, default is that call params are like RPC even for document style
4023
         * Each call() can override this value.
4024
         *
4025
         * @param    boolean $rpcParams
4026
         * @access public
4027
         */
4028
	function setDefaultRpcParams($rpcParams) {
4029
            $this->defaultRpcParams = $rpcParams;
4030
	}
4031
	
4032
	/**
4033
         * dynamically creates proxy class, allowing user to directly call methods from wsdl
4034
         *
4035
         * @return   object soap_proxy object
4036
         * @access   public
4037
         */
4038
	function getProxy(){
4039
            $evalStr = '';
4040
            foreach($this->operations as $operation => $opData){
4041
                if($operation != ''){
4042
                    // create param string
4043
                    $paramStr = '';
4044
                    if(sizeof($opData['input']['parts']) > 0){
4045
                        foreach($opData['input']['parts'] as $name => $type){
4046
                            $paramStr .= "\$$name,";
4047
                        }
4048
                        $paramStr = substr($paramStr,0,strlen($paramStr)-1);
4049
                    }
4050
                    $opData['namespace'] = !isset($opData['namespace']) ? 'http://testuri.com' : $opData['namespace'];
4051
                    $evalStr .= "function $operation ($paramStr){
4052
					// load params into array
4053
					\$params = array($paramStr);
4054
					return \$this->call('$operation',\$params,'".$opData['namespace']."','".$opData['soapAction']."');
4055
				}";
4056
                    unset($paramStr);
4057
                }
4058
            }
4059
            $r = rand();
4060
            $evalStr = 'class soap_proxy_'.$r.' extends soapclient {
4061
				'.$evalStr.'
4062
			}';
4063
            //print "proxy class:<pre>$evalStr</pre>";
4064
            // eval the class
4065
            eval($evalStr);
0 ignored issues
show
Coding Style introduced by
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...
4066
            // instantiate proxy object
4067
            eval("\$proxy = new soap_proxy_$r('');");
0 ignored issues
show
Coding Style introduced by
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...
4068
            // transfer current wsdl data to the proxy thereby avoiding parsing the wsdl twice
4069
            $proxy->endpointType = 'wsdl';
0 ignored issues
show
Bug introduced by
The variable $proxy does not exist. Did you forget to declare it?

This check marks access to variables or properties that have not been declared yet. While PHP has no explicit notion of declaring a variable, accessing it before a value is assigned to it is most likely a bug.

Loading history...
4070
            $proxy->wsdlFile = $this->wsdlFile;
4071
            $proxy->wsdl = $this->wsdl;
4072
            $proxy->operations = $this->operations;
4073
            $proxy->defaultRpcParams = $this->defaultRpcParams;
4074
            return $proxy;
4075
	}
4076
}
4077
4078
// Local Variables:
4079
// mode: php
4080
// tab-width: 8
4081
// c-basic-offset: 4
4082
// c-hanging-comment-ender-p: nil
4083
// indent-tabs-mode: nil
4084
// End:
4085
?>