~dangarner/xibo/107-oggcamp2010

« back to all changes in this revision

Viewing changes to server/3rdparty/nuSoap/class.wsdl.php

  • Committer: Alex Harrington
  • Date: 2009-12-31 11:48:37 UTC
  • Revision ID: alex@longhill.org.uk-20091231114837-90kgz9qy4us1184v
Converted to 2.0 repo format and fixed line endings.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
<?php
2
 
 
3
 
 
4
 
 
5
 
 
6
 
/**
7
 
* parses a WSDL file, allows access to it's data, other utility methods.
8
 
* also builds WSDL structures programmatically.
9
 
10
 
* @author   Dietrich Ayala <dietrich@ganx4.com>
11
 
* @author   Scott Nichol <snichol@users.sourceforge.net>
12
 
* @version  $Id: class.wsdl.php,v 1.69 2007/11/06 15:17:46 snichol Exp $
13
 
* @access public 
14
 
*/
15
 
class wsdl extends nusoap_base {
16
 
        // URL or filename of the root of this WSDL
17
 
    var $wsdl; 
18
 
    // define internal arrays of bindings, ports, operations, messages, etc.
19
 
    var $schemas = array();
20
 
    var $currentSchema;
21
 
    var $message = array();
22
 
    var $complexTypes = array();
23
 
    var $messages = array();
24
 
    var $currentMessage;
25
 
    var $currentOperation;
26
 
    var $portTypes = array();
27
 
    var $currentPortType;
28
 
    var $bindings = array();
29
 
    var $currentBinding;
30
 
    var $ports = array();
31
 
    var $currentPort;
32
 
    var $opData = array();
33
 
    var $status = '';
34
 
    var $documentation = false;
35
 
    var $endpoint = ''; 
36
 
    // array of wsdl docs to import
37
 
    var $import = array(); 
38
 
    // parser vars
39
 
    var $parser;
40
 
    var $position = 0;
41
 
    var $depth = 0;
42
 
    var $depth_array = array();
43
 
        // for getting wsdl
44
 
        var $proxyhost = '';
45
 
    var $proxyport = '';
46
 
        var $proxyusername = '';
47
 
        var $proxypassword = '';
48
 
        var $timeout = 0;
49
 
        var $response_timeout = 30;
50
 
        var $curl_options = array();    // User-specified cURL options
51
 
        var $use_curl = false;                  // whether to always try to use cURL
52
 
        // for HTTP authentication
53
 
        var $username = '';                             // Username for HTTP authentication
54
 
        var $password = '';                             // Password for HTTP authentication
55
 
        var $authtype = '';                             // Type of HTTP authentication
56
 
        var $certRequest = array();             // Certificate for HTTP SSL authentication
57
 
 
58
 
    /**
59
 
     * constructor
60
 
     * 
61
 
     * @param string $wsdl WSDL document URL
62
 
         * @param string $proxyhost
63
 
         * @param string $proxyport
64
 
         * @param string $proxyusername
65
 
         * @param string $proxypassword
66
 
         * @param integer $timeout set the connection timeout
67
 
         * @param integer $response_timeout set the response timeout
68
 
         * @param array $curl_options user-specified cURL options
69
 
         * @param boolean $use_curl try to use cURL
70
 
     * @access public 
71
 
     */
72
 
    function wsdl($wsdl = '',$proxyhost=false,$proxyport=false,$proxyusername=false,$proxypassword=false,$timeout=0,$response_timeout=30,$curl_options=null,$use_curl=false){
73
 
                parent::nusoap_base();
74
 
                $this->debug("ctor wsdl=$wsdl timeout=$timeout response_timeout=$response_timeout");
75
 
        $this->proxyhost = $proxyhost;
76
 
        $this->proxyport = $proxyport;
77
 
                $this->proxyusername = $proxyusername;
78
 
                $this->proxypassword = $proxypassword;
79
 
                $this->timeout = $timeout;
80
 
                $this->response_timeout = $response_timeout;
81
 
                if (is_array($curl_options))
82
 
                        $this->curl_options = $curl_options;
83
 
                $this->use_curl = $use_curl;
84
 
                $this->fetchWSDL($wsdl);
85
 
    }
86
 
 
87
 
        /**
88
 
         * fetches the WSDL document and parses it
89
 
         *
90
 
         * @access public
91
 
         */
92
 
        function fetchWSDL($wsdl) {
93
 
                $this->debug("parse and process WSDL path=$wsdl");
94
 
                $this->wsdl = $wsdl;
95
 
        // parse wsdl file
96
 
        if ($this->wsdl != "") {
97
 
            $this->parseWSDL($this->wsdl);
98
 
        }
99
 
        // imports
100
 
        // TODO: handle imports more properly, grabbing them in-line and nesting them
101
 
        $imported_urls = array();
102
 
        $imported = 1;
103
 
        while ($imported > 0) {
104
 
                $imported = 0;
105
 
                // Schema imports
106
 
                foreach ($this->schemas as $ns => $list) {
107
 
                        foreach ($list as $xs) {
108
 
                                        $wsdlparts = parse_url($this->wsdl);    // this is bogusly simple!
109
 
                            foreach ($xs->imports as $ns2 => $list2) {
110
 
                                for ($ii = 0; $ii < count($list2); $ii++) {
111
 
                                        if (! $list2[$ii]['loaded']) {
112
 
                                                $this->schemas[$ns]->imports[$ns2][$ii]['loaded'] = true;
113
 
                                                $url = $list2[$ii]['location'];
114
 
                                                                if ($url != '') {
115
 
                                                                        $urlparts = parse_url($url);
116
 
                                                                        if (!isset($urlparts['host'])) {
117
 
                                                                                $url = $wsdlparts['scheme'] . '://' . $wsdlparts['host'] . (isset($wsdlparts['port']) ? ':' .$wsdlparts['port'] : '') .
118
 
                                                                                                substr($wsdlparts['path'],0,strrpos($wsdlparts['path'],'/') + 1) .$urlparts['path'];
119
 
                                                                        }
120
 
                                                                        if (! in_array($url, $imported_urls)) {
121
 
                                                                $this->parseWSDL($url);
122
 
                                                                $imported++;
123
 
                                                                $imported_urls[] = $url;
124
 
                                                        }
125
 
                                                                } else {
126
 
                                                                        $this->debug("Unexpected scenario: empty URL for unloaded import");
127
 
                                                                }
128
 
                                                        }
129
 
                                                }
130
 
                            } 
131
 
                        }
132
 
                }
133
 
                // WSDL imports
134
 
                        $wsdlparts = parse_url($this->wsdl);    // this is bogusly simple!
135
 
            foreach ($this->import as $ns => $list) {
136
 
                for ($ii = 0; $ii < count($list); $ii++) {
137
 
                        if (! $list[$ii]['loaded']) {
138
 
                                $this->import[$ns][$ii]['loaded'] = true;
139
 
                                $url = $list[$ii]['location'];
140
 
                                                if ($url != '') {
141
 
                                                        $urlparts = parse_url($url);
142
 
                                                        if (!isset($urlparts['host'])) {
143
 
                                                                $url = $wsdlparts['scheme'] . '://' . $wsdlparts['host'] . (isset($wsdlparts['port']) ? ':' . $wsdlparts['port'] : '') .
144
 
                                                                                substr($wsdlparts['path'],0,strrpos($wsdlparts['path'],'/') + 1) .$urlparts['path'];
145
 
                                                        }
146
 
                                                        if (! in_array($url, $imported_urls)) {
147
 
                                                $this->parseWSDL($url);
148
 
                                                $imported++;
149
 
                                                $imported_urls[] = $url;
150
 
                                        }
151
 
                                                } else {
152
 
                                                        $this->debug("Unexpected scenario: empty URL for unloaded import");
153
 
                                                }
154
 
                                        }
155
 
                                }
156
 
            } 
157
 
                }
158
 
        // add new data to operation data
159
 
        foreach($this->bindings as $binding => $bindingData) {
160
 
            if (isset($bindingData['operations']) && is_array($bindingData['operations'])) {
161
 
                foreach($bindingData['operations'] as $operation => $data) {
162
 
                    $this->debug('post-parse data gathering for ' . $operation);
163
 
                    $this->bindings[$binding]['operations'][$operation]['input'] = 
164
 
                                                isset($this->bindings[$binding]['operations'][$operation]['input']) ? 
165
 
                                                array_merge($this->bindings[$binding]['operations'][$operation]['input'], $this->portTypes[ $bindingData['portType'] ][$operation]['input']) :
166
 
                                                $this->portTypes[ $bindingData['portType'] ][$operation]['input'];
167
 
                    $this->bindings[$binding]['operations'][$operation]['output'] = 
168
 
                                                isset($this->bindings[$binding]['operations'][$operation]['output']) ?
169
 
                                                array_merge($this->bindings[$binding]['operations'][$operation]['output'], $this->portTypes[ $bindingData['portType'] ][$operation]['output']) :
170
 
                                                $this->portTypes[ $bindingData['portType'] ][$operation]['output'];
171
 
                    if(isset($this->messages[ $this->bindings[$binding]['operations'][$operation]['input']['message'] ])){
172
 
                                                $this->bindings[$binding]['operations'][$operation]['input']['parts'] = $this->messages[ $this->bindings[$binding]['operations'][$operation]['input']['message'] ];
173
 
                                        }
174
 
                                        if(isset($this->messages[ $this->bindings[$binding]['operations'][$operation]['output']['message'] ])){
175
 
                                $this->bindings[$binding]['operations'][$operation]['output']['parts'] = $this->messages[ $this->bindings[$binding]['operations'][$operation]['output']['message'] ];
176
 
                    }
177
 
                    // Set operation style if necessary, but do not override one already provided
178
 
                                        if (isset($bindingData['style']) && !isset($this->bindings[$binding]['operations'][$operation]['style'])) {
179
 
                        $this->bindings[$binding]['operations'][$operation]['style'] = $bindingData['style'];
180
 
                    }
181
 
                    $this->bindings[$binding]['operations'][$operation]['transport'] = isset($bindingData['transport']) ? $bindingData['transport'] : '';
182
 
                    $this->bindings[$binding]['operations'][$operation]['documentation'] = isset($this->portTypes[ $bindingData['portType'] ][$operation]['documentation']) ? $this->portTypes[ $bindingData['portType'] ][$operation]['documentation'] : '';
183
 
                    $this->bindings[$binding]['operations'][$operation]['endpoint'] = isset($bindingData['endpoint']) ? $bindingData['endpoint'] : '';
184
 
                } 
185
 
            } 
186
 
        }
187
 
        }
188
 
 
189
 
    /**
190
 
     * parses the wsdl document
191
 
     * 
192
 
     * @param string $wsdl path or URL
193
 
     * @access private 
194
 
     */
195
 
    function parseWSDL($wsdl = '') {
196
 
                $this->debug("parse WSDL at path=$wsdl");
197
 
 
198
 
        if ($wsdl == '') {
199
 
            $this->debug('no wsdl passed to parseWSDL()!!');
200
 
            $this->setError('no wsdl passed to parseWSDL()!!');
201
 
            return false;
202
 
        }
203
 
        
204
 
        // parse $wsdl for url format
205
 
        $wsdl_props = parse_url($wsdl);
206
 
 
207
 
        if (isset($wsdl_props['scheme']) && ($wsdl_props['scheme'] == 'http' || $wsdl_props['scheme'] == 'https')) {
208
 
            $this->debug('getting WSDL http(s) URL ' . $wsdl);
209
 
                // get wsdl
210
 
                $tr = new soap_transport_http($wsdl, $this->curl_options, $this->use_curl);
211
 
                        $tr->request_method = 'GET';
212
 
                        $tr->useSOAPAction = false;
213
 
                        if($this->proxyhost && $this->proxyport){
214
 
                                $tr->setProxy($this->proxyhost,$this->proxyport,$this->proxyusername,$this->proxypassword);
215
 
                        }
216
 
                        if ($this->authtype != '') {
217
 
                                $tr->setCredentials($this->username, $this->password, $this->authtype, array(), $this->certRequest);
218
 
                        }
219
 
                        $tr->setEncoding('gzip, deflate');
220
 
                        $wsdl_string = $tr->send('', $this->timeout, $this->response_timeout);
221
 
                        //$this->debug("WSDL request\n" . $tr->outgoing_payload);
222
 
                        //$this->debug("WSDL response\n" . $tr->incoming_payload);
223
 
                        $this->appendDebug($tr->getDebug());
224
 
                        // catch errors
225
 
                        if($err = $tr->getError() ){
226
 
                                $errstr = 'HTTP ERROR: '.$err;
227
 
                                $this->debug($errstr);
228
 
                    $this->setError($errstr);
229
 
                                unset($tr);
230
 
                    return false;
231
 
                        }
232
 
                        unset($tr);
233
 
                        $this->debug("got WSDL URL");
234
 
        } else {
235
 
            // $wsdl is not http(s), so treat it as a file URL or plain file path
236
 
                if (isset($wsdl_props['scheme']) && ($wsdl_props['scheme'] == 'file') && isset($wsdl_props['path'])) {
237
 
                        $path = isset($wsdl_props['host']) ? ($wsdl_props['host'] . ':' . $wsdl_props['path']) : $wsdl_props['path'];
238
 
                } else {
239
 
                        $path = $wsdl;
240
 
                }
241
 
            $this->debug('getting WSDL file ' . $path);
242
 
            if ($fp = @fopen($path, 'r')) {
243
 
                $wsdl_string = '';
244
 
                while ($data = fread($fp, 32768)) {
245
 
                    $wsdl_string .= $data;
246
 
                } 
247
 
                fclose($fp);
248
 
            } else {
249
 
                $errstr = "Bad path to WSDL file $path";
250
 
                $this->debug($errstr);
251
 
                $this->setError($errstr);
252
 
                return false;
253
 
            } 
254
 
        }
255
 
        $this->debug('Parse WSDL');
256
 
        // end new code added
257
 
        // Create an XML parser.
258
 
        $this->parser = xml_parser_create(); 
259
 
        // Set the options for parsing the XML data.
260
 
        // xml_parser_set_option($parser, XML_OPTION_SKIP_WHITE, 1);
261
 
        xml_parser_set_option($this->parser, XML_OPTION_CASE_FOLDING, 0); 
262
 
        // Set the object for the parser.
263
 
        xml_set_object($this->parser, $this); 
264
 
        // Set the element handlers for the parser.
265
 
        xml_set_element_handler($this->parser, 'start_element', 'end_element');
266
 
        xml_set_character_data_handler($this->parser, 'character_data');
267
 
        // Parse the XML file.
268
 
        if (!xml_parse($this->parser, $wsdl_string, true)) {
269
 
            // Display an error message.
270
 
            $errstr = sprintf(
271
 
                                'XML error parsing WSDL from %s on line %d: %s',
272
 
                                $wsdl,
273
 
                xml_get_current_line_number($this->parser),
274
 
                xml_error_string(xml_get_error_code($this->parser))
275
 
                );
276
 
            $this->debug($errstr);
277
 
                        $this->debug("XML payload:\n" . $wsdl_string);
278
 
            $this->setError($errstr);
279
 
            return false;
280
 
        } 
281
 
                // free the parser
282
 
        xml_parser_free($this->parser);
283
 
        $this->debug('Parsing WSDL done');
284
 
                // catch wsdl parse errors
285
 
                if($this->getError()){
286
 
                        return false;
287
 
                }
288
 
        return true;
289
 
    } 
290
 
 
291
 
    /**
292
 
     * start-element handler
293
 
     * 
294
 
     * @param string $parser XML parser object
295
 
     * @param string $name element name
296
 
     * @param string $attrs associative array of attributes
297
 
     * @access private 
298
 
     */
299
 
    function start_element($parser, $name, $attrs)
300
 
    {
301
 
        if ($this->status == 'schema') {
302
 
            $this->currentSchema->schemaStartElement($parser, $name, $attrs);
303
 
            $this->appendDebug($this->currentSchema->getDebug());
304
 
            $this->currentSchema->clearDebug();
305
 
        } elseif (ereg('schema$', $name)) {
306
 
                $this->debug('Parsing WSDL schema');
307
 
            // $this->debug("startElement for $name ($attrs[name]). status = $this->status (".$this->getLocalPart($name).")");
308
 
            $this->status = 'schema';
309
 
            $this->currentSchema = new nusoap_xmlschema('', '', $this->namespaces);
310
 
            $this->currentSchema->schemaStartElement($parser, $name, $attrs);
311
 
            $this->appendDebug($this->currentSchema->getDebug());
312
 
            $this->currentSchema->clearDebug();
313
 
        } else {
314
 
            // position in the total number of elements, starting from 0
315
 
            $pos = $this->position++;
316
 
            $depth = $this->depth++; 
317
 
            // set self as current value for this depth
318
 
            $this->depth_array[$depth] = $pos;
319
 
            $this->message[$pos] = array('cdata' => ''); 
320
 
            // process attributes
321
 
            if (count($attrs) > 0) {
322
 
                                // register namespace declarations
323
 
                foreach($attrs as $k => $v) {
324
 
                    if (ereg("^xmlns", $k)) {
325
 
                        if ($ns_prefix = substr(strrchr($k, ':'), 1)) {
326
 
                            $this->namespaces[$ns_prefix] = $v;
327
 
                        } else {
328
 
                            $this->namespaces['ns' . (count($this->namespaces) + 1)] = $v;
329
 
                        } 
330
 
                        if ($v == 'http://www.w3.org/2001/XMLSchema' || $v == 'http://www.w3.org/1999/XMLSchema' || $v == 'http://www.w3.org/2000/10/XMLSchema') {
331
 
                            $this->XMLSchemaVersion = $v;
332
 
                            $this->namespaces['xsi'] = $v . '-instance';
333
 
                        } 
334
 
                    }
335
 
                }
336
 
                // expand each attribute prefix to its namespace
337
 
                foreach($attrs as $k => $v) {
338
 
                    $k = strpos($k, ':') ? $this->expandQname($k) : $k;
339
 
                    if ($k != 'location' && $k != 'soapAction' && $k != 'namespace') {
340
 
                        $v = strpos($v, ':') ? $this->expandQname($v) : $v;
341
 
                    } 
342
 
                    $eAttrs[$k] = $v;
343
 
                } 
344
 
                $attrs = $eAttrs;
345
 
            } else {
346
 
                $attrs = array();
347
 
            } 
348
 
            // get element prefix, namespace and name
349
 
            if (ereg(':', $name)) {
350
 
                // get ns prefix
351
 
                $prefix = substr($name, 0, strpos($name, ':')); 
352
 
                // get ns
353
 
                $namespace = isset($this->namespaces[$prefix]) ? $this->namespaces[$prefix] : ''; 
354
 
                // get unqualified name
355
 
                $name = substr(strstr($name, ':'), 1);
356
 
            } 
357
 
                        // process attributes, expanding any prefixes to namespaces
358
 
            // find status, register data
359
 
            switch ($this->status) {
360
 
                case 'message':
361
 
                    if ($name == 'part') {
362
 
                                    if (isset($attrs['type'])) {
363
 
                                    $this->debug("msg " . $this->currentMessage . ": found part (with type) $attrs[name]: " . implode(',', $attrs));
364
 
                                    $this->messages[$this->currentMessage][$attrs['name']] = $attrs['type'];
365
 
                                } 
366
 
                                    if (isset($attrs['element'])) {
367
 
                                    $this->debug("msg " . $this->currentMessage . ": found part (with element) $attrs[name]: " . implode(',', $attrs));
368
 
                                        $this->messages[$this->currentMessage][$attrs['name']] = $attrs['element'] . '^';
369
 
                                    } 
370
 
                                } 
371
 
                                break;
372
 
                            case 'portType':
373
 
                                switch ($name) {
374
 
                                    case 'operation':
375
 
                                        $this->currentPortOperation = $attrs['name'];
376
 
                                        $this->debug("portType $this->currentPortType operation: $this->currentPortOperation");
377
 
                                        if (isset($attrs['parameterOrder'])) {
378
 
                                                $this->portTypes[$this->currentPortType][$attrs['name']]['parameterOrder'] = $attrs['parameterOrder'];
379
 
                                                } 
380
 
                                                break;
381
 
                                            case 'documentation':
382
 
                                                $this->documentation = true;
383
 
                                                break; 
384
 
                                            // merge input/output data
385
 
                                            default:
386
 
                                                $m = isset($attrs['message']) ? $this->getLocalPart($attrs['message']) : '';
387
 
                                                $this->portTypes[$this->currentPortType][$this->currentPortOperation][$name]['message'] = $m;
388
 
                                                break;
389
 
                                        } 
390
 
                                break;
391
 
                                case 'binding':
392
 
                                    switch ($name) {
393
 
                                        case 'binding': 
394
 
                                            // get ns prefix
395
 
                                            if (isset($attrs['style'])) {
396
 
                                            $this->bindings[$this->currentBinding]['prefix'] = $prefix;
397
 
                                                } 
398
 
                                                $this->bindings[$this->currentBinding] = array_merge($this->bindings[$this->currentBinding], $attrs);
399
 
                                                break;
400
 
                                                case 'header':
401
 
                                                    $this->bindings[$this->currentBinding]['operations'][$this->currentOperation][$this->opStatus]['headers'][] = $attrs;
402
 
                                                    break;
403
 
                                                case 'operation':
404
 
                                                    if (isset($attrs['soapAction'])) {
405
 
                                                        $this->bindings[$this->currentBinding]['operations'][$this->currentOperation]['soapAction'] = $attrs['soapAction'];
406
 
                                                    } 
407
 
                                                    if (isset($attrs['style'])) {
408
 
                                                        $this->bindings[$this->currentBinding]['operations'][$this->currentOperation]['style'] = $attrs['style'];
409
 
                                                    } 
410
 
                                                    if (isset($attrs['name'])) {
411
 
                                                        $this->currentOperation = $attrs['name'];
412
 
                                                        $this->debug("current binding operation: $this->currentOperation");
413
 
                                                        $this->bindings[$this->currentBinding]['operations'][$this->currentOperation]['name'] = $attrs['name'];
414
 
                                                        $this->bindings[$this->currentBinding]['operations'][$this->currentOperation]['binding'] = $this->currentBinding;
415
 
                                                        $this->bindings[$this->currentBinding]['operations'][$this->currentOperation]['endpoint'] = isset($this->bindings[$this->currentBinding]['endpoint']) ? $this->bindings[$this->currentBinding]['endpoint'] : '';
416
 
                                                    } 
417
 
                                                    break;
418
 
                                                case 'input':
419
 
                                                    $this->opStatus = 'input';
420
 
                                                    break;
421
 
                                                case 'output':
422
 
                                                    $this->opStatus = 'output';
423
 
                                                    break;
424
 
                                                case 'body':
425
 
                                                    if (isset($this->bindings[$this->currentBinding]['operations'][$this->currentOperation][$this->opStatus])) {
426
 
                                                        $this->bindings[$this->currentBinding]['operations'][$this->currentOperation][$this->opStatus] = array_merge($this->bindings[$this->currentBinding]['operations'][$this->currentOperation][$this->opStatus], $attrs);
427
 
                                                    } else {
428
 
                                                        $this->bindings[$this->currentBinding]['operations'][$this->currentOperation][$this->opStatus] = $attrs;
429
 
                                                    } 
430
 
                                                    break;
431
 
                                        } 
432
 
                                        break;
433
 
                                case 'service':
434
 
                                        switch ($name) {
435
 
                                            case 'port':
436
 
                                                $this->currentPort = $attrs['name'];
437
 
                                                $this->debug('current port: ' . $this->currentPort);
438
 
                                                $this->ports[$this->currentPort]['binding'] = $this->getLocalPart($attrs['binding']);
439
 
                                        
440
 
                                                break;
441
 
                                            case 'address':
442
 
                                                $this->ports[$this->currentPort]['location'] = $attrs['location'];
443
 
                                                $this->ports[$this->currentPort]['bindingType'] = $namespace;
444
 
                                                $this->bindings[ $this->ports[$this->currentPort]['binding'] ]['bindingType'] = $namespace;
445
 
                                                $this->bindings[ $this->ports[$this->currentPort]['binding'] ]['endpoint'] = $attrs['location'];
446
 
                                                break;
447
 
                                        } 
448
 
                                        break;
449
 
                        } 
450
 
                // set status
451
 
                switch ($name) {
452
 
                        case 'import':
453
 
                            if (isset($attrs['location'])) {
454
 
                    $this->import[$attrs['namespace']][] = array('location' => $attrs['location'], 'loaded' => false);
455
 
                    $this->debug('parsing import ' . $attrs['namespace']. ' - ' . $attrs['location'] . ' (' . count($this->import[$attrs['namespace']]).')');
456
 
                                } else {
457
 
                    $this->import[$attrs['namespace']][] = array('location' => '', 'loaded' => true);
458
 
                                        if (! $this->getPrefixFromNamespace($attrs['namespace'])) {
459
 
                                                $this->namespaces['ns'.(count($this->namespaces)+1)] = $attrs['namespace'];
460
 
                                        }
461
 
                    $this->debug('parsing import ' . $attrs['namespace']. ' - [no location] (' . count($this->import[$attrs['namespace']]).')');
462
 
                                }
463
 
                                break;
464
 
                        //wait for schema
465
 
                        //case 'types':
466
 
                        //      $this->status = 'schema';
467
 
                        //      break;
468
 
                        case 'message':
469
 
                                $this->status = 'message';
470
 
                                $this->messages[$attrs['name']] = array();
471
 
                                $this->currentMessage = $attrs['name'];
472
 
                                break;
473
 
                        case 'portType':
474
 
                                $this->status = 'portType';
475
 
                                $this->portTypes[$attrs['name']] = array();
476
 
                                $this->currentPortType = $attrs['name'];
477
 
                                break;
478
 
                        case "binding":
479
 
                                if (isset($attrs['name'])) {
480
 
                                // get binding name
481
 
                                        if (strpos($attrs['name'], ':')) {
482
 
                                        $this->currentBinding = $this->getLocalPart($attrs['name']);
483
 
                                        } else {
484
 
                                        $this->currentBinding = $attrs['name'];
485
 
                                        } 
486
 
                                        $this->status = 'binding';
487
 
                                        $this->bindings[$this->currentBinding]['portType'] = $this->getLocalPart($attrs['type']);
488
 
                                        $this->debug("current binding: $this->currentBinding of portType: " . $attrs['type']);
489
 
                                } 
490
 
                                break;
491
 
                        case 'service':
492
 
                                $this->serviceName = $attrs['name'];
493
 
                                $this->status = 'service';
494
 
                                $this->debug('current service: ' . $this->serviceName);
495
 
                                break;
496
 
                        case 'definitions':
497
 
                                foreach ($attrs as $name => $value) {
498
 
                                        $this->wsdl_info[$name] = $value;
499
 
                                } 
500
 
                                break;
501
 
                        } 
502
 
                } 
503
 
        } 
504
 
 
505
 
        /**
506
 
        * end-element handler
507
 
        * 
508
 
        * @param string $parser XML parser object
509
 
        * @param string $name element name
510
 
        * @access private 
511
 
        */
512
 
        function end_element($parser, $name){ 
513
 
                // unset schema status
514
 
                if (/*ereg('types$', $name) ||*/ ereg('schema$', $name)) {
515
 
                        $this->status = "";
516
 
            $this->appendDebug($this->currentSchema->getDebug());
517
 
            $this->currentSchema->clearDebug();
518
 
                        $this->schemas[$this->currentSchema->schemaTargetNamespace][] = $this->currentSchema;
519
 
                $this->debug('Parsing WSDL schema done');
520
 
                } 
521
 
                if ($this->status == 'schema') {
522
 
                        $this->currentSchema->schemaEndElement($parser, $name);
523
 
                } else {
524
 
                        // bring depth down a notch
525
 
                        $this->depth--;
526
 
                } 
527
 
                // end documentation
528
 
                if ($this->documentation) {
529
 
                        //TODO: track the node to which documentation should be assigned; it can be a part, message, etc.
530
 
                        //$this->portTypes[$this->currentPortType][$this->currentPortOperation]['documentation'] = $this->documentation;
531
 
                        $this->documentation = false;
532
 
                } 
533
 
        } 
534
 
 
535
 
        /**
536
 
         * element content handler
537
 
         * 
538
 
         * @param string $parser XML parser object
539
 
         * @param string $data element content
540
 
         * @access private 
541
 
         */
542
 
        function character_data($parser, $data)
543
 
        {
544
 
                $pos = isset($this->depth_array[$this->depth]) ? $this->depth_array[$this->depth] : 0;
545
 
                if (isset($this->message[$pos]['cdata'])) {
546
 
                        $this->message[$pos]['cdata'] .= $data;
547
 
                } 
548
 
                if ($this->documentation) {
549
 
                        $this->documentation .= $data;
550
 
                } 
551
 
        } 
552
 
        
553
 
        /**
554
 
        * if authenticating, set user credentials here
555
 
        *
556
 
        * @param    string $username
557
 
        * @param    string $password
558
 
        * @param        string $authtype (basic|digest|certificate|ntlm)
559
 
        * @param        array $certRequest (keys must be cainfofile (optional), sslcertfile, sslkeyfile, passphrase, certpassword (optional), verifypeer (optional), verifyhost (optional): see corresponding options in cURL docs)
560
 
        * @access   public
561
 
        */
562
 
        function setCredentials($username, $password, $authtype = 'basic', $certRequest = array()) {
563
 
                $this->debug("setCredentials username=$username authtype=$authtype certRequest=");
564
 
                $this->appendDebug($this->varDump($certRequest));
565
 
                $this->username = $username;
566
 
                $this->password = $password;
567
 
                $this->authtype = $authtype;
568
 
                $this->certRequest = $certRequest;
569
 
        }
570
 
        
571
 
        function getBindingData($binding)
572
 
        {
573
 
                if (is_array($this->bindings[$binding])) {
574
 
                        return $this->bindings[$binding];
575
 
                } 
576
 
        }
577
 
        
578
 
        /**
579
 
         * returns an assoc array of operation names => operation data
580
 
         * 
581
 
         * @param string $bindingType eg: soap, smtp, dime (only soap and soap12 are currently supported)
582
 
         * @return array 
583
 
         * @access public 
584
 
         */
585
 
        function getOperations($bindingType = 'soap') {
586
 
                $ops = array();
587
 
                if ($bindingType == 'soap') {
588
 
                        $bindingType = 'http://schemas.xmlsoap.org/wsdl/soap/';
589
 
                } elseif ($bindingType == 'soap12') {
590
 
                        $bindingType = 'http://schemas.xmlsoap.org/wsdl/soap12/';
591
 
                }
592
 
                // loop thru ports
593
 
                foreach($this->ports as $port => $portData) {
594
 
                        // binding type of port matches parameter
595
 
                        if ($portData['bindingType'] == $bindingType) {
596
 
                                //$this->debug("getOperations for port $port");
597
 
                                //$this->debug("port data: " . $this->varDump($portData));
598
 
                                //$this->debug("bindings: " . $this->varDump($this->bindings[ $portData['binding'] ]));
599
 
                                // merge bindings
600
 
                                if (isset($this->bindings[ $portData['binding'] ]['operations'])) {
601
 
                                        $ops = array_merge ($ops, $this->bindings[ $portData['binding'] ]['operations']);
602
 
                                }
603
 
                        }
604
 
                } 
605
 
                return $ops;
606
 
        } 
607
 
        
608
 
        /**
609
 
         * returns an associative array of data necessary for calling an operation
610
 
         * 
611
 
         * @param string $operation name of operation
612
 
         * @param string $bindingType type of binding eg: soap, soap12
613
 
         * @return array 
614
 
         * @access public 
615
 
         */
616
 
        function getOperationData($operation, $bindingType = 'soap')
617
 
        {
618
 
                if ($bindingType == 'soap') {
619
 
                        $bindingType = 'http://schemas.xmlsoap.org/wsdl/soap/';
620
 
                } elseif ($bindingType == 'soap12') {
621
 
                        $bindingType = 'http://schemas.xmlsoap.org/wsdl/soap12/';
622
 
                }
623
 
                // loop thru ports
624
 
                foreach($this->ports as $port => $portData) {
625
 
                        // binding type of port matches parameter
626
 
                        if ($portData['bindingType'] == $bindingType) {
627
 
                                // get binding
628
 
                                //foreach($this->bindings[ $portData['binding'] ]['operations'] as $bOperation => $opData) {
629
 
                                foreach(array_keys($this->bindings[ $portData['binding'] ]['operations']) as $bOperation) {
630
 
                                        // note that we could/should also check the namespace here
631
 
                                        if ($operation == $bOperation) {
632
 
                                                $opData = $this->bindings[ $portData['binding'] ]['operations'][$operation];
633
 
                                            return $opData;
634
 
                                        } 
635
 
                                } 
636
 
                        }
637
 
                } 
638
 
        }
639
 
        
640
 
        /**
641
 
         * returns an associative array of data necessary for calling an operation
642
 
         * 
643
 
         * @param string $soapAction soapAction for operation
644
 
         * @param string $bindingType type of binding eg: soap, soap12
645
 
         * @return array 
646
 
         * @access public 
647
 
         */
648
 
        function getOperationDataForSoapAction($soapAction, $bindingType = 'soap') {
649
 
                if ($bindingType == 'soap') {
650
 
                        $bindingType = 'http://schemas.xmlsoap.org/wsdl/soap/';
651
 
                } elseif ($bindingType == 'soap12') {
652
 
                        $bindingType = 'http://schemas.xmlsoap.org/wsdl/soap12/';
653
 
                }
654
 
                // loop thru ports
655
 
                foreach($this->ports as $port => $portData) {
656
 
                        // binding type of port matches parameter
657
 
                        if ($portData['bindingType'] == $bindingType) {
658
 
                                // loop through operations for the binding
659
 
                                foreach ($this->bindings[ $portData['binding'] ]['operations'] as $bOperation => $opData) {
660
 
                                        if ($opData['soapAction'] == $soapAction) {
661
 
                                            return $opData;
662
 
                                        } 
663
 
                                } 
664
 
                        }
665
 
                } 
666
 
        }
667
 
        
668
 
        /**
669
 
    * returns an array of information about a given type
670
 
    * returns false if no type exists by the given name
671
 
    *
672
 
        *        typeDef = array(
673
 
        *        'elements' => array(), // refs to elements array
674
 
        *       'restrictionBase' => '',
675
 
        *       'phpType' => '',
676
 
        *       'order' => '(sequence|all)',
677
 
        *       'attrs' => array() // refs to attributes array
678
 
        *       )
679
 
    *
680
 
    * @param string $type the type
681
 
    * @param string $ns namespace (not prefix) of the type
682
 
    * @return mixed
683
 
    * @access public
684
 
    * @see nusoap_xmlschema
685
 
    */
686
 
        function getTypeDef($type, $ns) {
687
 
                $this->debug("in getTypeDef: type=$type, ns=$ns");
688
 
                if ((! $ns) && isset($this->namespaces['tns'])) {
689
 
                        $ns = $this->namespaces['tns'];
690
 
                        $this->debug("in getTypeDef: type namespace forced to $ns");
691
 
                }
692
 
                if (!isset($this->schemas[$ns])) {
693
 
                        foreach ($this->schemas as $ns0 => $schema0) {
694
 
                                if (strcasecmp($ns, $ns0) == 0) {
695
 
                                        $this->debug("in getTypeDef: replacing schema namespace $ns with $ns0");
696
 
                                        $ns = $ns0;
697
 
                                        break;
698
 
                                }
699
 
                        }
700
 
                }
701
 
                if (isset($this->schemas[$ns])) {
702
 
                        $this->debug("in getTypeDef: have schema for namespace $ns");
703
 
                        for ($i = 0; $i < count($this->schemas[$ns]); $i++) {
704
 
                                $xs = &$this->schemas[$ns][$i];
705
 
                                $t = $xs->getTypeDef($type);
706
 
                                //$this->appendDebug($xs->getDebug());
707
 
                                //$xs->clearDebug();
708
 
                                if ($t) {
709
 
                                        if (!isset($t['phpType'])) {
710
 
                                                // get info for type to tack onto the element
711
 
                                                $uqType = substr($t['type'], strrpos($t['type'], ':') + 1);
712
 
                                                $ns = substr($t['type'], 0, strrpos($t['type'], ':'));
713
 
                                                $etype = $this->getTypeDef($uqType, $ns);
714
 
                                                if ($etype) {
715
 
                                                        $this->debug("found type for [element] $type:");
716
 
                                                        $this->debug($this->varDump($etype));
717
 
                                                        if (isset($etype['phpType'])) {
718
 
                                                                $t['phpType'] = $etype['phpType'];
719
 
                                                        }
720
 
                                                        if (isset($etype['elements'])) {
721
 
                                                                $t['elements'] = $etype['elements'];
722
 
                                                        }
723
 
                                                        if (isset($etype['attrs'])) {
724
 
                                                                $t['attrs'] = $etype['attrs'];
725
 
                                                        }
726
 
                                                }
727
 
                                        }
728
 
                                        return $t;
729
 
                                }
730
 
                        }
731
 
                } else {
732
 
                        $this->debug("in getTypeDef: do not have schema for namespace $ns");
733
 
                }
734
 
                return false;
735
 
        }
736
 
 
737
 
    /**
738
 
    * prints html description of services
739
 
    *
740
 
    * @access private
741
 
    */
742
 
    function webDescription(){
743
 
        global $HTTP_SERVER_VARS;
744
 
 
745
 
                if (isset($_SERVER)) {
746
 
                        $PHP_SELF = $_SERVER['PHP_SELF'];
747
 
                } elseif (isset($HTTP_SERVER_VARS)) {
748
 
                        $PHP_SELF = $HTTP_SERVER_VARS['PHP_SELF'];
749
 
                } else {
750
 
                        $this->setError("Neither _SERVER nor HTTP_SERVER_VARS is available");
751
 
                }
752
 
 
753
 
                $b = '
754
 
                <html><head><title>NuSOAP: '.$this->serviceName.'</title>
755
 
                <style type="text/css">
756
 
                    body    { font-family: arial; color: #000000; background-color: #ffffff; margin: 0px 0px 0px 0px; }
757
 
                    p       { font-family: arial; color: #000000; margin-top: 0px; margin-bottom: 12px; }
758
 
                    pre { background-color: silver; padding: 5px; font-family: Courier New; font-size: x-small; color: #000000;}
759
 
                    ul      { margin-top: 10px; margin-left: 20px; }
760
 
                    li      { list-style-type: none; margin-top: 10px; color: #000000; }
761
 
                    .content{
762
 
                        margin-left: 0px; padding-bottom: 2em; }
763
 
                    .nav {
764
 
                        padding-top: 10px; padding-bottom: 10px; padding-left: 15px; font-size: .70em;
765
 
                        margin-top: 10px; margin-left: 0px; color: #000000;
766
 
                        background-color: #ccccff; width: 20%; margin-left: 20px; margin-top: 20px; }
767
 
                    .title {
768
 
                        font-family: arial; font-size: 26px; color: #ffffff;
769
 
                        background-color: #999999; width: 105%; margin-left: 0px;
770
 
                        padding-top: 10px; padding-bottom: 10px; padding-left: 15px;}
771
 
                    .hidden {
772
 
                        position: absolute; visibility: hidden; z-index: 200; left: 250px; top: 100px;
773
 
                        font-family: arial; overflow: hidden; width: 600;
774
 
                        padding: 20px; font-size: 10px; background-color: #999999;
775
 
                        layer-background-color:#FFFFFF; }
776
 
                    a,a:active  { color: charcoal; font-weight: bold; }
777
 
                    a:visited   { color: #666666; font-weight: bold; }
778
 
                    a:hover     { color: cc3300; font-weight: bold; }
779
 
                </style>
780
 
                <script language="JavaScript" type="text/javascript">
781
 
                <!--
782
 
                // POP-UP CAPTIONS...
783
 
                function lib_bwcheck(){ //Browsercheck (needed)
784
 
                    this.ver=navigator.appVersion
785
 
                    this.agent=navigator.userAgent
786
 
                    this.dom=document.getElementById?1:0
787
 
                    this.opera5=this.agent.indexOf("Opera 5")>-1
788
 
                    this.ie5=(this.ver.indexOf("MSIE 5")>-1 && this.dom && !this.opera5)?1:0;
789
 
                    this.ie6=(this.ver.indexOf("MSIE 6")>-1 && this.dom && !this.opera5)?1:0;
790
 
                    this.ie4=(document.all && !this.dom && !this.opera5)?1:0;
791
 
                    this.ie=this.ie4||this.ie5||this.ie6
792
 
                    this.mac=this.agent.indexOf("Mac")>-1
793
 
                    this.ns6=(this.dom && parseInt(this.ver) >= 5) ?1:0;
794
 
                    this.ns4=(document.layers && !this.dom)?1:0;
795
 
                    this.bw=(this.ie6 || this.ie5 || this.ie4 || this.ns4 || this.ns6 || this.opera5)
796
 
                    return this
797
 
                }
798
 
                var bw = new lib_bwcheck()
799
 
                //Makes crossbrowser object.
800
 
                function makeObj(obj){
801
 
                    this.evnt=bw.dom? document.getElementById(obj):bw.ie4?document.all[obj]:bw.ns4?document.layers[obj]:0;
802
 
                    if(!this.evnt) return false
803
 
                    this.css=bw.dom||bw.ie4?this.evnt.style:bw.ns4?this.evnt:0;
804
 
                    this.wref=bw.dom||bw.ie4?this.evnt:bw.ns4?this.css.document:0;
805
 
                    this.writeIt=b_writeIt;
806
 
                    return this
807
 
                }
808
 
                // A unit of measure that will be added when setting the position of a layer.
809
 
                //var px = bw.ns4||window.opera?"":"px";
810
 
                function b_writeIt(text){
811
 
                    if (bw.ns4){this.wref.write(text);this.wref.close()}
812
 
                    else this.wref.innerHTML = text
813
 
                }
814
 
                //Shows the messages
815
 
                var oDesc;
816
 
                function popup(divid){
817
 
                    if(oDesc = new makeObj(divid)){
818
 
                        oDesc.css.visibility = "visible"
819
 
                    }
820
 
                }
821
 
                function popout(){ // Hides message
822
 
                    if(oDesc) oDesc.css.visibility = "hidden"
823
 
                }
824
 
                //-->
825
 
                </script>
826
 
                </head>
827
 
                <body>
828
 
                <div class=content>
829
 
                        <br><br>
830
 
                        <div class=title>'.$this->serviceName.'</div>
831
 
                        <div class=nav>
832
 
                                <p>View the <a href="'.$PHP_SELF.'?wsdl">WSDL</a> for the service.
833
 
                                Click on an operation name to view it&apos;s details.</p>
834
 
                                <ul>';
835
 
                                foreach($this->getOperations() as $op => $data){
836
 
                                    $b .= "<li><a href='#' onclick=\"popout();popup('$op')\">$op</a></li>";
837
 
                                    // create hidden div
838
 
                                    $b .= "<div id='$op' class='hidden'>
839
 
                                    <a href='#' onclick='popout()'><font color='#ffffff'>Close</font></a><br><br>";
840
 
                                    foreach($data as $donnie => $marie){ // loop through opdata
841
 
                                                if($donnie == 'input' || $donnie == 'output'){ // show input/output data
842
 
                                                    $b .= "<font color='white'>".ucfirst($donnie).':</font><br>';
843
 
                                                    foreach($marie as $captain => $tenille){ // loop through data
844
 
                                                                if($captain == 'parts'){ // loop thru parts
845
 
                                                                    $b .= "&nbsp;&nbsp;$captain:<br>";
846
 
                                                        //if(is_array($tenille)){
847
 
                                                                        foreach($tenille as $joanie => $chachi){
848
 
                                                                                        $b .= "&nbsp;&nbsp;&nbsp;&nbsp;$joanie: $chachi<br>";
849
 
                                                                        }
850
 
                                                                //}
851
 
                                                                } else {
852
 
                                                                    $b .= "&nbsp;&nbsp;$captain: $tenille<br>";
853
 
                                                                }
854
 
                                                    }
855
 
                                                } else {
856
 
                                                    $b .= "<font color='white'>".ucfirst($donnie).":</font> $marie<br>";
857
 
                                                }
858
 
                                    }
859
 
                                        $b .= '</div>';
860
 
                                }
861
 
                                $b .= '
862
 
                                <ul>
863
 
                        </div>
864
 
                </div></body></html>';
865
 
                return $b;
866
 
    }
867
 
 
868
 
        /**
869
 
        * serialize the parsed wsdl
870
 
        *
871
 
        * @param mixed $debug whether to put debug=1 in endpoint URL
872
 
        * @return string serialization of WSDL
873
 
        * @access public 
874
 
        */
875
 
        function serialize($debug = 0)
876
 
        {
877
 
                $xml = '<?xml version="1.0" encoding="ISO-8859-1"?>';
878
 
                $xml .= "\n<definitions";
879
 
                foreach($this->namespaces as $k => $v) {
880
 
                        $xml .= " xmlns:$k=\"$v\"";
881
 
                } 
882
 
                // 10.9.02 - add poulter fix for wsdl and tns declarations
883
 
                if (isset($this->namespaces['wsdl'])) {
884
 
                        $xml .= " xmlns=\"" . $this->namespaces['wsdl'] . "\"";
885
 
                } 
886
 
                if (isset($this->namespaces['tns'])) {
887
 
                        $xml .= " targetNamespace=\"" . $this->namespaces['tns'] . "\"";
888
 
                } 
889
 
                $xml .= '>'; 
890
 
                // imports
891
 
                if (sizeof($this->import) > 0) {
892
 
                        foreach($this->import as $ns => $list) {
893
 
                                foreach ($list as $ii) {
894
 
                                        if ($ii['location'] != '') {
895
 
                                                $xml .= '<import location="' . $ii['location'] . '" namespace="' . $ns . '" />';
896
 
                                        } else {
897
 
                                                $xml .= '<import namespace="' . $ns . '" />';
898
 
                                        }
899
 
                                }
900
 
                        } 
901
 
                } 
902
 
                // types
903
 
                if (count($this->schemas)>=1) {
904
 
                        $xml .= "\n<types>\n";
905
 
                        foreach ($this->schemas as $ns => $list) {
906
 
                                foreach ($list as $xs) {
907
 
                                        $xml .= $xs->serializeSchema();
908
 
                                }
909
 
                        }
910
 
                        $xml .= '</types>';
911
 
                } 
912
 
                // messages
913
 
                if (count($this->messages) >= 1) {
914
 
                        foreach($this->messages as $msgName => $msgParts) {
915
 
                                $xml .= "\n<message name=\"" . $msgName . '">';
916
 
                                if(is_array($msgParts)){
917
 
                                        foreach($msgParts as $partName => $partType) {
918
 
                                                // print 'serializing '.$partType.', sv: '.$this->XMLSchemaVersion.'<br>';
919
 
                                                if (strpos($partType, ':')) {
920
 
                                                    $typePrefix = $this->getPrefixFromNamespace($this->getPrefix($partType));
921
 
                                                } elseif (isset($this->typemap[$this->namespaces['xsd']][$partType])) {
922
 
                                                    // print 'checking typemap: '.$this->XMLSchemaVersion.'<br>';
923
 
                                                    $typePrefix = 'xsd';
924
 
                                                } else {
925
 
                                                    foreach($this->typemap as $ns => $types) {
926
 
                                                        if (isset($types[$partType])) {
927
 
                                                            $typePrefix = $this->getPrefixFromNamespace($ns);
928
 
                                                        } 
929
 
                                                    } 
930
 
                                                    if (!isset($typePrefix)) {
931
 
                                                        die("$partType has no namespace!");
932
 
                                                    } 
933
 
                                                }
934
 
                                                $ns = $this->getNamespaceFromPrefix($typePrefix);
935
 
                                                $localPart = $this->getLocalPart($partType);
936
 
                                                $typeDef = $this->getTypeDef($localPart, $ns);
937
 
                                                if ($typeDef['typeClass'] == 'element') {
938
 
                                                        $elementortype = 'element';
939
 
                                                        if (substr($localPart, -1) == '^') {
940
 
                                                                $localPart = substr($localPart, 0, -1);
941
 
                                                        }
942
 
                                                } else {
943
 
                                                        $elementortype = 'type';
944
 
                                                }
945
 
                                                $xml .= "\n" . '  <part name="' . $partName . '" ' . $elementortype . '="' . $typePrefix . ':' . $localPart . '" />';
946
 
                                        }
947
 
                                }
948
 
                                $xml .= '</message>';
949
 
                        } 
950
 
                } 
951
 
                // bindings & porttypes
952
 
                if (count($this->bindings) >= 1) {
953
 
                        $binding_xml = '';
954
 
                        $portType_xml = '';
955
 
                        foreach($this->bindings as $bindingName => $attrs) {
956
 
                                $binding_xml .= "\n<binding name=\"" . $bindingName . '" type="tns:' . $attrs['portType'] . '">';
957
 
                                $binding_xml .= "\n" . '  <soap:binding style="' . $attrs['style'] . '" transport="' . $attrs['transport'] . '"/>';
958
 
                                $portType_xml .= "\n<portType name=\"" . $attrs['portType'] . '">';
959
 
                                foreach($attrs['operations'] as $opName => $opParts) {
960
 
                                        $binding_xml .= "\n" . '  <operation name="' . $opName . '">';
961
 
                                        $binding_xml .= "\n" . '    <soap:operation soapAction="' . $opParts['soapAction'] . '" style="'. $opParts['style'] . '"/>';
962
 
                                        if (isset($opParts['input']['encodingStyle']) && $opParts['input']['encodingStyle'] != '') {
963
 
                                                $enc_style = ' encodingStyle="' . $opParts['input']['encodingStyle'] . '"';
964
 
                                        } else {
965
 
                                                $enc_style = '';
966
 
                                        }
967
 
                                        $binding_xml .= "\n" . '    <input><soap:body use="' . $opParts['input']['use'] . '" namespace="' . $opParts['input']['namespace'] . '"' . $enc_style . '/></input>';
968
 
                                        if (isset($opParts['output']['encodingStyle']) && $opParts['output']['encodingStyle'] != '') {
969
 
                                                $enc_style = ' encodingStyle="' . $opParts['output']['encodingStyle'] . '"';
970
 
                                        } else {
971
 
                                                $enc_style = '';
972
 
                                        }
973
 
                                        $binding_xml .= "\n" . '    <output><soap:body use="' . $opParts['output']['use'] . '" namespace="' . $opParts['output']['namespace'] . '"' . $enc_style . '/></output>';
974
 
                                        $binding_xml .= "\n" . '  </operation>';
975
 
                                        $portType_xml .= "\n" . '  <operation name="' . $opParts['name'] . '"';
976
 
                                        if (isset($opParts['parameterOrder'])) {
977
 
                                            $portType_xml .= ' parameterOrder="' . $opParts['parameterOrder'] . '"';
978
 
                                        } 
979
 
                                        $portType_xml .= '>';
980
 
                                        if(isset($opParts['documentation']) && $opParts['documentation'] != '') {
981
 
                                                $portType_xml .= "\n" . '    <documentation>' . htmlspecialchars($opParts['documentation']) . '</documentation>';
982
 
                                        }
983
 
                                        $portType_xml .= "\n" . '    <input message="tns:' . $opParts['input']['message'] . '"/>';
984
 
                                        $portType_xml .= "\n" . '    <output message="tns:' . $opParts['output']['message'] . '"/>';
985
 
                                        $portType_xml .= "\n" . '  </operation>';
986
 
                                } 
987
 
                                $portType_xml .= "\n" . '</portType>';
988
 
                                $binding_xml .= "\n" . '</binding>';
989
 
                        } 
990
 
                        $xml .= $portType_xml . $binding_xml;
991
 
                } 
992
 
                // services
993
 
                $xml .= "\n<service name=\"" . $this->serviceName . '">';
994
 
                if (count($this->ports) >= 1) {
995
 
                        foreach($this->ports as $pName => $attrs) {
996
 
                                $xml .= "\n" . '  <port name="' . $pName . '" binding="tns:' . $attrs['binding'] . '">';
997
 
                                $xml .= "\n" . '    <soap:address location="' . $attrs['location'] . ($debug ? '?debug=1' : '') . '"/>';
998
 
                                $xml .= "\n" . '  </port>';
999
 
                        } 
1000
 
                } 
1001
 
                $xml .= "\n" . '</service>';
1002
 
                return $xml . "\n</definitions>";
1003
 
        } 
1004
 
 
1005
 
        /**
1006
 
         * determine whether a set of parameters are unwrapped
1007
 
         * when they are expect to be wrapped, Microsoft-style.
1008
 
         *
1009
 
         * @param string $type the type (element name) of the wrapper
1010
 
         * @param array $parameters the parameter values for the SOAP call
1011
 
         * @return boolean whether they parameters are unwrapped (and should be wrapped)
1012
 
         * @access private
1013
 
         */
1014
 
        function parametersMatchWrapped($type, &$parameters) {
1015
 
                $this->debug("in parametersMatchWrapped type=$type, parameters=");
1016
 
                $this->appendDebug($this->varDump($parameters));
1017
 
 
1018
 
                // split type into namespace:unqualified-type
1019
 
                if (strpos($type, ':')) {
1020
 
                        $uqType = substr($type, strrpos($type, ':') + 1);
1021
 
                        $ns = substr($type, 0, strrpos($type, ':'));
1022
 
                        $this->debug("in parametersMatchWrapped: got a prefixed type: $uqType, $ns");
1023
 
                        if ($this->getNamespaceFromPrefix($ns)) {
1024
 
                                $ns = $this->getNamespaceFromPrefix($ns);
1025
 
                                $this->debug("in parametersMatchWrapped: expanded prefixed type: $uqType, $ns");
1026
 
                        }
1027
 
                } else {
1028
 
                        // TODO: should the type be compared to types in XSD, and the namespace
1029
 
                        // set to XSD if the type matches?
1030
 
                        $this->debug("in parametersMatchWrapped: No namespace for type $type");
1031
 
                        $ns = '';
1032
 
                        $uqType = $type;
1033
 
                }
1034
 
 
1035
 
                // get the type information
1036
 
                if (!$typeDef = $this->getTypeDef($uqType, $ns)) {
1037
 
                        $this->debug("in parametersMatchWrapped: $type ($uqType) is not a supported type.");
1038
 
                        return false;
1039
 
                }
1040
 
                $this->debug("in parametersMatchWrapped: found typeDef=");
1041
 
                $this->appendDebug($this->varDump($typeDef));
1042
 
                if (substr($uqType, -1) == '^') {
1043
 
                        $uqType = substr($uqType, 0, -1);
1044
 
                }
1045
 
                $phpType = $typeDef['phpType'];
1046
 
                $arrayType = (isset($typeDef['arrayType']) ? $typeDef['arrayType'] : '');
1047
 
                $this->debug("in parametersMatchWrapped: uqType: $uqType, ns: $ns, phptype: $phpType, arrayType: $arrayType");
1048
 
                
1049
 
                // we expect a complexType or element of complexType
1050
 
                if ($phpType != 'struct') {
1051
 
                        $this->debug("in parametersMatchWrapped: not a struct");
1052
 
                        return false;
1053
 
                }
1054
 
 
1055
 
                // see whether the parameter names match the elements
1056
 
                if (isset($typeDef['elements']) && is_array($typeDef['elements'])) {
1057
 
                        $elements = 0;
1058
 
                        $matches = 0;
1059
 
                        $change = false;
1060
 
                        if ($this->isArraySimpleOrStruct($parameters) == 'arraySimple' && count($parameters) == count($typeDef['elements'])) {
1061
 
                                $this->debug("in parametersMatchWrapped: (wrapped return value kludge) correct number of elements in simple array, so change array and wrap");
1062
 
                                $change = true;
1063
 
                        }
1064
 
                        foreach ($typeDef['elements'] as $name => $attrs) {
1065
 
                                if ($change) {
1066
 
                                        $this->debug("in parametersMatchWrapped: change parameter $element to name $name");
1067
 
                                        $parameters[$name] = $parameters[$elements];
1068
 
                                        unset($parameters[$elements]);
1069
 
                                        $matches++;
1070
 
                                } elseif (isset($parameters[$name])) {
1071
 
                                        $this->debug("in parametersMatchWrapped: have parameter named $name");
1072
 
                                        $matches++;
1073
 
                                } else {
1074
 
                                        $this->debug("in parametersMatchWrapped: do not have parameter named $name");
1075
 
                                }
1076
 
                                $elements++;
1077
 
                        }
1078
 
 
1079
 
                        $this->debug("in parametersMatchWrapped: $matches parameter names match $elements wrapped parameter names");
1080
 
                        if ($matches == 0) {
1081
 
                                return false;
1082
 
                        }
1083
 
                        return true;
1084
 
                }
1085
 
 
1086
 
                // since there are no elements for the type, if the user passed no
1087
 
                // parameters, the parameters match wrapped.
1088
 
                $this->debug("in parametersMatchWrapped: no elements type $ns:$uqType");
1089
 
                return count($parameters) == 0;
1090
 
        }
1091
 
 
1092
 
        /**
1093
 
         * serialize PHP values according to a WSDL message definition
1094
 
         * contrary to the method name, this is not limited to RPC
1095
 
         *
1096
 
         * TODO
1097
 
         * - multi-ref serialization
1098
 
         * - validate PHP values against type definitions, return errors if invalid
1099
 
         * 
1100
 
         * @param string $operation operation name
1101
 
         * @param string $direction (input|output)
1102
 
         * @param mixed $parameters parameter value(s)
1103
 
         * @param string $bindingType (soap|soap12)
1104
 
         * @return mixed parameters serialized as XML or false on error (e.g. operation not found)
1105
 
         * @access public
1106
 
         */
1107
 
        function serializeRPCParameters($operation, $direction, $parameters, $bindingType = 'soap') {
1108
 
                $this->debug("in serializeRPCParameters: operation=$operation, direction=$direction, XMLSchemaVersion=$this->XMLSchemaVersion, bindingType=$bindingType");
1109
 
                $this->appendDebug('parameters=' . $this->varDump($parameters));
1110
 
                
1111
 
                if ($direction != 'input' && $direction != 'output') {
1112
 
                        $this->debug('The value of the \$direction argument needs to be either "input" or "output"');
1113
 
                        $this->setError('The value of the \$direction argument needs to be either "input" or "output"');
1114
 
                        return false;
1115
 
                } 
1116
 
                if (!$opData = $this->getOperationData($operation, $bindingType)) {
1117
 
                        $this->debug('Unable to retrieve WSDL data for operation: ' . $operation . ' bindingType: ' . $bindingType);
1118
 
                        $this->setError('Unable to retrieve WSDL data for operation: ' . $operation . ' bindingType: ' . $bindingType);
1119
 
                        return false;
1120
 
                }
1121
 
                $this->debug('in serializeRPCParameters: opData:');
1122
 
                $this->appendDebug($this->varDump($opData));
1123
 
 
1124
 
                // Get encoding style for output and set to current
1125
 
                $encodingStyle = 'http://schemas.xmlsoap.org/soap/encoding/';
1126
 
                if(($direction == 'input') && isset($opData['output']['encodingStyle']) && ($opData['output']['encodingStyle'] != $encodingStyle)) {
1127
 
                        $encodingStyle = $opData['output']['encodingStyle'];
1128
 
                        $enc_style = $encodingStyle;
1129
 
                }
1130
 
 
1131
 
                // set input params
1132
 
                $xml = '';
1133
 
                if (isset($opData[$direction]['parts']) && sizeof($opData[$direction]['parts']) > 0) {
1134
 
                        $parts = &$opData[$direction]['parts'];
1135
 
                        $part_count = sizeof($parts);
1136
 
                        $style = $opData['style'];
1137
 
                        $use = $opData[$direction]['use'];
1138
 
                        $this->debug("have $part_count part(s) to serialize using $style/$use");
1139
 
                        if (is_array($parameters)) {
1140
 
                                $parametersArrayType = $this->isArraySimpleOrStruct($parameters);
1141
 
                                $parameter_count = count($parameters);
1142
 
                                $this->debug("have $parameter_count parameter(s) provided as $parametersArrayType to serialize");
1143
 
                                // check for Microsoft-style wrapped parameters
1144
 
                                if ($style == 'document' && $use == 'literal' && $part_count == 1 && isset($parts['parameters'])) {
1145
 
                                        $this->debug('check whether the caller has wrapped the parameters');
1146
 
                                        if ((($parametersArrayType == 'arrayStruct' || $parameter_count == 0) && !isset($parameters['parameters'])) || ($direction == 'output' && $parametersArrayType == 'arraySimple' && $parameter_count == 1)) {
1147
 
                                                $this->debug('check whether caller\'s parameters match the wrapped ones');
1148
 
                                                if ($this->parametersMatchWrapped($parts['parameters'], $parameters)) {
1149
 
                                                        $this->debug('wrap the parameters for the caller');
1150
 
                                                        $parameters = array('parameters' => $parameters);
1151
 
                                                        $parameter_count = 1;
1152
 
                                                }
1153
 
                                        }
1154
 
                                }
1155
 
                                foreach ($parts as $name => $type) {
1156
 
                                        $this->debug("serializing part $name of type $type");
1157
 
                                        // Track encoding style
1158
 
                                        if (isset($opData[$direction]['encodingStyle']) && $encodingStyle != $opData[$direction]['encodingStyle']) {
1159
 
                                                $encodingStyle = $opData[$direction]['encodingStyle'];                  
1160
 
                                                $enc_style = $encodingStyle;
1161
 
                                        } else {
1162
 
                                                $enc_style = false;
1163
 
                                        }
1164
 
                                        // NOTE: add error handling here
1165
 
                                        // if serializeType returns false, then catch global error and fault
1166
 
                                        if ($parametersArrayType == 'arraySimple') {
1167
 
                                                $p = array_shift($parameters);
1168
 
                                                $this->debug('calling serializeType w/indexed param');
1169
 
                                                $xml .= $this->serializeType($name, $type, $p, $use, $enc_style);
1170
 
                                        } elseif (isset($parameters[$name])) {
1171
 
                                                $this->debug('calling serializeType w/named param');
1172
 
                                                $xml .= $this->serializeType($name, $type, $parameters[$name], $use, $enc_style);
1173
 
                                        } else {
1174
 
                                                // TODO: only send nillable
1175
 
                                                $this->debug('calling serializeType w/null param');
1176
 
                                                $xml .= $this->serializeType($name, $type, null, $use, $enc_style);
1177
 
                                        }
1178
 
                                }
1179
 
                        } else {
1180
 
                                $this->debug('no parameters passed.');
1181
 
                        }
1182
 
                }
1183
 
                $this->debug("serializeRPCParameters returning: $xml");
1184
 
                return $xml;
1185
 
        } 
1186
 
        
1187
 
        /**
1188
 
         * serialize a PHP value according to a WSDL message definition
1189
 
         * 
1190
 
         * TODO
1191
 
         * - multi-ref serialization
1192
 
         * - validate PHP values against type definitions, return errors if invalid
1193
 
         * 
1194
 
         * @param string $operation operation name
1195
 
         * @param string $direction (input|output)
1196
 
         * @param mixed $parameters parameter value(s)
1197
 
         * @return mixed parameters serialized as XML or false on error (e.g. operation not found)
1198
 
         * @access public
1199
 
         * @deprecated
1200
 
         */
1201
 
        function serializeParameters($operation, $direction, $parameters)
1202
 
        {
1203
 
                $this->debug("in serializeParameters: operation=$operation, direction=$direction, XMLSchemaVersion=$this->XMLSchemaVersion"); 
1204
 
                $this->appendDebug('parameters=' . $this->varDump($parameters));
1205
 
                
1206
 
                if ($direction != 'input' && $direction != 'output') {
1207
 
                        $this->debug('The value of the \$direction argument needs to be either "input" or "output"');
1208
 
                        $this->setError('The value of the \$direction argument needs to be either "input" or "output"');
1209
 
                        return false;
1210
 
                } 
1211
 
                if (!$opData = $this->getOperationData($operation)) {
1212
 
                        $this->debug('Unable to retrieve WSDL data for operation: ' . $operation);
1213
 
                        $this->setError('Unable to retrieve WSDL data for operation: ' . $operation);
1214
 
                        return false;
1215
 
                }
1216
 
                $this->debug('opData:');
1217
 
                $this->appendDebug($this->varDump($opData));
1218
 
                
1219
 
                // Get encoding style for output and set to current
1220
 
                $encodingStyle = 'http://schemas.xmlsoap.org/soap/encoding/';
1221
 
                if(($direction == 'input') && isset($opData['output']['encodingStyle']) && ($opData['output']['encodingStyle'] != $encodingStyle)) {
1222
 
                        $encodingStyle = $opData['output']['encodingStyle'];
1223
 
                        $enc_style = $encodingStyle;
1224
 
                }
1225
 
                
1226
 
                // set input params
1227
 
                $xml = '';
1228
 
                if (isset($opData[$direction]['parts']) && sizeof($opData[$direction]['parts']) > 0) {
1229
 
                        
1230
 
                        $use = $opData[$direction]['use'];
1231
 
                        $this->debug("use=$use");
1232
 
                        $this->debug('got ' . count($opData[$direction]['parts']) . ' part(s)');
1233
 
                        if (is_array($parameters)) {
1234
 
                                $parametersArrayType = $this->isArraySimpleOrStruct($parameters);
1235
 
                                $this->debug('have ' . $parametersArrayType . ' parameters');
1236
 
                                foreach($opData[$direction]['parts'] as $name => $type) {
1237
 
                                        $this->debug('serializing part "'.$name.'" of type "'.$type.'"');
1238
 
                                        // Track encoding style
1239
 
                                        if(isset($opData[$direction]['encodingStyle']) && $encodingStyle != $opData[$direction]['encodingStyle']) {
1240
 
                                                $encodingStyle = $opData[$direction]['encodingStyle'];                  
1241
 
                                                $enc_style = $encodingStyle;
1242
 
                                        } else {
1243
 
                                                $enc_style = false;
1244
 
                                        }
1245
 
                                        // NOTE: add error handling here
1246
 
                                        // if serializeType returns false, then catch global error and fault
1247
 
                                        if ($parametersArrayType == 'arraySimple') {
1248
 
                                                $p = array_shift($parameters);
1249
 
                                                $this->debug('calling serializeType w/indexed param');
1250
 
                                                $xml .= $this->serializeType($name, $type, $p, $use, $enc_style);
1251
 
                                        } elseif (isset($parameters[$name])) {
1252
 
                                                $this->debug('calling serializeType w/named param');
1253
 
                                                $xml .= $this->serializeType($name, $type, $parameters[$name], $use, $enc_style);
1254
 
                                        } else {
1255
 
                                                // TODO: only send nillable
1256
 
                                                $this->debug('calling serializeType w/null param');
1257
 
                                                $xml .= $this->serializeType($name, $type, null, $use, $enc_style);
1258
 
                                        }
1259
 
                                }
1260
 
                        } else {
1261
 
                                $this->debug('no parameters passed.');
1262
 
                        }
1263
 
                }
1264
 
                $this->debug("serializeParameters returning: $xml");
1265
 
                return $xml;
1266
 
        } 
1267
 
        
1268
 
        /**
1269
 
         * serializes a PHP value according a given type definition
1270
 
         * 
1271
 
         * @param string $name name of value (part or element)
1272
 
         * @param string $type XML schema type of value (type or element)
1273
 
         * @param mixed $value a native PHP value (parameter value)
1274
 
         * @param string $use use for part (encoded|literal)
1275
 
         * @param string $encodingStyle SOAP encoding style for the value (if different than the enclosing style)
1276
 
         * @param boolean $unqualified a kludge for what should be XML namespace form handling
1277
 
         * @return string value serialized as an XML string
1278
 
         * @access private
1279
 
         */
1280
 
        function serializeType($name, $type, $value, $use='encoded', $encodingStyle=false, $unqualified=false)
1281
 
        {
1282
 
                $this->debug("in serializeType: name=$name, type=$type, use=$use, encodingStyle=$encodingStyle, unqualified=" . ($unqualified ? "unqualified" : "qualified"));
1283
 
                $this->appendDebug("value=" . $this->varDump($value));
1284
 
                if($use == 'encoded' && $encodingStyle) {
1285
 
                        $encodingStyle = ' SOAP-ENV:encodingStyle="' . $encodingStyle . '"';
1286
 
                }
1287
 
 
1288
 
                // if a soapval has been supplied, let its type override the WSDL
1289
 
        if (is_object($value) && get_class($value) == 'soapval') {
1290
 
                if ($value->type_ns) {
1291
 
                        $type = $value->type_ns . ':' . $value->type;
1292
 
                        $forceType = true;
1293
 
                        $this->debug("in serializeType: soapval overrides type to $type");
1294
 
                } elseif ($value->type) {
1295
 
                        $type = $value->type;
1296
 
                        $forceType = true;
1297
 
                        $this->debug("in serializeType: soapval overrides type to $type");
1298
 
                } else {
1299
 
                        $forceType = false;
1300
 
                        $this->debug("in serializeType: soapval does not override type");
1301
 
                }
1302
 
                $attrs = $value->attributes;
1303
 
                $value = $value->value;
1304
 
                $this->debug("in serializeType: soapval overrides value to $value");
1305
 
                if ($attrs) {
1306
 
                        if (!is_array($value)) {
1307
 
                                $value['!'] = $value;
1308
 
                        }
1309
 
                        foreach ($attrs as $n => $v) {
1310
 
                                $value['!' . $n] = $v;
1311
 
                        }
1312
 
                        $this->debug("in serializeType: soapval provides attributes");
1313
 
                    }
1314
 
        } else {
1315
 
                $forceType = false;
1316
 
        }
1317
 
 
1318
 
                $xml = '';
1319
 
                if (strpos($type, ':')) {
1320
 
                        $uqType = substr($type, strrpos($type, ':') + 1);
1321
 
                        $ns = substr($type, 0, strrpos($type, ':'));
1322
 
                        $this->debug("in serializeType: got a prefixed type: $uqType, $ns");
1323
 
                        if ($this->getNamespaceFromPrefix($ns)) {
1324
 
                                $ns = $this->getNamespaceFromPrefix($ns);
1325
 
                                $this->debug("in serializeType: expanded prefixed type: $uqType, $ns");
1326
 
                        }
1327
 
 
1328
 
                        if($ns == $this->XMLSchemaVersion || $ns == 'http://schemas.xmlsoap.org/soap/encoding/'){
1329
 
                                $this->debug('in serializeType: type namespace indicates XML Schema or SOAP Encoding type');
1330
 
                                if ($unqualified && $use == 'literal') {
1331
 
                                        $elementNS = " xmlns=\"\"";
1332
 
                                } else {
1333
 
                                        $elementNS = '';
1334
 
                                }
1335
 
                                if (is_null($value)) {
1336
 
                                        if ($use == 'literal') {
1337
 
                                                // TODO: depends on minOccurs
1338
 
                                                $xml = "<$name$elementNS/>";
1339
 
                                        } else {
1340
 
                                                // TODO: depends on nillable, which should be checked before calling this method
1341
 
                                                $xml = "<$name$elementNS xsi:nil=\"true\" xsi:type=\"" . $this->getPrefixFromNamespace($ns) . ":$uqType\"/>";
1342
 
                                        }
1343
 
                                        $this->debug("in serializeType: returning: $xml");
1344
 
                                        return $xml;
1345
 
                                }
1346
 
                                if ($uqType == 'Array') {
1347
 
                                        // JBoss/Axis does this sometimes
1348
 
                                        return $this->serialize_val($value, $name, false, false, false, false, $use);
1349
 
                                }
1350
 
                        if ($uqType == 'boolean') {
1351
 
                                if ((is_string($value) && $value == 'false') || (! $value)) {
1352
 
                                                $value = 'false';
1353
 
                                        } else {
1354
 
                                                $value = 'true';
1355
 
                                        }
1356
 
                                } 
1357
 
                                if ($uqType == 'string' && gettype($value) == 'string') {
1358
 
                                        $value = $this->expandEntities($value);
1359
 
                                }
1360
 
                                if (($uqType == 'long' || $uqType == 'unsignedLong') && gettype($value) == 'double') {
1361
 
                                        $value = sprintf("%.0lf", $value);
1362
 
                                }
1363
 
                                // it's a scalar
1364
 
                                // TODO: what about null/nil values?
1365
 
                                // check type isn't a custom type extending xmlschema namespace
1366
 
                                if (!$this->getTypeDef($uqType, $ns)) {
1367
 
                                        if ($use == 'literal') {
1368
 
                                                if ($forceType) {
1369
 
                                                        $xml = "<$name$elementNS xsi:type=\"" . $this->getPrefixFromNamespace($ns) . ":$uqType\">$value</$name>";
1370
 
                                                } else {
1371
 
                                                        $xml = "<$name$elementNS>$value</$name>";
1372
 
                                                }
1373
 
                                        } else {
1374
 
                                                $xml = "<$name$elementNS xsi:type=\"" . $this->getPrefixFromNamespace($ns) . ":$uqType\"$encodingStyle>$value</$name>";
1375
 
                                        }
1376
 
                                        $this->debug("in serializeType: returning: $xml");
1377
 
                                        return $xml;
1378
 
                                }
1379
 
                                $this->debug('custom type extends XML Schema or SOAP Encoding namespace (yuck)');
1380
 
                        } else if ($ns == 'http://xml.apache.org/xml-soap') {
1381
 
                                $this->debug('in serializeType: appears to be Apache SOAP type');
1382
 
                                if ($uqType == 'Map') {
1383
 
                                        $tt_prefix = $this->getPrefixFromNamespace('http://xml.apache.org/xml-soap');
1384
 
                                        if (! $tt_prefix) {
1385
 
                                                $this->debug('in serializeType: Add namespace for Apache SOAP type');
1386
 
                                                $tt_prefix = 'ns' . rand(1000, 9999);
1387
 
                                                $this->namespaces[$tt_prefix] = 'http://xml.apache.org/xml-soap';
1388
 
                                                // force this to be added to usedNamespaces
1389
 
                                                $tt_prefix = $this->getPrefixFromNamespace('http://xml.apache.org/xml-soap');
1390
 
                                        }
1391
 
                                        $contents = '';
1392
 
                                        foreach($value as $k => $v) {
1393
 
                                                $this->debug("serializing map element: key $k, value $v");
1394
 
                                                $contents .= '<item>';
1395
 
                                                $contents .= $this->serialize_val($k,'key',false,false,false,false,$use);
1396
 
                                                $contents .= $this->serialize_val($v,'value',false,false,false,false,$use);
1397
 
                                                $contents .= '</item>';
1398
 
                                        }
1399
 
                                        if ($use == 'literal') {
1400
 
                                                if ($forceType) {
1401
 
                                                        $xml = "<$name xsi:type=\"" . $tt_prefix . ":$uqType\">$contents</$name>";
1402
 
                                                } else {
1403
 
                                                        $xml = "<$name>$contents</$name>";
1404
 
                                                }
1405
 
                                        } else {
1406
 
                                                $xml = "<$name xsi:type=\"" . $tt_prefix . ":$uqType\"$encodingStyle>$contents</$name>";
1407
 
                                        }
1408
 
                                        $this->debug("in serializeType: returning: $xml");
1409
 
                                        return $xml;
1410
 
                                }
1411
 
                                $this->debug('in serializeType: Apache SOAP type, but only support Map');
1412
 
                        }
1413
 
                } else {
1414
 
                        // TODO: should the type be compared to types in XSD, and the namespace
1415
 
                        // set to XSD if the type matches?
1416
 
                        $this->debug("in serializeType: No namespace for type $type");
1417
 
                        $ns = '';
1418
 
                        $uqType = $type;
1419
 
                }
1420
 
                if(!$typeDef = $this->getTypeDef($uqType, $ns)){
1421
 
                        $this->setError("$type ($uqType) is not a supported type.");
1422
 
                        $this->debug("in serializeType: $type ($uqType) is not a supported type.");
1423
 
                        return false;
1424
 
                } else {
1425
 
                        $this->debug("in serializeType: found typeDef");
1426
 
                        $this->appendDebug('typeDef=' . $this->varDump($typeDef));
1427
 
                        if (substr($uqType, -1) == '^') {
1428
 
                                $uqType = substr($uqType, 0, -1);
1429
 
                        }
1430
 
                }
1431
 
                $phpType = $typeDef['phpType'];
1432
 
                $this->debug("in serializeType: uqType: $uqType, ns: $ns, phptype: $phpType, arrayType: " . (isset($typeDef['arrayType']) ? $typeDef['arrayType'] : '') ); 
1433
 
                // if php type == struct, map value to the <all> element names
1434
 
                if ($phpType == 'struct') {
1435
 
                        if (isset($typeDef['typeClass']) && $typeDef['typeClass'] == 'element') {
1436
 
                                $elementName = $uqType;
1437
 
                                if (isset($typeDef['form']) && ($typeDef['form'] == 'qualified')) {
1438
 
                                        $elementNS = " xmlns=\"$ns\"";
1439
 
                                } else {
1440
 
                                        $elementNS = " xmlns=\"\"";
1441
 
                                }
1442
 
                        } else {
1443
 
                                $elementName = $name;
1444
 
                                if ($unqualified) {
1445
 
                                        $elementNS = " xmlns=\"\"";
1446
 
                                } else {
1447
 
                                        $elementNS = '';
1448
 
                                }
1449
 
                        }
1450
 
                        if (is_null($value)) {
1451
 
                                if ($use == 'literal') {
1452
 
                                        // TODO: depends on minOccurs
1453
 
                                        $xml = "<$elementName$elementNS/>";
1454
 
                                } else {
1455
 
                                        $xml = "<$elementName$elementNS xsi:nil=\"true\" xsi:type=\"" . $this->getPrefixFromNamespace($ns) . ":$uqType\"/>";
1456
 
                                }
1457
 
                                $this->debug("in serializeType: returning: $xml");
1458
 
                                return $xml;
1459
 
                        }
1460
 
                        if (is_object($value)) {
1461
 
                                $value = get_object_vars($value);
1462
 
                        }
1463
 
                        if (is_array($value)) {
1464
 
                                $elementAttrs = $this->serializeComplexTypeAttributes($typeDef, $value, $ns, $uqType);
1465
 
                                if ($use == 'literal') {
1466
 
                                        if ($forceType) {
1467
 
                                                $xml = "<$elementName$elementNS$elementAttrs xsi:type=\"" . $this->getPrefixFromNamespace($ns) . ":$uqType\">";
1468
 
                                        } else {
1469
 
                                                $xml = "<$elementName$elementNS$elementAttrs>";
1470
 
                                        }
1471
 
                                } else {
1472
 
                                        $xml = "<$elementName$elementNS$elementAttrs xsi:type=\"" . $this->getPrefixFromNamespace($ns) . ":$uqType\"$encodingStyle>";
1473
 
                                }
1474
 
        
1475
 
                                $xml .= $this->serializeComplexTypeElements($typeDef, $value, $ns, $uqType, $use, $encodingStyle);
1476
 
                                $xml .= "</$elementName>";
1477
 
                        } else {
1478
 
                                $this->debug("in serializeType: phpType is struct, but value is not an array");
1479
 
                                $this->setError("phpType is struct, but value is not an array: see debug output for details");
1480
 
                                $xml = '';
1481
 
                        }
1482
 
                } elseif ($phpType == 'array') {
1483
 
                        if (isset($typeDef['form']) && ($typeDef['form'] == 'qualified')) {
1484
 
                                $elementNS = " xmlns=\"$ns\"";
1485
 
                        } else {
1486
 
                                if ($unqualified) {
1487
 
                                        $elementNS = " xmlns=\"\"";
1488
 
                                } else {
1489
 
                                        $elementNS = '';
1490
 
                                }
1491
 
                        }
1492
 
                        if (is_null($value)) {
1493
 
                                if ($use == 'literal') {
1494
 
                                        // TODO: depends on minOccurs
1495
 
                                        $xml = "<$name$elementNS/>";
1496
 
                                } else {
1497
 
                                        $xml = "<$name$elementNS xsi:nil=\"true\" xsi:type=\"" .
1498
 
                                                $this->getPrefixFromNamespace('http://schemas.xmlsoap.org/soap/encoding/') .
1499
 
                                                ":Array\" " .
1500
 
                                                $this->getPrefixFromNamespace('http://schemas.xmlsoap.org/soap/encoding/') .
1501
 
                                                ':arrayType="' .
1502
 
                                                $this->getPrefixFromNamespace($this->getPrefix($typeDef['arrayType'])) .
1503
 
                                                ':' .
1504
 
                                                $this->getLocalPart($typeDef['arrayType'])."[0]\"/>";
1505
 
                                }
1506
 
                                $this->debug("in serializeType: returning: $xml");
1507
 
                                return $xml;
1508
 
                        }
1509
 
                        if (isset($typeDef['multidimensional'])) {
1510
 
                                $nv = array();
1511
 
                                foreach($value as $v) {
1512
 
                                        $cols = ',' . sizeof($v);
1513
 
                                        $nv = array_merge($nv, $v);
1514
 
                                } 
1515
 
                                $value = $nv;
1516
 
                        } else {
1517
 
                                $cols = '';
1518
 
                        } 
1519
 
                        if (is_array($value) && sizeof($value) >= 1) {
1520
 
                                $rows = sizeof($value);
1521
 
                                $contents = '';
1522
 
                                foreach($value as $k => $v) {
1523
 
                                        $this->debug("serializing array element: $k, $v of type: $typeDef[arrayType]");
1524
 
                                        //if (strpos($typeDef['arrayType'], ':') ) {
1525
 
                                        if (!in_array($typeDef['arrayType'],$this->typemap['http://www.w3.org/2001/XMLSchema'])) {
1526
 
                                            $contents .= $this->serializeType('item', $typeDef['arrayType'], $v, $use);
1527
 
                                        } else {
1528
 
                                            $contents .= $this->serialize_val($v, 'item', $typeDef['arrayType'], null, $this->XMLSchemaVersion, false, $use);
1529
 
                                        } 
1530
 
                                }
1531
 
                        } else {
1532
 
                                $rows = 0;
1533
 
                                $contents = null;
1534
 
                        }
1535
 
                        // TODO: for now, an empty value will be serialized as a zero element
1536
 
                        // array.  Revisit this when coding the handling of null/nil values.
1537
 
                        if ($use == 'literal') {
1538
 
                                $xml = "<$name$elementNS>"
1539
 
                                        .$contents
1540
 
                                        ."</$name>";
1541
 
                        } else {
1542
 
                                $xml = "<$name$elementNS xsi:type=\"".$this->getPrefixFromNamespace('http://schemas.xmlsoap.org/soap/encoding/').':Array" '.
1543
 
                                        $this->getPrefixFromNamespace('http://schemas.xmlsoap.org/soap/encoding/')
1544
 
                                        .':arrayType="'
1545
 
                                        .$this->getPrefixFromNamespace($this->getPrefix($typeDef['arrayType']))
1546
 
                                        .":".$this->getLocalPart($typeDef['arrayType'])."[$rows$cols]\">"
1547
 
                                        .$contents
1548
 
                                        ."</$name>";
1549
 
                        }
1550
 
                } elseif ($phpType == 'scalar') {
1551
 
                        if (isset($typeDef['form']) && ($typeDef['form'] == 'qualified')) {
1552
 
                                $elementNS = " xmlns=\"$ns\"";
1553
 
                        } else {
1554
 
                                if ($unqualified) {
1555
 
                                        $elementNS = " xmlns=\"\"";
1556
 
                                } else {
1557
 
                                        $elementNS = '';
1558
 
                                }
1559
 
                        }
1560
 
                        if ($use == 'literal') {
1561
 
                                if ($forceType) {
1562
 
                                        $xml = "<$name$elementNS xsi:type=\"" . $this->getPrefixFromNamespace($ns) . ":$uqType\">$value</$name>";
1563
 
                                } else {
1564
 
                                        $xml = "<$name$elementNS>$value</$name>";
1565
 
                                }
1566
 
                        } else {
1567
 
                                $xml = "<$name$elementNS xsi:type=\"" . $this->getPrefixFromNamespace($ns) . ":$uqType\"$encodingStyle>$value</$name>";
1568
 
                        }
1569
 
                }
1570
 
                $this->debug("in serializeType: returning: $xml");
1571
 
                return $xml;
1572
 
        }
1573
 
        
1574
 
        /**
1575
 
         * serializes the attributes for a complexType
1576
 
         *
1577
 
         * @param array $typeDef our internal representation of an XML schema type (or element)
1578
 
         * @param mixed $value a native PHP value (parameter value)
1579
 
         * @param string $ns the namespace of the type
1580
 
         * @param string $uqType the local part of the type
1581
 
         * @return string value serialized as an XML string
1582
 
         * @access private
1583
 
         */
1584
 
        function serializeComplexTypeAttributes($typeDef, $value, $ns, $uqType) {
1585
 
                $xml = '';
1586
 
                if (isset($typeDef['attrs']) && is_array($typeDef['attrs'])) {
1587
 
                        $this->debug("serialize attributes for XML Schema type $ns:$uqType");
1588
 
                        if (is_array($value)) {
1589
 
                                $xvalue = $value;
1590
 
                        } elseif (is_object($value)) {
1591
 
                                $xvalue = get_object_vars($value);
1592
 
                        } else {
1593
 
                                $this->debug("value is neither an array nor an object for XML Schema type $ns:$uqType");
1594
 
                                $xvalue = array();
1595
 
                        }
1596
 
                        foreach ($typeDef['attrs'] as $aName => $attrs) {
1597
 
                                if (isset($xvalue['!' . $aName])) {
1598
 
                                        $xname = '!' . $aName;
1599
 
                                        $this->debug("value provided for attribute $aName with key $xname");
1600
 
                                } elseif (isset($xvalue[$aName])) {
1601
 
                                        $xname = $aName;
1602
 
                                        $this->debug("value provided for attribute $aName with key $xname");
1603
 
                                } elseif (isset($attrs['default'])) {
1604
 
                                        $xname = '!' . $aName;
1605
 
                                        $xvalue[$xname] = $attrs['default'];
1606
 
                                        $this->debug('use default value of ' . $xvalue[$aName] . ' for attribute ' . $aName);
1607
 
                                } else {
1608
 
                                        $xname = '';
1609
 
                                        $this->debug("no value provided for attribute $aName");
1610
 
                                }
1611
 
                                if ($xname) {
1612
 
                                        $xml .=  " $aName=\"" . $this->expandEntities($xvalue[$xname]) . "\"";
1613
 
                                }
1614
 
                        } 
1615
 
                } else {
1616
 
                        $this->debug("no attributes to serialize for XML Schema type $ns:$uqType");
1617
 
                }
1618
 
                if (isset($typeDef['extensionBase'])) {
1619
 
                        $ns = $this->getPrefix($typeDef['extensionBase']);
1620
 
                        $uqType = $this->getLocalPart($typeDef['extensionBase']);
1621
 
                        if ($this->getNamespaceFromPrefix($ns)) {
1622
 
                                $ns = $this->getNamespaceFromPrefix($ns);
1623
 
                        }
1624
 
                        if ($typeDef = $this->getTypeDef($uqType, $ns)) {
1625
 
                                $this->debug("serialize attributes for extension base $ns:$uqType");
1626
 
                                $xml .= $this->serializeComplexTypeAttributes($typeDef, $value, $ns, $uqType);
1627
 
                        } else {
1628
 
                                $this->debug("extension base $ns:$uqType is not a supported type");
1629
 
                        }
1630
 
                }
1631
 
                return $xml;
1632
 
        }
1633
 
 
1634
 
        /**
1635
 
         * serializes the elements for a complexType
1636
 
         *
1637
 
         * @param array $typeDef our internal representation of an XML schema type (or element)
1638
 
         * @param mixed $value a native PHP value (parameter value)
1639
 
         * @param string $ns the namespace of the type
1640
 
         * @param string $uqType the local part of the type
1641
 
         * @param string $use use for part (encoded|literal)
1642
 
         * @param string $encodingStyle SOAP encoding style for the value (if different than the enclosing style)
1643
 
         * @return string value serialized as an XML string
1644
 
         * @access private
1645
 
         */
1646
 
        function serializeComplexTypeElements($typeDef, $value, $ns, $uqType, $use='encoded', $encodingStyle=false) {
1647
 
                $xml = '';
1648
 
                if (isset($typeDef['elements']) && is_array($typeDef['elements'])) {
1649
 
                        $this->debug("in serializeComplexTypeElements, serialize elements for XML Schema type $ns:$uqType");
1650
 
                        if (is_array($value)) {
1651
 
                                $xvalue = $value;
1652
 
                        } elseif (is_object($value)) {
1653
 
                                $xvalue = get_object_vars($value);
1654
 
                        } else {
1655
 
                                $this->debug("value is neither an array nor an object for XML Schema type $ns:$uqType");
1656
 
                                $xvalue = array();
1657
 
                        }
1658
 
                        // toggle whether all elements are present - ideally should validate against schema
1659
 
                        if (count($typeDef['elements']) != count($xvalue)){
1660
 
                                $optionals = true;
1661
 
                        }
1662
 
                        foreach ($typeDef['elements'] as $eName => $attrs) {
1663
 
                                if (!isset($xvalue[$eName])) {
1664
 
                                        if (isset($attrs['default'])) {
1665
 
                                                $xvalue[$eName] = $attrs['default'];
1666
 
                                                $this->debug('use default value of ' . $xvalue[$eName] . ' for element ' . $eName);
1667
 
                                        }
1668
 
                                }
1669
 
                                // if user took advantage of a minOccurs=0, then only serialize named parameters
1670
 
                                if (isset($optionals)
1671
 
                                    && (!isset($xvalue[$eName])) 
1672
 
                                        && ( (!isset($attrs['nillable'])) || $attrs['nillable'] != 'true')
1673
 
                                        ){
1674
 
                                        if (isset($attrs['minOccurs']) && $attrs['minOccurs'] <> '0') {
1675
 
                                                $this->debug("apparent error: no value provided for element $eName with minOccurs=" . $attrs['minOccurs']);
1676
 
                                        }
1677
 
                                        // do nothing
1678
 
                                        $this->debug("no value provided for complexType element $eName and element is not nillable, so serialize nothing");
1679
 
                                } else {
1680
 
                                        // get value
1681
 
                                        if (isset($xvalue[$eName])) {
1682
 
                                            $v = $xvalue[$eName];
1683
 
                                        } else {
1684
 
                                            $v = null;
1685
 
                                        }
1686
 
                                        if (isset($attrs['form'])) {
1687
 
                                                $unqualified = ($attrs['form'] == 'unqualified');
1688
 
                                        } else {
1689
 
                                                $unqualified = false;
1690
 
                                        }
1691
 
                                        if (isset($attrs['maxOccurs']) && ($attrs['maxOccurs'] == 'unbounded' || $attrs['maxOccurs'] > 1) && isset($v) && is_array($v) && $this->isArraySimpleOrStruct($v) == 'arraySimple') {
1692
 
                                                $vv = $v;
1693
 
                                                foreach ($vv as $k => $v) {
1694
 
                                                        if (isset($attrs['type']) || isset($attrs['ref'])) {
1695
 
                                                                // serialize schema-defined type
1696
 
                                                            $xml .= $this->serializeType($eName, isset($attrs['type']) ? $attrs['type'] : $attrs['ref'], $v, $use, $encodingStyle, $unqualified);
1697
 
                                                        } else {
1698
 
                                                                // serialize generic type (can this ever really happen?)
1699
 
                                                            $this->debug("calling serialize_val() for $v, $eName, false, false, false, false, $use");
1700
 
                                                            $xml .= $this->serialize_val($v, $eName, false, false, false, false, $use);
1701
 
                                                        }
1702
 
                                                }
1703
 
                                        } else {
1704
 
                                                if (isset($attrs['type']) || isset($attrs['ref'])) {
1705
 
                                                        // serialize schema-defined type
1706
 
                                                    $xml .= $this->serializeType($eName, isset($attrs['type']) ? $attrs['type'] : $attrs['ref'], $v, $use, $encodingStyle, $unqualified);
1707
 
                                                } else {
1708
 
                                                        // serialize generic type (can this ever really happen?)
1709
 
                                                    $this->debug("calling serialize_val() for $v, $eName, false, false, false, false, $use");
1710
 
                                                    $xml .= $this->serialize_val($v, $eName, false, false, false, false, $use);
1711
 
                                                }
1712
 
                                        }
1713
 
                                }
1714
 
                        } 
1715
 
                } else {
1716
 
                        $this->debug("no elements to serialize for XML Schema type $ns:$uqType");
1717
 
                }
1718
 
                if (isset($typeDef['extensionBase'])) {
1719
 
                        $ns = $this->getPrefix($typeDef['extensionBase']);
1720
 
                        $uqType = $this->getLocalPart($typeDef['extensionBase']);
1721
 
                        if ($this->getNamespaceFromPrefix($ns)) {
1722
 
                                $ns = $this->getNamespaceFromPrefix($ns);
1723
 
                        }
1724
 
                        if ($typeDef = $this->getTypeDef($uqType, $ns)) {
1725
 
                                $this->debug("serialize elements for extension base $ns:$uqType");
1726
 
                                $xml .= $this->serializeComplexTypeElements($typeDef, $value, $ns, $uqType, $use, $encodingStyle);
1727
 
                        } else {
1728
 
                                $this->debug("extension base $ns:$uqType is not a supported type");
1729
 
                        }
1730
 
                }
1731
 
                return $xml;
1732
 
        }
1733
 
 
1734
 
        /**
1735
 
        * adds an XML Schema complex type to the WSDL types
1736
 
        *
1737
 
        * @param string $name
1738
 
        * @param string $typeClass (complexType|simpleType|attribute)
1739
 
        * @param string $phpType currently supported are array and struct (php assoc array)
1740
 
        * @param string $compositor (all|sequence|choice)
1741
 
        * @param string $restrictionBase namespace:name (http://schemas.xmlsoap.org/soap/encoding/:Array)
1742
 
        * @param array $elements e.g. array ( name => array(name=>'',type=>'') )
1743
 
        * @param array $attrs e.g. array(array('ref'=>'SOAP-ENC:arrayType','wsdl:arrayType'=>'xsd:string[]'))
1744
 
        * @param string $arrayType as namespace:name (xsd:string)
1745
 
        * @see nusoap_xmlschema
1746
 
        * @access public
1747
 
        */
1748
 
        function addComplexType($name,$typeClass='complexType',$phpType='array',$compositor='',$restrictionBase='',$elements=array(),$attrs=array(),$arrayType='') {
1749
 
                if (count($elements) > 0) {
1750
 
                        $eElements = array();
1751
 
                foreach($elements as $n => $e){
1752
 
                    // expand each element
1753
 
                    $ee = array();
1754
 
                    foreach ($e as $k => $v) {
1755
 
                            $k = strpos($k,':') ? $this->expandQname($k) : $k;
1756
 
                            $v = strpos($v,':') ? $this->expandQname($v) : $v;
1757
 
                            $ee[$k] = $v;
1758
 
                        }
1759
 
                        $eElements[$n] = $ee;
1760
 
                }
1761
 
                $elements = $eElements;
1762
 
                }
1763
 
                
1764
 
                if (count($attrs) > 0) {
1765
 
                foreach($attrs as $n => $a){
1766
 
                    // expand each attribute
1767
 
                    foreach ($a as $k => $v) {
1768
 
                            $k = strpos($k,':') ? $this->expandQname($k) : $k;
1769
 
                            $v = strpos($v,':') ? $this->expandQname($v) : $v;
1770
 
                            $aa[$k] = $v;
1771
 
                        }
1772
 
                        $eAttrs[$n] = $aa;
1773
 
                }
1774
 
                $attrs = $eAttrs;
1775
 
                }
1776
 
 
1777
 
                $restrictionBase = strpos($restrictionBase,':') ? $this->expandQname($restrictionBase) : $restrictionBase;
1778
 
                $arrayType = strpos($arrayType,':') ? $this->expandQname($arrayType) : $arrayType;
1779
 
 
1780
 
                $typens = isset($this->namespaces['types']) ? $this->namespaces['types'] : $this->namespaces['tns'];
1781
 
                $this->schemas[$typens][0]->addComplexType($name,$typeClass,$phpType,$compositor,$restrictionBase,$elements,$attrs,$arrayType);
1782
 
        }
1783
 
 
1784
 
        /**
1785
 
        * adds an XML Schema simple type to the WSDL types
1786
 
        *
1787
 
        * @param string $name
1788
 
        * @param string $restrictionBase namespace:name (http://schemas.xmlsoap.org/soap/encoding/:Array)
1789
 
        * @param string $typeClass (should always be simpleType)
1790
 
        * @param string $phpType (should always be scalar)
1791
 
        * @param array $enumeration array of values
1792
 
        * @see nusoap_xmlschema
1793
 
        * @access public
1794
 
        */
1795
 
        function addSimpleType($name, $restrictionBase='', $typeClass='simpleType', $phpType='scalar', $enumeration=array()) {
1796
 
                $restrictionBase = strpos($restrictionBase,':') ? $this->expandQname($restrictionBase) : $restrictionBase;
1797
 
 
1798
 
                $typens = isset($this->namespaces['types']) ? $this->namespaces['types'] : $this->namespaces['tns'];
1799
 
                $this->schemas[$typens][0]->addSimpleType($name, $restrictionBase, $typeClass, $phpType, $enumeration);
1800
 
        }
1801
 
 
1802
 
        /**
1803
 
        * adds an element to the WSDL types
1804
 
        *
1805
 
        * @param array $attrs attributes that must include name and type
1806
 
        * @see nusoap_xmlschema
1807
 
        * @access public
1808
 
        */
1809
 
        function addElement($attrs) {
1810
 
                $typens = isset($this->namespaces['types']) ? $this->namespaces['types'] : $this->namespaces['tns'];
1811
 
                $this->schemas[$typens][0]->addElement($attrs);
1812
 
        }
1813
 
 
1814
 
        /**
1815
 
        * register an operation with the server
1816
 
        * 
1817
 
        * @param string $name operation (method) name
1818
 
        * @param array $in assoc array of input values: key = param name, value = param type
1819
 
        * @param array $out assoc array of output values: key = param name, value = param type
1820
 
        * @param string $namespace optional The namespace for the operation
1821
 
        * @param string $soapaction optional The soapaction for the operation
1822
 
        * @param string $style (rpc|document) optional The style for the operation Note: when 'document' is specified, parameter and return wrappers are created for you automatically
1823
 
        * @param string $use (encoded|literal) optional The use for the parameters (cannot mix right now)
1824
 
        * @param string $documentation optional The description to include in the WSDL
1825
 
        * @param string $encodingStyle optional (usually 'http://schemas.xmlsoap.org/soap/encoding/' for encoded)
1826
 
        * @access public 
1827
 
        */
1828
 
        function addOperation($name, $in = false, $out = false, $namespace = false, $soapaction = false, $style = 'rpc', $use = 'encoded', $documentation = '', $encodingStyle = ''){
1829
 
                if ($use == 'encoded' && $encodingStyle == '') {
1830
 
                        $encodingStyle = 'http://schemas.xmlsoap.org/soap/encoding/';
1831
 
                }
1832
 
 
1833
 
                if ($style == 'document') {
1834
 
                        $elements = array();
1835
 
                        foreach ($in as $n => $t) {
1836
 
                                $elements[$n] = array('name' => $n, 'type' => $t);
1837
 
                        }
1838
 
                        $this->addComplexType($name . 'RequestType', 'complexType', 'struct', 'all', '', $elements);
1839
 
                        $this->addElement(array('name' => $name, 'type' => $name . 'RequestType'));
1840
 
                        $in = array('parameters' => 'tns:' . $name . '^');
1841
 
 
1842
 
                        $elements = array();
1843
 
                        foreach ($out as $n => $t) {
1844
 
                                $elements[$n] = array('name' => $n, 'type' => $t);
1845
 
                        }
1846
 
                        $this->addComplexType($name . 'ResponseType', 'complexType', 'struct', 'all', '', $elements);
1847
 
                        $this->addElement(array('name' => $name . 'Response', 'type' => $name . 'ResponseType', 'form' => 'qualified'));
1848
 
                        $out = array('parameters' => 'tns:' . $name . 'Response' . '^');
1849
 
                }
1850
 
 
1851
 
                // get binding
1852
 
                $this->bindings[ $this->serviceName . 'Binding' ]['operations'][$name] =
1853
 
                array(
1854
 
                'name' => $name,
1855
 
                'binding' => $this->serviceName . 'Binding',
1856
 
                'endpoint' => $this->endpoint,
1857
 
                'soapAction' => $soapaction,
1858
 
                'style' => $style,
1859
 
                'input' => array(
1860
 
                        'use' => $use,
1861
 
                        'namespace' => $namespace,
1862
 
                        'encodingStyle' => $encodingStyle,
1863
 
                        'message' => $name . 'Request',
1864
 
                        'parts' => $in),
1865
 
                'output' => array(
1866
 
                        'use' => $use,
1867
 
                        'namespace' => $namespace,
1868
 
                        'encodingStyle' => $encodingStyle,
1869
 
                        'message' => $name . 'Response',
1870
 
                        'parts' => $out),
1871
 
                'namespace' => $namespace,
1872
 
                'transport' => 'http://schemas.xmlsoap.org/soap/http',
1873
 
                'documentation' => $documentation); 
1874
 
                // add portTypes
1875
 
                // add messages
1876
 
                if($in)
1877
 
                {
1878
 
                        foreach($in as $pName => $pType)
1879
 
                        {
1880
 
                                if(strpos($pType,':')) {
1881
 
                                        $pType = $this->getNamespaceFromPrefix($this->getPrefix($pType)).":".$this->getLocalPart($pType);
1882
 
                                }
1883
 
                                $this->messages[$name.'Request'][$pName] = $pType;
1884
 
                        }
1885
 
                } else {
1886
 
            $this->messages[$name.'Request']= '0';
1887
 
        }
1888
 
                if($out)
1889
 
                {
1890
 
                        foreach($out as $pName => $pType)
1891
 
                        {
1892
 
                                if(strpos($pType,':')) {
1893
 
                                        $pType = $this->getNamespaceFromPrefix($this->getPrefix($pType)).":".$this->getLocalPart($pType);
1894
 
                                }
1895
 
                                $this->messages[$name.'Response'][$pName] = $pType;
1896
 
                        }
1897
 
                } else {
1898
 
            $this->messages[$name.'Response']= '0';
1899
 
        }
1900
 
                return true;
1901
 
        } 
1902
 
}
1903
 
 
 
1
<?php
 
2
 
 
3
 
 
4
 
 
5
 
 
6
/**
 
7
* parses a WSDL file, allows access to it's data, other utility methods.
 
8
* also builds WSDL structures programmatically.
 
9
 
10
* @author   Dietrich Ayala <dietrich@ganx4.com>
 
11
* @author   Scott Nichol <snichol@users.sourceforge.net>
 
12
* @version  $Id: class.wsdl.php,v 1.69 2007/11/06 15:17:46 snichol Exp $
 
13
* @access public 
 
14
*/
 
15
class wsdl extends nusoap_base {
 
16
        // URL or filename of the root of this WSDL
 
17
    var $wsdl; 
 
18
    // define internal arrays of bindings, ports, operations, messages, etc.
 
19
    var $schemas = array();
 
20
    var $currentSchema;
 
21
    var $message = array();
 
22
    var $complexTypes = array();
 
23
    var $messages = array();
 
24
    var $currentMessage;
 
25
    var $currentOperation;
 
26
    var $portTypes = array();
 
27
    var $currentPortType;
 
28
    var $bindings = array();
 
29
    var $currentBinding;
 
30
    var $ports = array();
 
31
    var $currentPort;
 
32
    var $opData = array();
 
33
    var $status = '';
 
34
    var $documentation = false;
 
35
    var $endpoint = ''; 
 
36
    // array of wsdl docs to import
 
37
    var $import = array(); 
 
38
    // parser vars
 
39
    var $parser;
 
40
    var $position = 0;
 
41
    var $depth = 0;
 
42
    var $depth_array = array();
 
43
        // for getting wsdl
 
44
        var $proxyhost = '';
 
45
    var $proxyport = '';
 
46
        var $proxyusername = '';
 
47
        var $proxypassword = '';
 
48
        var $timeout = 0;
 
49
        var $response_timeout = 30;
 
50
        var $curl_options = array();    // User-specified cURL options
 
51
        var $use_curl = false;                  // whether to always try to use cURL
 
52
        // for HTTP authentication
 
53
        var $username = '';                             // Username for HTTP authentication
 
54
        var $password = '';                             // Password for HTTP authentication
 
55
        var $authtype = '';                             // Type of HTTP authentication
 
56
        var $certRequest = array();             // Certificate for HTTP SSL authentication
 
57
 
 
58
    /**
 
59
     * constructor
 
60
     * 
 
61
     * @param string $wsdl WSDL document URL
 
62
         * @param string $proxyhost
 
63
         * @param string $proxyport
 
64
         * @param string $proxyusername
 
65
         * @param string $proxypassword
 
66
         * @param integer $timeout set the connection timeout
 
67
         * @param integer $response_timeout set the response timeout
 
68
         * @param array $curl_options user-specified cURL options
 
69
         * @param boolean $use_curl try to use cURL
 
70
     * @access public 
 
71
     */
 
72
    function wsdl($wsdl = '',$proxyhost=false,$proxyport=false,$proxyusername=false,$proxypassword=false,$timeout=0,$response_timeout=30,$curl_options=null,$use_curl=false){
 
73
                parent::nusoap_base();
 
74
                $this->debug("ctor wsdl=$wsdl timeout=$timeout response_timeout=$response_timeout");
 
75
        $this->proxyhost = $proxyhost;
 
76
        $this->proxyport = $proxyport;
 
77
                $this->proxyusername = $proxyusername;
 
78
                $this->proxypassword = $proxypassword;
 
79
                $this->timeout = $timeout;
 
80
                $this->response_timeout = $response_timeout;
 
81
                if (is_array($curl_options))
 
82
                        $this->curl_options = $curl_options;
 
83
                $this->use_curl = $use_curl;
 
84
                $this->fetchWSDL($wsdl);
 
85
    }
 
86
 
 
87
        /**
 
88
         * fetches the WSDL document and parses it
 
89
         *
 
90
         * @access public
 
91
         */
 
92
        function fetchWSDL($wsdl) {
 
93
                $this->debug("parse and process WSDL path=$wsdl");
 
94
                $this->wsdl = $wsdl;
 
95
        // parse wsdl file
 
96
        if ($this->wsdl != "") {
 
97
            $this->parseWSDL($this->wsdl);
 
98
        }
 
99
        // imports
 
100
        // TODO: handle imports more properly, grabbing them in-line and nesting them
 
101
        $imported_urls = array();
 
102
        $imported = 1;
 
103
        while ($imported > 0) {
 
104
                $imported = 0;
 
105
                // Schema imports
 
106
                foreach ($this->schemas as $ns => $list) {
 
107
                        foreach ($list as $xs) {
 
108
                                        $wsdlparts = parse_url($this->wsdl);    // this is bogusly simple!
 
109
                            foreach ($xs->imports as $ns2 => $list2) {
 
110
                                for ($ii = 0; $ii < count($list2); $ii++) {
 
111
                                        if (! $list2[$ii]['loaded']) {
 
112
                                                $this->schemas[$ns]->imports[$ns2][$ii]['loaded'] = true;
 
113
                                                $url = $list2[$ii]['location'];
 
114
                                                                if ($url != '') {
 
115
                                                                        $urlparts = parse_url($url);
 
116
                                                                        if (!isset($urlparts['host'])) {
 
117
                                                                                $url = $wsdlparts['scheme'] . '://' . $wsdlparts['host'] . (isset($wsdlparts['port']) ? ':' .$wsdlparts['port'] : '') .
 
118
                                                                                                substr($wsdlparts['path'],0,strrpos($wsdlparts['path'],'/') + 1) .$urlparts['path'];
 
119
                                                                        }
 
120
                                                                        if (! in_array($url, $imported_urls)) {
 
121
                                                                $this->parseWSDL($url);
 
122
                                                                $imported++;
 
123
                                                                $imported_urls[] = $url;
 
124
                                                        }
 
125
                                                                } else {
 
126
                                                                        $this->debug("Unexpected scenario: empty URL for unloaded import");
 
127
                                                                }
 
128
                                                        }
 
129
                                                }
 
130
                            } 
 
131
                        }
 
132
                }
 
133
                // WSDL imports
 
134
                        $wsdlparts = parse_url($this->wsdl);    // this is bogusly simple!
 
135
            foreach ($this->import as $ns => $list) {
 
136
                for ($ii = 0; $ii < count($list); $ii++) {
 
137
                        if (! $list[$ii]['loaded']) {
 
138
                                $this->import[$ns][$ii]['loaded'] = true;
 
139
                                $url = $list[$ii]['location'];
 
140
                                                if ($url != '') {
 
141
                                                        $urlparts = parse_url($url);
 
142
                                                        if (!isset($urlparts['host'])) {
 
143
                                                                $url = $wsdlparts['scheme'] . '://' . $wsdlparts['host'] . (isset($wsdlparts['port']) ? ':' . $wsdlparts['port'] : '') .
 
144
                                                                                substr($wsdlparts['path'],0,strrpos($wsdlparts['path'],'/') + 1) .$urlparts['path'];
 
145
                                                        }
 
146
                                                        if (! in_array($url, $imported_urls)) {
 
147
                                                $this->parseWSDL($url);
 
148
                                                $imported++;
 
149
                                                $imported_urls[] = $url;
 
150
                                        }
 
151
                                                } else {
 
152
                                                        $this->debug("Unexpected scenario: empty URL for unloaded import");
 
153
                                                }
 
154
                                        }
 
155
                                }
 
156
            } 
 
157
                }
 
158
        // add new data to operation data
 
159
        foreach($this->bindings as $binding => $bindingData) {
 
160
            if (isset($bindingData['operations']) && is_array($bindingData['operations'])) {
 
161
                foreach($bindingData['operations'] as $operation => $data) {
 
162
                    $this->debug('post-parse data gathering for ' . $operation);
 
163
                    $this->bindings[$binding]['operations'][$operation]['input'] = 
 
164
                                                isset($this->bindings[$binding]['operations'][$operation]['input']) ? 
 
165
                                                array_merge($this->bindings[$binding]['operations'][$operation]['input'], $this->portTypes[ $bindingData['portType'] ][$operation]['input']) :
 
166
                                                $this->portTypes[ $bindingData['portType'] ][$operation]['input'];
 
167
                    $this->bindings[$binding]['operations'][$operation]['output'] = 
 
168
                                                isset($this->bindings[$binding]['operations'][$operation]['output']) ?
 
169
                                                array_merge($this->bindings[$binding]['operations'][$operation]['output'], $this->portTypes[ $bindingData['portType'] ][$operation]['output']) :
 
170
                                                $this->portTypes[ $bindingData['portType'] ][$operation]['output'];
 
171
                    if(isset($this->messages[ $this->bindings[$binding]['operations'][$operation]['input']['message'] ])){
 
172
                                                $this->bindings[$binding]['operations'][$operation]['input']['parts'] = $this->messages[ $this->bindings[$binding]['operations'][$operation]['input']['message'] ];
 
173
                                        }
 
174
                                        if(isset($this->messages[ $this->bindings[$binding]['operations'][$operation]['output']['message'] ])){
 
175
                                $this->bindings[$binding]['operations'][$operation]['output']['parts'] = $this->messages[ $this->bindings[$binding]['operations'][$operation]['output']['message'] ];
 
176
                    }
 
177
                    // Set operation style if necessary, but do not override one already provided
 
178
                                        if (isset($bindingData['style']) && !isset($this->bindings[$binding]['operations'][$operation]['style'])) {
 
179
                        $this->bindings[$binding]['operations'][$operation]['style'] = $bindingData['style'];
 
180
                    }
 
181
                    $this->bindings[$binding]['operations'][$operation]['transport'] = isset($bindingData['transport']) ? $bindingData['transport'] : '';
 
182
                    $this->bindings[$binding]['operations'][$operation]['documentation'] = isset($this->portTypes[ $bindingData['portType'] ][$operation]['documentation']) ? $this->portTypes[ $bindingData['portType'] ][$operation]['documentation'] : '';
 
183
                    $this->bindings[$binding]['operations'][$operation]['endpoint'] = isset($bindingData['endpoint']) ? $bindingData['endpoint'] : '';
 
184
                } 
 
185
            } 
 
186
        }
 
187
        }
 
188
 
 
189
    /**
 
190
     * parses the wsdl document
 
191
     * 
 
192
     * @param string $wsdl path or URL
 
193
     * @access private 
 
194
     */
 
195
    function parseWSDL($wsdl = '') {
 
196
                $this->debug("parse WSDL at path=$wsdl");
 
197
 
 
198
        if ($wsdl == '') {
 
199
            $this->debug('no wsdl passed to parseWSDL()!!');
 
200
            $this->setError('no wsdl passed to parseWSDL()!!');
 
201
            return false;
 
202
        }
 
203
        
 
204
        // parse $wsdl for url format
 
205
        $wsdl_props = parse_url($wsdl);
 
206
 
 
207
        if (isset($wsdl_props['scheme']) && ($wsdl_props['scheme'] == 'http' || $wsdl_props['scheme'] == 'https')) {
 
208
            $this->debug('getting WSDL http(s) URL ' . $wsdl);
 
209
                // get wsdl
 
210
                $tr = new soap_transport_http($wsdl, $this->curl_options, $this->use_curl);
 
211
                        $tr->request_method = 'GET';
 
212
                        $tr->useSOAPAction = false;
 
213
                        if($this->proxyhost && $this->proxyport){
 
214
                                $tr->setProxy($this->proxyhost,$this->proxyport,$this->proxyusername,$this->proxypassword);
 
215
                        }
 
216
                        if ($this->authtype != '') {
 
217
                                $tr->setCredentials($this->username, $this->password, $this->authtype, array(), $this->certRequest);
 
218
                        }
 
219
                        $tr->setEncoding('gzip, deflate');
 
220
                        $wsdl_string = $tr->send('', $this->timeout, $this->response_timeout);
 
221
                        //$this->debug("WSDL request\n" . $tr->outgoing_payload);
 
222
                        //$this->debug("WSDL response\n" . $tr->incoming_payload);
 
223
                        $this->appendDebug($tr->getDebug());
 
224
                        // catch errors
 
225
                        if($err = $tr->getError() ){
 
226
                                $errstr = 'HTTP ERROR: '.$err;
 
227
                                $this->debug($errstr);
 
228
                    $this->setError($errstr);
 
229
                                unset($tr);
 
230
                    return false;
 
231
                        }
 
232
                        unset($tr);
 
233
                        $this->debug("got WSDL URL");
 
234
        } else {
 
235
            // $wsdl is not http(s), so treat it as a file URL or plain file path
 
236
                if (isset($wsdl_props['scheme']) && ($wsdl_props['scheme'] == 'file') && isset($wsdl_props['path'])) {
 
237
                        $path = isset($wsdl_props['host']) ? ($wsdl_props['host'] . ':' . $wsdl_props['path']) : $wsdl_props['path'];
 
238
                } else {
 
239
                        $path = $wsdl;
 
240
                }
 
241
            $this->debug('getting WSDL file ' . $path);
 
242
            if ($fp = @fopen($path, 'r')) {
 
243
                $wsdl_string = '';
 
244
                while ($data = fread($fp, 32768)) {
 
245
                    $wsdl_string .= $data;
 
246
                } 
 
247
                fclose($fp);
 
248
            } else {
 
249
                $errstr = "Bad path to WSDL file $path";
 
250
                $this->debug($errstr);
 
251
                $this->setError($errstr);
 
252
                return false;
 
253
            } 
 
254
        }
 
255
        $this->debug('Parse WSDL');
 
256
        // end new code added
 
257
        // Create an XML parser.
 
258
        $this->parser = xml_parser_create(); 
 
259
        // Set the options for parsing the XML data.
 
260
        // xml_parser_set_option($parser, XML_OPTION_SKIP_WHITE, 1);
 
261
        xml_parser_set_option($this->parser, XML_OPTION_CASE_FOLDING, 0); 
 
262
        // Set the object for the parser.
 
263
        xml_set_object($this->parser, $this); 
 
264
        // Set the element handlers for the parser.
 
265
        xml_set_element_handler($this->parser, 'start_element', 'end_element');
 
266
        xml_set_character_data_handler($this->parser, 'character_data');
 
267
        // Parse the XML file.
 
268
        if (!xml_parse($this->parser, $wsdl_string, true)) {
 
269
            // Display an error message.
 
270
            $errstr = sprintf(
 
271
                                'XML error parsing WSDL from %s on line %d: %s',
 
272
                                $wsdl,
 
273
                xml_get_current_line_number($this->parser),
 
274
                xml_error_string(xml_get_error_code($this->parser))
 
275
                );
 
276
            $this->debug($errstr);
 
277
                        $this->debug("XML payload:\n" . $wsdl_string);
 
278
            $this->setError($errstr);
 
279
            return false;
 
280
        } 
 
281
                // free the parser
 
282
        xml_parser_free($this->parser);
 
283
        $this->debug('Parsing WSDL done');
 
284
                // catch wsdl parse errors
 
285
                if($this->getError()){
 
286
                        return false;
 
287
                }
 
288
        return true;
 
289
    } 
 
290
 
 
291
    /**
 
292
     * start-element handler
 
293
     * 
 
294
     * @param string $parser XML parser object
 
295
     * @param string $name element name
 
296
     * @param string $attrs associative array of attributes
 
297
     * @access private 
 
298
     */
 
299
    function start_element($parser, $name, $attrs)
 
300
    {
 
301
        if ($this->status == 'schema') {
 
302
            $this->currentSchema->schemaStartElement($parser, $name, $attrs);
 
303
            $this->appendDebug($this->currentSchema->getDebug());
 
304
            $this->currentSchema->clearDebug();
 
305
        } elseif (ereg('schema$', $name)) {
 
306
                $this->debug('Parsing WSDL schema');
 
307
            // $this->debug("startElement for $name ($attrs[name]). status = $this->status (".$this->getLocalPart($name).")");
 
308
            $this->status = 'schema';
 
309
            $this->currentSchema = new nusoap_xmlschema('', '', $this->namespaces);
 
310
            $this->currentSchema->schemaStartElement($parser, $name, $attrs);
 
311
            $this->appendDebug($this->currentSchema->getDebug());
 
312
            $this->currentSchema->clearDebug();
 
313
        } else {
 
314
            // position in the total number of elements, starting from 0
 
315
            $pos = $this->position++;
 
316
            $depth = $this->depth++; 
 
317
            // set self as current value for this depth
 
318
            $this->depth_array[$depth] = $pos;
 
319
            $this->message[$pos] = array('cdata' => ''); 
 
320
            // process attributes
 
321
            if (count($attrs) > 0) {
 
322
                                // register namespace declarations
 
323
                foreach($attrs as $k => $v) {
 
324
                    if (ereg("^xmlns", $k)) {
 
325
                        if ($ns_prefix = substr(strrchr($k, ':'), 1)) {
 
326
                            $this->namespaces[$ns_prefix] = $v;
 
327
                        } else {
 
328
                            $this->namespaces['ns' . (count($this->namespaces) + 1)] = $v;
 
329
                        } 
 
330
                        if ($v == 'http://www.w3.org/2001/XMLSchema' || $v == 'http://www.w3.org/1999/XMLSchema' || $v == 'http://www.w3.org/2000/10/XMLSchema') {
 
331
                            $this->XMLSchemaVersion = $v;
 
332
                            $this->namespaces['xsi'] = $v . '-instance';
 
333
                        } 
 
334
                    }
 
335
                }
 
336
                // expand each attribute prefix to its namespace
 
337
                foreach($attrs as $k => $v) {
 
338
                    $k = strpos($k, ':') ? $this->expandQname($k) : $k;
 
339
                    if ($k != 'location' && $k != 'soapAction' && $k != 'namespace') {
 
340
                        $v = strpos($v, ':') ? $this->expandQname($v) : $v;
 
341
                    } 
 
342
                    $eAttrs[$k] = $v;
 
343
                } 
 
344
                $attrs = $eAttrs;
 
345
            } else {
 
346
                $attrs = array();
 
347
            } 
 
348
            // get element prefix, namespace and name
 
349
            if (ereg(':', $name)) {
 
350
                // get ns prefix
 
351
                $prefix = substr($name, 0, strpos($name, ':')); 
 
352
                // get ns
 
353
                $namespace = isset($this->namespaces[$prefix]) ? $this->namespaces[$prefix] : ''; 
 
354
                // get unqualified name
 
355
                $name = substr(strstr($name, ':'), 1);
 
356
            } 
 
357
                        // process attributes, expanding any prefixes to namespaces
 
358
            // find status, register data
 
359
            switch ($this->status) {
 
360
                case 'message':
 
361
                    if ($name == 'part') {
 
362
                                    if (isset($attrs['type'])) {
 
363
                                    $this->debug("msg " . $this->currentMessage . ": found part (with type) $attrs[name]: " . implode(',', $attrs));
 
364
                                    $this->messages[$this->currentMessage][$attrs['name']] = $attrs['type'];
 
365
                                } 
 
366
                                    if (isset($attrs['element'])) {
 
367
                                    $this->debug("msg " . $this->currentMessage . ": found part (with element) $attrs[name]: " . implode(',', $attrs));
 
368
                                        $this->messages[$this->currentMessage][$attrs['name']] = $attrs['element'] . '^';
 
369
                                    } 
 
370
                                } 
 
371
                                break;
 
372
                            case 'portType':
 
373
                                switch ($name) {
 
374
                                    case 'operation':
 
375
                                        $this->currentPortOperation = $attrs['name'];
 
376
                                        $this->debug("portType $this->currentPortType operation: $this->currentPortOperation");
 
377
                                        if (isset($attrs['parameterOrder'])) {
 
378
                                                $this->portTypes[$this->currentPortType][$attrs['name']]['parameterOrder'] = $attrs['parameterOrder'];
 
379
                                                } 
 
380
                                                break;
 
381
                                            case 'documentation':
 
382
                                                $this->documentation = true;
 
383
                                                break; 
 
384
                                            // merge input/output data
 
385
                                            default:
 
386
                                                $m = isset($attrs['message']) ? $this->getLocalPart($attrs['message']) : '';
 
387
                                                $this->portTypes[$this->currentPortType][$this->currentPortOperation][$name]['message'] = $m;
 
388
                                                break;
 
389
                                        } 
 
390
                                break;
 
391
                                case 'binding':
 
392
                                    switch ($name) {
 
393
                                        case 'binding': 
 
394
                                            // get ns prefix
 
395
                                            if (isset($attrs['style'])) {
 
396
                                            $this->bindings[$this->currentBinding]['prefix'] = $prefix;
 
397
                                                } 
 
398
                                                $this->bindings[$this->currentBinding] = array_merge($this->bindings[$this->currentBinding], $attrs);
 
399
                                                break;
 
400
                                                case 'header':
 
401
                                                    $this->bindings[$this->currentBinding]['operations'][$this->currentOperation][$this->opStatus]['headers'][] = $attrs;
 
402
                                                    break;
 
403
                                                case 'operation':
 
404
                                                    if (isset($attrs['soapAction'])) {
 
405
                                                        $this->bindings[$this->currentBinding]['operations'][$this->currentOperation]['soapAction'] = $attrs['soapAction'];
 
406
                                                    } 
 
407
                                                    if (isset($attrs['style'])) {
 
408
                                                        $this->bindings[$this->currentBinding]['operations'][$this->currentOperation]['style'] = $attrs['style'];
 
409
                                                    } 
 
410
                                                    if (isset($attrs['name'])) {
 
411
                                                        $this->currentOperation = $attrs['name'];
 
412
                                                        $this->debug("current binding operation: $this->currentOperation");
 
413
                                                        $this->bindings[$this->currentBinding]['operations'][$this->currentOperation]['name'] = $attrs['name'];
 
414
                                                        $this->bindings[$this->currentBinding]['operations'][$this->currentOperation]['binding'] = $this->currentBinding;
 
415
                                                        $this->bindings[$this->currentBinding]['operations'][$this->currentOperation]['endpoint'] = isset($this->bindings[$this->currentBinding]['endpoint']) ? $this->bindings[$this->currentBinding]['endpoint'] : '';
 
416
                                                    } 
 
417
                                                    break;
 
418
                                                case 'input':
 
419
                                                    $this->opStatus = 'input';
 
420
                                                    break;
 
421
                                                case 'output':
 
422
                                                    $this->opStatus = 'output';
 
423
                                                    break;
 
424
                                                case 'body':
 
425
                                                    if (isset($this->bindings[$this->currentBinding]['operations'][$this->currentOperation][$this->opStatus])) {
 
426
                                                        $this->bindings[$this->currentBinding]['operations'][$this->currentOperation][$this->opStatus] = array_merge($this->bindings[$this->currentBinding]['operations'][$this->currentOperation][$this->opStatus], $attrs);
 
427
                                                    } else {
 
428
                                                        $this->bindings[$this->currentBinding]['operations'][$this->currentOperation][$this->opStatus] = $attrs;
 
429
                                                    } 
 
430
                                                    break;
 
431
                                        } 
 
432
                                        break;
 
433
                                case 'service':
 
434
                                        switch ($name) {
 
435
                                            case 'port':
 
436
                                                $this->currentPort = $attrs['name'];
 
437
                                                $this->debug('current port: ' . $this->currentPort);
 
438
                                                $this->ports[$this->currentPort]['binding'] = $this->getLocalPart($attrs['binding']);
 
439
                                        
 
440
                                                break;
 
441
                                            case 'address':
 
442
                                                $this->ports[$this->currentPort]['location'] = $attrs['location'];
 
443
                                                $this->ports[$this->currentPort]['bindingType'] = $namespace;
 
444
                                                $this->bindings[ $this->ports[$this->currentPort]['binding'] ]['bindingType'] = $namespace;
 
445
                                                $this->bindings[ $this->ports[$this->currentPort]['binding'] ]['endpoint'] = $attrs['location'];
 
446
                                                break;
 
447
                                        } 
 
448
                                        break;
 
449
                        } 
 
450
                // set status
 
451
                switch ($name) {
 
452
                        case 'import':
 
453
                            if (isset($attrs['location'])) {
 
454
                    $this->import[$attrs['namespace']][] = array('location' => $attrs['location'], 'loaded' => false);
 
455
                    $this->debug('parsing import ' . $attrs['namespace']. ' - ' . $attrs['location'] . ' (' . count($this->import[$attrs['namespace']]).')');
 
456
                                } else {
 
457
                    $this->import[$attrs['namespace']][] = array('location' => '', 'loaded' => true);
 
458
                                        if (! $this->getPrefixFromNamespace($attrs['namespace'])) {
 
459
                                                $this->namespaces['ns'.(count($this->namespaces)+1)] = $attrs['namespace'];
 
460
                                        }
 
461
                    $this->debug('parsing import ' . $attrs['namespace']. ' - [no location] (' . count($this->import[$attrs['namespace']]).')');
 
462
                                }
 
463
                                break;
 
464
                        //wait for schema
 
465
                        //case 'types':
 
466
                        //      $this->status = 'schema';
 
467
                        //      break;
 
468
                        case 'message':
 
469
                                $this->status = 'message';
 
470
                                $this->messages[$attrs['name']] = array();
 
471
                                $this->currentMessage = $attrs['name'];
 
472
                                break;
 
473
                        case 'portType':
 
474
                                $this->status = 'portType';
 
475
                                $this->portTypes[$attrs['name']] = array();
 
476
                                $this->currentPortType = $attrs['name'];
 
477
                                break;
 
478
                        case "binding":
 
479
                                if (isset($attrs['name'])) {
 
480
                                // get binding name
 
481
                                        if (strpos($attrs['name'], ':')) {
 
482
                                        $this->currentBinding = $this->getLocalPart($attrs['name']);
 
483
                                        } else {
 
484
                                        $this->currentBinding = $attrs['name'];
 
485
                                        } 
 
486
                                        $this->status = 'binding';
 
487
                                        $this->bindings[$this->currentBinding]['portType'] = $this->getLocalPart($attrs['type']);
 
488
                                        $this->debug("current binding: $this->currentBinding of portType: " . $attrs['type']);
 
489
                                } 
 
490
                                break;
 
491
                        case 'service':
 
492
                                $this->serviceName = $attrs['name'];
 
493
                                $this->status = 'service';
 
494
                                $this->debug('current service: ' . $this->serviceName);
 
495
                                break;
 
496
                        case 'definitions':
 
497
                                foreach ($attrs as $name => $value) {
 
498
                                        $this->wsdl_info[$name] = $value;
 
499
                                } 
 
500
                                break;
 
501
                        } 
 
502
                } 
 
503
        } 
 
504
 
 
505
        /**
 
506
        * end-element handler
 
507
        * 
 
508
        * @param string $parser XML parser object
 
509
        * @param string $name element name
 
510
        * @access private 
 
511
        */
 
512
        function end_element($parser, $name){ 
 
513
                // unset schema status
 
514
                if (/*ereg('types$', $name) ||*/ ereg('schema$', $name)) {
 
515
                        $this->status = "";
 
516
            $this->appendDebug($this->currentSchema->getDebug());
 
517
            $this->currentSchema->clearDebug();
 
518
                        $this->schemas[$this->currentSchema->schemaTargetNamespace][] = $this->currentSchema;
 
519
                $this->debug('Parsing WSDL schema done');
 
520
                } 
 
521
                if ($this->status == 'schema') {
 
522
                        $this->currentSchema->schemaEndElement($parser, $name);
 
523
                } else {
 
524
                        // bring depth down a notch
 
525
                        $this->depth--;
 
526
                } 
 
527
                // end documentation
 
528
                if ($this->documentation) {
 
529
                        //TODO: track the node to which documentation should be assigned; it can be a part, message, etc.
 
530
                        //$this->portTypes[$this->currentPortType][$this->currentPortOperation]['documentation'] = $this->documentation;
 
531
                        $this->documentation = false;
 
532
                } 
 
533
        } 
 
534
 
 
535
        /**
 
536
         * element content handler
 
537
         * 
 
538
         * @param string $parser XML parser object
 
539
         * @param string $data element content
 
540
         * @access private 
 
541
         */
 
542
        function character_data($parser, $data)
 
543
        {
 
544
                $pos = isset($this->depth_array[$this->depth]) ? $this->depth_array[$this->depth] : 0;
 
545
                if (isset($this->message[$pos]['cdata'])) {
 
546
                        $this->message[$pos]['cdata'] .= $data;
 
547
                } 
 
548
                if ($this->documentation) {
 
549
                        $this->documentation .= $data;
 
550
                } 
 
551
        } 
 
552
        
 
553
        /**
 
554
        * if authenticating, set user credentials here
 
555
        *
 
556
        * @param    string $username
 
557
        * @param    string $password
 
558
        * @param        string $authtype (basic|digest|certificate|ntlm)
 
559
        * @param        array $certRequest (keys must be cainfofile (optional), sslcertfile, sslkeyfile, passphrase, certpassword (optional), verifypeer (optional), verifyhost (optional): see corresponding options in cURL docs)
 
560
        * @access   public
 
561
        */
 
562
        function setCredentials($username, $password, $authtype = 'basic', $certRequest = array()) {
 
563
                $this->debug("setCredentials username=$username authtype=$authtype certRequest=");
 
564
                $this->appendDebug($this->varDump($certRequest));
 
565
                $this->username = $username;
 
566
                $this->password = $password;
 
567
                $this->authtype = $authtype;
 
568
                $this->certRequest = $certRequest;
 
569
        }
 
570
        
 
571
        function getBindingData($binding)
 
572
        {
 
573
                if (is_array($this->bindings[$binding])) {
 
574
                        return $this->bindings[$binding];
 
575
                } 
 
576
        }
 
577
        
 
578
        /**
 
579
         * returns an assoc array of operation names => operation data
 
580
         * 
 
581
         * @param string $bindingType eg: soap, smtp, dime (only soap and soap12 are currently supported)
 
582
         * @return array 
 
583
         * @access public 
 
584
         */
 
585
        function getOperations($bindingType = 'soap') {
 
586
                $ops = array();
 
587
                if ($bindingType == 'soap') {
 
588
                        $bindingType = 'http://schemas.xmlsoap.org/wsdl/soap/';
 
589
                } elseif ($bindingType == 'soap12') {
 
590
                        $bindingType = 'http://schemas.xmlsoap.org/wsdl/soap12/';
 
591
                }
 
592
                // loop thru ports
 
593
                foreach($this->ports as $port => $portData) {
 
594
                        // binding type of port matches parameter
 
595
                        if ($portData['bindingType'] == $bindingType) {
 
596
                                //$this->debug("getOperations for port $port");
 
597
                                //$this->debug("port data: " . $this->varDump($portData));
 
598
                                //$this->debug("bindings: " . $this->varDump($this->bindings[ $portData['binding'] ]));
 
599
                                // merge bindings
 
600
                                if (isset($this->bindings[ $portData['binding'] ]['operations'])) {
 
601
                                        $ops = array_merge ($ops, $this->bindings[ $portData['binding'] ]['operations']);
 
602
                                }
 
603
                        }
 
604
                } 
 
605
                return $ops;
 
606
        } 
 
607
        
 
608
        /**
 
609
         * returns an associative array of data necessary for calling an operation
 
610
         * 
 
611
         * @param string $operation name of operation
 
612
         * @param string $bindingType type of binding eg: soap, soap12
 
613
         * @return array 
 
614
         * @access public 
 
615
         */
 
616
        function getOperationData($operation, $bindingType = 'soap')
 
617
        {
 
618
                if ($bindingType == 'soap') {
 
619
                        $bindingType = 'http://schemas.xmlsoap.org/wsdl/soap/';
 
620
                } elseif ($bindingType == 'soap12') {
 
621
                        $bindingType = 'http://schemas.xmlsoap.org/wsdl/soap12/';
 
622
                }
 
623
                // loop thru ports
 
624
                foreach($this->ports as $port => $portData) {
 
625
                        // binding type of port matches parameter
 
626
                        if ($portData['bindingType'] == $bindingType) {
 
627
                                // get binding
 
628
                                //foreach($this->bindings[ $portData['binding'] ]['operations'] as $bOperation => $opData) {
 
629
                                foreach(array_keys($this->bindings[ $portData['binding'] ]['operations']) as $bOperation) {
 
630
                                        // note that we could/should also check the namespace here
 
631
                                        if ($operation == $bOperation) {
 
632
                                                $opData = $this->bindings[ $portData['binding'] ]['operations'][$operation];
 
633
                                            return $opData;
 
634
                                        } 
 
635
                                } 
 
636
                        }
 
637
                } 
 
638
        }
 
639
        
 
640
        /**
 
641
         * returns an associative array of data necessary for calling an operation
 
642
         * 
 
643
         * @param string $soapAction soapAction for operation
 
644
         * @param string $bindingType type of binding eg: soap, soap12
 
645
         * @return array 
 
646
         * @access public 
 
647
         */
 
648
        function getOperationDataForSoapAction($soapAction, $bindingType = 'soap') {
 
649
                if ($bindingType == 'soap') {
 
650
                        $bindingType = 'http://schemas.xmlsoap.org/wsdl/soap/';
 
651
                } elseif ($bindingType == 'soap12') {
 
652
                        $bindingType = 'http://schemas.xmlsoap.org/wsdl/soap12/';
 
653
                }
 
654
                // loop thru ports
 
655
                foreach($this->ports as $port => $portData) {
 
656
                        // binding type of port matches parameter
 
657
                        if ($portData['bindingType'] == $bindingType) {
 
658
                                // loop through operations for the binding
 
659
                                foreach ($this->bindings[ $portData['binding'] ]['operations'] as $bOperation => $opData) {
 
660
                                        if ($opData['soapAction'] == $soapAction) {
 
661
                                            return $opData;
 
662
                                        } 
 
663
                                } 
 
664
                        }
 
665
                } 
 
666
        }
 
667
        
 
668
        /**
 
669
    * returns an array of information about a given type
 
670
    * returns false if no type exists by the given name
 
671
    *
 
672
        *        typeDef = array(
 
673
        *        'elements' => array(), // refs to elements array
 
674
        *       'restrictionBase' => '',
 
675
        *       'phpType' => '',
 
676
        *       'order' => '(sequence|all)',
 
677
        *       'attrs' => array() // refs to attributes array
 
678
        *       )
 
679
    *
 
680
    * @param string $type the type
 
681
    * @param string $ns namespace (not prefix) of the type
 
682
    * @return mixed
 
683
    * @access public
 
684
    * @see nusoap_xmlschema
 
685
    */
 
686
        function getTypeDef($type, $ns) {
 
687
                $this->debug("in getTypeDef: type=$type, ns=$ns");
 
688
                if ((! $ns) && isset($this->namespaces['tns'])) {
 
689
                        $ns = $this->namespaces['tns'];
 
690
                        $this->debug("in getTypeDef: type namespace forced to $ns");
 
691
                }
 
692
                if (!isset($this->schemas[$ns])) {
 
693
                        foreach ($this->schemas as $ns0 => $schema0) {
 
694
                                if (strcasecmp($ns, $ns0) == 0) {
 
695
                                        $this->debug("in getTypeDef: replacing schema namespace $ns with $ns0");
 
696
                                        $ns = $ns0;
 
697
                                        break;
 
698
                                }
 
699
                        }
 
700
                }
 
701
                if (isset($this->schemas[$ns])) {
 
702
                        $this->debug("in getTypeDef: have schema for namespace $ns");
 
703
                        for ($i = 0; $i < count($this->schemas[$ns]); $i++) {
 
704
                                $xs = &$this->schemas[$ns][$i];
 
705
                                $t = $xs->getTypeDef($type);
 
706
                                //$this->appendDebug($xs->getDebug());
 
707
                                //$xs->clearDebug();
 
708
                                if ($t) {
 
709
                                        if (!isset($t['phpType'])) {
 
710
                                                // get info for type to tack onto the element
 
711
                                                $uqType = substr($t['type'], strrpos($t['type'], ':') + 1);
 
712
                                                $ns = substr($t['type'], 0, strrpos($t['type'], ':'));
 
713
                                                $etype = $this->getTypeDef($uqType, $ns);
 
714
                                                if ($etype) {
 
715
                                                        $this->debug("found type for [element] $type:");
 
716
                                                        $this->debug($this->varDump($etype));
 
717
                                                        if (isset($etype['phpType'])) {
 
718
                                                                $t['phpType'] = $etype['phpType'];
 
719
                                                        }
 
720
                                                        if (isset($etype['elements'])) {
 
721
                                                                $t['elements'] = $etype['elements'];
 
722
                                                        }
 
723
                                                        if (isset($etype['attrs'])) {
 
724
                                                                $t['attrs'] = $etype['attrs'];
 
725
                                                        }
 
726
                                                }
 
727
                                        }
 
728
                                        return $t;
 
729
                                }
 
730
                        }
 
731
                } else {
 
732
                        $this->debug("in getTypeDef: do not have schema for namespace $ns");
 
733
                }
 
734
                return false;
 
735
        }
 
736
 
 
737
    /**
 
738
    * prints html description of services
 
739
    *
 
740
    * @access private
 
741
    */
 
742
    function webDescription(){
 
743
        global $HTTP_SERVER_VARS;
 
744
 
 
745
                if (isset($_SERVER)) {
 
746
                        $PHP_SELF = $_SERVER['PHP_SELF'];
 
747
                } elseif (isset($HTTP_SERVER_VARS)) {
 
748
                        $PHP_SELF = $HTTP_SERVER_VARS['PHP_SELF'];
 
749
                } else {
 
750
                        $this->setError("Neither _SERVER nor HTTP_SERVER_VARS is available");
 
751
                }
 
752
 
 
753
                $b = '
 
754
                <html><head><title>NuSOAP: '.$this->serviceName.'</title>
 
755
                <style type="text/css">
 
756
                    body    { font-family: arial; color: #000000; background-color: #ffffff; margin: 0px 0px 0px 0px; }
 
757
                    p       { font-family: arial; color: #000000; margin-top: 0px; margin-bottom: 12px; }
 
758
                    pre { background-color: silver; padding: 5px; font-family: Courier New; font-size: x-small; color: #000000;}
 
759
                    ul      { margin-top: 10px; margin-left: 20px; }
 
760
                    li      { list-style-type: none; margin-top: 10px; color: #000000; }
 
761
                    .content{
 
762
                        margin-left: 0px; padding-bottom: 2em; }
 
763
                    .nav {
 
764
                        padding-top: 10px; padding-bottom: 10px; padding-left: 15px; font-size: .70em;
 
765
                        margin-top: 10px; margin-left: 0px; color: #000000;
 
766
                        background-color: #ccccff; width: 20%; margin-left: 20px; margin-top: 20px; }
 
767
                    .title {
 
768
                        font-family: arial; font-size: 26px; color: #ffffff;
 
769
                        background-color: #999999; width: 105%; margin-left: 0px;
 
770
                        padding-top: 10px; padding-bottom: 10px; padding-left: 15px;}
 
771
                    .hidden {
 
772
                        position: absolute; visibility: hidden; z-index: 200; left: 250px; top: 100px;
 
773
                        font-family: arial; overflow: hidden; width: 600;
 
774
                        padding: 20px; font-size: 10px; background-color: #999999;
 
775
                        layer-background-color:#FFFFFF; }
 
776
                    a,a:active  { color: charcoal; font-weight: bold; }
 
777
                    a:visited   { color: #666666; font-weight: bold; }
 
778
                    a:hover     { color: cc3300; font-weight: bold; }
 
779
                </style>
 
780
                <script language="JavaScript" type="text/javascript">
 
781
                <!--
 
782
                // POP-UP CAPTIONS...
 
783
                function lib_bwcheck(){ //Browsercheck (needed)
 
784
                    this.ver=navigator.appVersion
 
785
                    this.agent=navigator.userAgent
 
786
                    this.dom=document.getElementById?1:0
 
787
                    this.opera5=this.agent.indexOf("Opera 5")>-1
 
788
                    this.ie5=(this.ver.indexOf("MSIE 5")>-1 && this.dom && !this.opera5)?1:0;
 
789
                    this.ie6=(this.ver.indexOf("MSIE 6")>-1 && this.dom && !this.opera5)?1:0;
 
790
                    this.ie4=(document.all && !this.dom && !this.opera5)?1:0;
 
791
                    this.ie=this.ie4||this.ie5||this.ie6
 
792
                    this.mac=this.agent.indexOf("Mac")>-1
 
793
                    this.ns6=(this.dom && parseInt(this.ver) >= 5) ?1:0;
 
794
                    this.ns4=(document.layers && !this.dom)?1:0;
 
795
                    this.bw=(this.ie6 || this.ie5 || this.ie4 || this.ns4 || this.ns6 || this.opera5)
 
796
                    return this
 
797
                }
 
798
                var bw = new lib_bwcheck()
 
799
                //Makes crossbrowser object.
 
800
                function makeObj(obj){
 
801
                    this.evnt=bw.dom? document.getElementById(obj):bw.ie4?document.all[obj]:bw.ns4?document.layers[obj]:0;
 
802
                    if(!this.evnt) return false
 
803
                    this.css=bw.dom||bw.ie4?this.evnt.style:bw.ns4?this.evnt:0;
 
804
                    this.wref=bw.dom||bw.ie4?this.evnt:bw.ns4?this.css.document:0;
 
805
                    this.writeIt=b_writeIt;
 
806
                    return this
 
807
                }
 
808
                // A unit of measure that will be added when setting the position of a layer.
 
809
                //var px = bw.ns4||window.opera?"":"px";
 
810
                function b_writeIt(text){
 
811
                    if (bw.ns4){this.wref.write(text);this.wref.close()}
 
812
                    else this.wref.innerHTML = text
 
813
                }
 
814
                //Shows the messages
 
815
                var oDesc;
 
816
                function popup(divid){
 
817
                    if(oDesc = new makeObj(divid)){
 
818
                        oDesc.css.visibility = "visible"
 
819
                    }
 
820
                }
 
821
                function popout(){ // Hides message
 
822
                    if(oDesc) oDesc.css.visibility = "hidden"
 
823
                }
 
824
                //-->
 
825
                </script>
 
826
                </head>
 
827
                <body>
 
828
                <div class=content>
 
829
                        <br><br>
 
830
                        <div class=title>'.$this->serviceName.'</div>
 
831
                        <div class=nav>
 
832
                                <p>View the <a href="'.$PHP_SELF.'?wsdl">WSDL</a> for the service.
 
833
                                Click on an operation name to view it&apos;s details.</p>
 
834
                                <ul>';
 
835
                                foreach($this->getOperations() as $op => $data){
 
836
                                    $b .= "<li><a href='#' onclick=\"popout();popup('$op')\">$op</a></li>";
 
837
                                    // create hidden div
 
838
                                    $b .= "<div id='$op' class='hidden'>
 
839
                                    <a href='#' onclick='popout()'><font color='#ffffff'>Close</font></a><br><br>";
 
840
                                    foreach($data as $donnie => $marie){ // loop through opdata
 
841
                                                if($donnie == 'input' || $donnie == 'output'){ // show input/output data
 
842
                                                    $b .= "<font color='white'>".ucfirst($donnie).':</font><br>';
 
843
                                                    foreach($marie as $captain => $tenille){ // loop through data
 
844
                                                                if($captain == 'parts'){ // loop thru parts
 
845
                                                                    $b .= "&nbsp;&nbsp;$captain:<br>";
 
846
                                                        //if(is_array($tenille)){
 
847
                                                                        foreach($tenille as $joanie => $chachi){
 
848
                                                                                        $b .= "&nbsp;&nbsp;&nbsp;&nbsp;$joanie: $chachi<br>";
 
849
                                                                        }
 
850
                                                                //}
 
851
                                                                } else {
 
852
                                                                    $b .= "&nbsp;&nbsp;$captain: $tenille<br>";
 
853
                                                                }
 
854
                                                    }
 
855
                                                } else {
 
856
                                                    $b .= "<font color='white'>".ucfirst($donnie).":</font> $marie<br>";
 
857
                                                }
 
858
                                    }
 
859
                                        $b .= '</div>';
 
860
                                }
 
861
                                $b .= '
 
862
                                <ul>
 
863
                        </div>
 
864
                </div></body></html>';
 
865
                return $b;
 
866
    }
 
867
 
 
868
        /**
 
869
        * serialize the parsed wsdl
 
870
        *
 
871
        * @param mixed $debug whether to put debug=1 in endpoint URL
 
872
        * @return string serialization of WSDL
 
873
        * @access public 
 
874
        */
 
875
        function serialize($debug = 0)
 
876
        {
 
877
                $xml = '<?xml version="1.0" encoding="ISO-8859-1"?>';
 
878
                $xml .= "\n<definitions";
 
879
                foreach($this->namespaces as $k => $v) {
 
880
                        $xml .= " xmlns:$k=\"$v\"";
 
881
                } 
 
882
                // 10.9.02 - add poulter fix for wsdl and tns declarations
 
883
                if (isset($this->namespaces['wsdl'])) {
 
884
                        $xml .= " xmlns=\"" . $this->namespaces['wsdl'] . "\"";
 
885
                } 
 
886
                if (isset($this->namespaces['tns'])) {
 
887
                        $xml .= " targetNamespace=\"" . $this->namespaces['tns'] . "\"";
 
888
                } 
 
889
                $xml .= '>'; 
 
890
                // imports
 
891
                if (sizeof($this->import) > 0) {
 
892
                        foreach($this->import as $ns => $list) {
 
893
                                foreach ($list as $ii) {
 
894
                                        if ($ii['location'] != '') {
 
895
                                                $xml .= '<import location="' . $ii['location'] . '" namespace="' . $ns . '" />';
 
896
                                        } else {
 
897
                                                $xml .= '<import namespace="' . $ns . '" />';
 
898
                                        }
 
899
                                }
 
900
                        } 
 
901
                } 
 
902
                // types
 
903
                if (count($this->schemas)>=1) {
 
904
                        $xml .= "\n<types>\n";
 
905
                        foreach ($this->schemas as $ns => $list) {
 
906
                                foreach ($list as $xs) {
 
907
                                        $xml .= $xs->serializeSchema();
 
908
                                }
 
909
                        }
 
910
                        $xml .= '</types>';
 
911
                } 
 
912
                // messages
 
913
                if (count($this->messages) >= 1) {
 
914
                        foreach($this->messages as $msgName => $msgParts) {
 
915
                                $xml .= "\n<message name=\"" . $msgName . '">';
 
916
                                if(is_array($msgParts)){
 
917
                                        foreach($msgParts as $partName => $partType) {
 
918
                                                // print 'serializing '.$partType.', sv: '.$this->XMLSchemaVersion.'<br>';
 
919
                                                if (strpos($partType, ':')) {
 
920
                                                    $typePrefix = $this->getPrefixFromNamespace($this->getPrefix($partType));
 
921
                                                } elseif (isset($this->typemap[$this->namespaces['xsd']][$partType])) {
 
922
                                                    // print 'checking typemap: '.$this->XMLSchemaVersion.'<br>';
 
923
                                                    $typePrefix = 'xsd';
 
924
                                                } else {
 
925
                                                    foreach($this->typemap as $ns => $types) {
 
926
                                                        if (isset($types[$partType])) {
 
927
                                                            $typePrefix = $this->getPrefixFromNamespace($ns);
 
928
                                                        } 
 
929
                                                    } 
 
930
                                                    if (!isset($typePrefix)) {
 
931
                                                        die("$partType has no namespace!");
 
932
                                                    } 
 
933
                                                }
 
934
                                                $ns = $this->getNamespaceFromPrefix($typePrefix);
 
935
                                                $localPart = $this->getLocalPart($partType);
 
936
                                                $typeDef = $this->getTypeDef($localPart, $ns);
 
937
                                                if ($typeDef['typeClass'] == 'element') {
 
938
                                                        $elementortype = 'element';
 
939
                                                        if (substr($localPart, -1) == '^') {
 
940
                                                                $localPart = substr($localPart, 0, -1);
 
941
                                                        }
 
942
                                                } else {
 
943
                                                        $elementortype = 'type';
 
944
                                                }
 
945
                                                $xml .= "\n" . '  <part name="' . $partName . '" ' . $elementortype . '="' . $typePrefix . ':' . $localPart . '" />';
 
946
                                        }
 
947
                                }
 
948
                                $xml .= '</message>';
 
949
                        } 
 
950
                } 
 
951
                // bindings & porttypes
 
952
                if (count($this->bindings) >= 1) {
 
953
                        $binding_xml = '';
 
954
                        $portType_xml = '';
 
955
                        foreach($this->bindings as $bindingName => $attrs) {
 
956
                                $binding_xml .= "\n<binding name=\"" . $bindingName . '" type="tns:' . $attrs['portType'] . '">';
 
957
                                $binding_xml .= "\n" . '  <soap:binding style="' . $attrs['style'] . '" transport="' . $attrs['transport'] . '"/>';
 
958
                                $portType_xml .= "\n<portType name=\"" . $attrs['portType'] . '">';
 
959
                                foreach($attrs['operations'] as $opName => $opParts) {
 
960
                                        $binding_xml .= "\n" . '  <operation name="' . $opName . '">';
 
961
                                        $binding_xml .= "\n" . '    <soap:operation soapAction="' . $opParts['soapAction'] . '" style="'. $opParts['style'] . '"/>';
 
962
                                        if (isset($opParts['input']['encodingStyle']) && $opParts['input']['encodingStyle'] != '') {
 
963
                                                $enc_style = ' encodingStyle="' . $opParts['input']['encodingStyle'] . '"';
 
964
                                        } else {
 
965
                                                $enc_style = '';
 
966
                                        }
 
967
                                        $binding_xml .= "\n" . '    <input><soap:body use="' . $opParts['input']['use'] . '" namespace="' . $opParts['input']['namespace'] . '"' . $enc_style . '/></input>';
 
968
                                        if (isset($opParts['output']['encodingStyle']) && $opParts['output']['encodingStyle'] != '') {
 
969
                                                $enc_style = ' encodingStyle="' . $opParts['output']['encodingStyle'] . '"';
 
970
                                        } else {
 
971
                                                $enc_style = '';
 
972
                                        }
 
973
                                        $binding_xml .= "\n" . '    <output><soap:body use="' . $opParts['output']['use'] . '" namespace="' . $opParts['output']['namespace'] . '"' . $enc_style . '/></output>';
 
974
                                        $binding_xml .= "\n" . '  </operation>';
 
975
                                        $portType_xml .= "\n" . '  <operation name="' . $opParts['name'] . '"';
 
976
                                        if (isset($opParts['parameterOrder'])) {
 
977
                                            $portType_xml .= ' parameterOrder="' . $opParts['parameterOrder'] . '"';
 
978
                                        } 
 
979
                                        $portType_xml .= '>';
 
980
                                        if(isset($opParts['documentation']) && $opParts['documentation'] != '') {
 
981
                                                $portType_xml .= "\n" . '    <documentation>' . htmlspecialchars($opParts['documentation']) . '</documentation>';
 
982
                                        }
 
983
                                        $portType_xml .= "\n" . '    <input message="tns:' . $opParts['input']['message'] . '"/>';
 
984
                                        $portType_xml .= "\n" . '    <output message="tns:' . $opParts['output']['message'] . '"/>';
 
985
                                        $portType_xml .= "\n" . '  </operation>';
 
986
                                } 
 
987
                                $portType_xml .= "\n" . '</portType>';
 
988
                                $binding_xml .= "\n" . '</binding>';
 
989
                        } 
 
990
                        $xml .= $portType_xml . $binding_xml;
 
991
                } 
 
992
                // services
 
993
                $xml .= "\n<service name=\"" . $this->serviceName . '">';
 
994
                if (count($this->ports) >= 1) {
 
995
                        foreach($this->ports as $pName => $attrs) {
 
996
                                $xml .= "\n" . '  <port name="' . $pName . '" binding="tns:' . $attrs['binding'] . '">';
 
997
                                $xml .= "\n" . '    <soap:address location="' . $attrs['location'] . ($debug ? '?debug=1' : '') . '"/>';
 
998
                                $xml .= "\n" . '  </port>';
 
999
                        } 
 
1000
                } 
 
1001
                $xml .= "\n" . '</service>';
 
1002
                return $xml . "\n</definitions>";
 
1003
        } 
 
1004
 
 
1005
        /**
 
1006
         * determine whether a set of parameters are unwrapped
 
1007
         * when they are expect to be wrapped, Microsoft-style.
 
1008
         *
 
1009
         * @param string $type the type (element name) of the wrapper
 
1010
         * @param array $parameters the parameter values for the SOAP call
 
1011
         * @return boolean whether they parameters are unwrapped (and should be wrapped)
 
1012
         * @access private
 
1013
         */
 
1014
        function parametersMatchWrapped($type, &$parameters) {
 
1015
                $this->debug("in parametersMatchWrapped type=$type, parameters=");
 
1016
                $this->appendDebug($this->varDump($parameters));
 
1017
 
 
1018
                // split type into namespace:unqualified-type
 
1019
                if (strpos($type, ':')) {
 
1020
                        $uqType = substr($type, strrpos($type, ':') + 1);
 
1021
                        $ns = substr($type, 0, strrpos($type, ':'));
 
1022
                        $this->debug("in parametersMatchWrapped: got a prefixed type: $uqType, $ns");
 
1023
                        if ($this->getNamespaceFromPrefix($ns)) {
 
1024
                                $ns = $this->getNamespaceFromPrefix($ns);
 
1025
                                $this->debug("in parametersMatchWrapped: expanded prefixed type: $uqType, $ns");
 
1026
                        }
 
1027
                } else {
 
1028
                        // TODO: should the type be compared to types in XSD, and the namespace
 
1029
                        // set to XSD if the type matches?
 
1030
                        $this->debug("in parametersMatchWrapped: No namespace for type $type");
 
1031
                        $ns = '';
 
1032
                        $uqType = $type;
 
1033
                }
 
1034
 
 
1035
                // get the type information
 
1036
                if (!$typeDef = $this->getTypeDef($uqType, $ns)) {
 
1037
                        $this->debug("in parametersMatchWrapped: $type ($uqType) is not a supported type.");
 
1038
                        return false;
 
1039
                }
 
1040
                $this->debug("in parametersMatchWrapped: found typeDef=");
 
1041
                $this->appendDebug($this->varDump($typeDef));
 
1042
                if (substr($uqType, -1) == '^') {
 
1043
                        $uqType = substr($uqType, 0, -1);
 
1044
                }
 
1045
                $phpType = $typeDef['phpType'];
 
1046
                $arrayType = (isset($typeDef['arrayType']) ? $typeDef['arrayType'] : '');
 
1047
                $this->debug("in parametersMatchWrapped: uqType: $uqType, ns: $ns, phptype: $phpType, arrayType: $arrayType");
 
1048
                
 
1049
                // we expect a complexType or element of complexType
 
1050
                if ($phpType != 'struct') {
 
1051
                        $this->debug("in parametersMatchWrapped: not a struct");
 
1052
                        return false;
 
1053
                }
 
1054
 
 
1055
                // see whether the parameter names match the elements
 
1056
                if (isset($typeDef['elements']) && is_array($typeDef['elements'])) {
 
1057
                        $elements = 0;
 
1058
                        $matches = 0;
 
1059
                        $change = false;
 
1060
                        if ($this->isArraySimpleOrStruct($parameters) == 'arraySimple' && count($parameters) == count($typeDef['elements'])) {
 
1061
                                $this->debug("in parametersMatchWrapped: (wrapped return value kludge) correct number of elements in simple array, so change array and wrap");
 
1062
                                $change = true;
 
1063
                        }
 
1064
                        foreach ($typeDef['elements'] as $name => $attrs) {
 
1065
                                if ($change) {
 
1066
                                        $this->debug("in parametersMatchWrapped: change parameter $element to name $name");
 
1067
                                        $parameters[$name] = $parameters[$elements];
 
1068
                                        unset($parameters[$elements]);
 
1069
                                        $matches++;
 
1070
                                } elseif (isset($parameters[$name])) {
 
1071
                                        $this->debug("in parametersMatchWrapped: have parameter named $name");
 
1072
                                        $matches++;
 
1073
                                } else {
 
1074
                                        $this->debug("in parametersMatchWrapped: do not have parameter named $name");
 
1075
                                }
 
1076
                                $elements++;
 
1077
                        }
 
1078
 
 
1079
                        $this->debug("in parametersMatchWrapped: $matches parameter names match $elements wrapped parameter names");
 
1080
                        if ($matches == 0) {
 
1081
                                return false;
 
1082
                        }
 
1083
                        return true;
 
1084
                }
 
1085
 
 
1086
                // since there are no elements for the type, if the user passed no
 
1087
                // parameters, the parameters match wrapped.
 
1088
                $this->debug("in parametersMatchWrapped: no elements type $ns:$uqType");
 
1089
                return count($parameters) == 0;
 
1090
        }
 
1091
 
 
1092
        /**
 
1093
         * serialize PHP values according to a WSDL message definition
 
1094
         * contrary to the method name, this is not limited to RPC
 
1095
         *
 
1096
         * TODO
 
1097
         * - multi-ref serialization
 
1098
         * - validate PHP values against type definitions, return errors if invalid
 
1099
         * 
 
1100
         * @param string $operation operation name
 
1101
         * @param string $direction (input|output)
 
1102
         * @param mixed $parameters parameter value(s)
 
1103
         * @param string $bindingType (soap|soap12)
 
1104
         * @return mixed parameters serialized as XML or false on error (e.g. operation not found)
 
1105
         * @access public
 
1106
         */
 
1107
        function serializeRPCParameters($operation, $direction, $parameters, $bindingType = 'soap') {
 
1108
                $this->debug("in serializeRPCParameters: operation=$operation, direction=$direction, XMLSchemaVersion=$this->XMLSchemaVersion, bindingType=$bindingType");
 
1109
                $this->appendDebug('parameters=' . $this->varDump($parameters));
 
1110
                
 
1111
                if ($direction != 'input' && $direction != 'output') {
 
1112
                        $this->debug('The value of the \$direction argument needs to be either "input" or "output"');
 
1113
                        $this->setError('The value of the \$direction argument needs to be either "input" or "output"');
 
1114
                        return false;
 
1115
                } 
 
1116
                if (!$opData = $this->getOperationData($operation, $bindingType)) {
 
1117
                        $this->debug('Unable to retrieve WSDL data for operation: ' . $operation . ' bindingType: ' . $bindingType);
 
1118
                        $this->setError('Unable to retrieve WSDL data for operation: ' . $operation . ' bindingType: ' . $bindingType);
 
1119
                        return false;
 
1120
                }
 
1121
                $this->debug('in serializeRPCParameters: opData:');
 
1122
                $this->appendDebug($this->varDump($opData));
 
1123
 
 
1124
                // Get encoding style for output and set to current
 
1125
                $encodingStyle = 'http://schemas.xmlsoap.org/soap/encoding/';
 
1126
                if(($direction == 'input') && isset($opData['output']['encodingStyle']) && ($opData['output']['encodingStyle'] != $encodingStyle)) {
 
1127
                        $encodingStyle = $opData['output']['encodingStyle'];
 
1128
                        $enc_style = $encodingStyle;
 
1129
                }
 
1130
 
 
1131
                // set input params
 
1132
                $xml = '';
 
1133
                if (isset($opData[$direction]['parts']) && sizeof($opData[$direction]['parts']) > 0) {
 
1134
                        $parts = &$opData[$direction]['parts'];
 
1135
                        $part_count = sizeof($parts);
 
1136
                        $style = $opData['style'];
 
1137
                        $use = $opData[$direction]['use'];
 
1138
                        $this->debug("have $part_count part(s) to serialize using $style/$use");
 
1139
                        if (is_array($parameters)) {
 
1140
                                $parametersArrayType = $this->isArraySimpleOrStruct($parameters);
 
1141
                                $parameter_count = count($parameters);
 
1142
                                $this->debug("have $parameter_count parameter(s) provided as $parametersArrayType to serialize");
 
1143
                                // check for Microsoft-style wrapped parameters
 
1144
                                if ($style == 'document' && $use == 'literal' && $part_count == 1 && isset($parts['parameters'])) {
 
1145
                                        $this->debug('check whether the caller has wrapped the parameters');
 
1146
                                        if ((($parametersArrayType == 'arrayStruct' || $parameter_count == 0) && !isset($parameters['parameters'])) || ($direction == 'output' && $parametersArrayType == 'arraySimple' && $parameter_count == 1)) {
 
1147
                                                $this->debug('check whether caller\'s parameters match the wrapped ones');
 
1148
                                                if ($this->parametersMatchWrapped($parts['parameters'], $parameters)) {
 
1149
                                                        $this->debug('wrap the parameters for the caller');
 
1150
                                                        $parameters = array('parameters' => $parameters);
 
1151
                                                        $parameter_count = 1;
 
1152
                                                }
 
1153
                                        }
 
1154
                                }
 
1155
                                foreach ($parts as $name => $type) {
 
1156
                                        $this->debug("serializing part $name of type $type");
 
1157
                                        // Track encoding style
 
1158
                                        if (isset($opData[$direction]['encodingStyle']) && $encodingStyle != $opData[$direction]['encodingStyle']) {
 
1159
                                                $encodingStyle = $opData[$direction]['encodingStyle'];                  
 
1160
                                                $enc_style = $encodingStyle;
 
1161
                                        } else {
 
1162
                                                $enc_style = false;
 
1163
                                        }
 
1164
                                        // NOTE: add error handling here
 
1165
                                        // if serializeType returns false, then catch global error and fault
 
1166
                                        if ($parametersArrayType == 'arraySimple') {
 
1167
                                                $p = array_shift($parameters);
 
1168
                                                $this->debug('calling serializeType w/indexed param');
 
1169
                                                $xml .= $this->serializeType($name, $type, $p, $use, $enc_style);
 
1170
                                        } elseif (isset($parameters[$name])) {
 
1171
                                                $this->debug('calling serializeType w/named param');
 
1172
                                                $xml .= $this->serializeType($name, $type, $parameters[$name], $use, $enc_style);
 
1173
                                        } else {
 
1174
                                                // TODO: only send nillable
 
1175
                                                $this->debug('calling serializeType w/null param');
 
1176
                                                $xml .= $this->serializeType($name, $type, null, $use, $enc_style);
 
1177
                                        }
 
1178
                                }
 
1179
                        } else {
 
1180
                                $this->debug('no parameters passed.');
 
1181
                        }
 
1182
                }
 
1183
                $this->debug("serializeRPCParameters returning: $xml");
 
1184
                return $xml;
 
1185
        } 
 
1186
        
 
1187
        /**
 
1188
         * serialize a PHP value according to a WSDL message definition
 
1189
         * 
 
1190
         * TODO
 
1191
         * - multi-ref serialization
 
1192
         * - validate PHP values against type definitions, return errors if invalid
 
1193
         * 
 
1194
         * @param string $operation operation name
 
1195
         * @param string $direction (input|output)
 
1196
         * @param mixed $parameters parameter value(s)
 
1197
         * @return mixed parameters serialized as XML or false on error (e.g. operation not found)
 
1198
         * @access public
 
1199
         * @deprecated
 
1200
         */
 
1201
        function serializeParameters($operation, $direction, $parameters)
 
1202
        {
 
1203
                $this->debug("in serializeParameters: operation=$operation, direction=$direction, XMLSchemaVersion=$this->XMLSchemaVersion"); 
 
1204
                $this->appendDebug('parameters=' . $this->varDump($parameters));
 
1205
                
 
1206
                if ($direction != 'input' && $direction != 'output') {
 
1207
                        $this->debug('The value of the \$direction argument needs to be either "input" or "output"');
 
1208
                        $this->setError('The value of the \$direction argument needs to be either "input" or "output"');
 
1209
                        return false;
 
1210
                } 
 
1211
                if (!$opData = $this->getOperationData($operation)) {
 
1212
                        $this->debug('Unable to retrieve WSDL data for operation: ' . $operation);
 
1213
                        $this->setError('Unable to retrieve WSDL data for operation: ' . $operation);
 
1214
                        return false;
 
1215
                }
 
1216
                $this->debug('opData:');
 
1217
                $this->appendDebug($this->varDump($opData));
 
1218
                
 
1219
                // Get encoding style for output and set to current
 
1220
                $encodingStyle = 'http://schemas.xmlsoap.org/soap/encoding/';
 
1221
                if(($direction == 'input') && isset($opData['output']['encodingStyle']) && ($opData['output']['encodingStyle'] != $encodingStyle)) {
 
1222
                        $encodingStyle = $opData['output']['encodingStyle'];
 
1223
                        $enc_style = $encodingStyle;
 
1224
                }
 
1225
                
 
1226
                // set input params
 
1227
                $xml = '';
 
1228
                if (isset($opData[$direction]['parts']) && sizeof($opData[$direction]['parts']) > 0) {
 
1229
                        
 
1230
                        $use = $opData[$direction]['use'];
 
1231
                        $this->debug("use=$use");
 
1232
                        $this->debug('got ' . count($opData[$direction]['parts']) . ' part(s)');
 
1233
                        if (is_array($parameters)) {
 
1234
                                $parametersArrayType = $this->isArraySimpleOrStruct($parameters);
 
1235
                                $this->debug('have ' . $parametersArrayType . ' parameters');
 
1236
                                foreach($opData[$direction]['parts'] as $name => $type) {
 
1237
                                        $this->debug('serializing part "'.$name.'" of type "'.$type.'"');
 
1238
                                        // Track encoding style
 
1239
                                        if(isset($opData[$direction]['encodingStyle']) && $encodingStyle != $opData[$direction]['encodingStyle']) {
 
1240
                                                $encodingStyle = $opData[$direction]['encodingStyle'];                  
 
1241
                                                $enc_style = $encodingStyle;
 
1242
                                        } else {
 
1243
                                                $enc_style = false;
 
1244
                                        }
 
1245
                                        // NOTE: add error handling here
 
1246
                                        // if serializeType returns false, then catch global error and fault
 
1247
                                        if ($parametersArrayType == 'arraySimple') {
 
1248
                                                $p = array_shift($parameters);
 
1249
                                                $this->debug('calling serializeType w/indexed param');
 
1250
                                                $xml .= $this->serializeType($name, $type, $p, $use, $enc_style);
 
1251
                                        } elseif (isset($parameters[$name])) {
 
1252
                                                $this->debug('calling serializeType w/named param');
 
1253
                                                $xml .= $this->serializeType($name, $type, $parameters[$name], $use, $enc_style);
 
1254
                                        } else {
 
1255
                                                // TODO: only send nillable
 
1256
                                                $this->debug('calling serializeType w/null param');
 
1257
                                                $xml .= $this->serializeType($name, $type, null, $use, $enc_style);
 
1258
                                        }
 
1259
                                }
 
1260
                        } else {
 
1261
                                $this->debug('no parameters passed.');
 
1262
                        }
 
1263
                }
 
1264
                $this->debug("serializeParameters returning: $xml");
 
1265
                return $xml;
 
1266
        } 
 
1267
        
 
1268
        /**
 
1269
         * serializes a PHP value according a given type definition
 
1270
         * 
 
1271
         * @param string $name name of value (part or element)
 
1272
         * @param string $type XML schema type of value (type or element)
 
1273
         * @param mixed $value a native PHP value (parameter value)
 
1274
         * @param string $use use for part (encoded|literal)
 
1275
         * @param string $encodingStyle SOAP encoding style for the value (if different than the enclosing style)
 
1276
         * @param boolean $unqualified a kludge for what should be XML namespace form handling
 
1277
         * @return string value serialized as an XML string
 
1278
         * @access private
 
1279
         */
 
1280
        function serializeType($name, $type, $value, $use='encoded', $encodingStyle=false, $unqualified=false)
 
1281
        {
 
1282
                $this->debug("in serializeType: name=$name, type=$type, use=$use, encodingStyle=$encodingStyle, unqualified=" . ($unqualified ? "unqualified" : "qualified"));
 
1283
                $this->appendDebug("value=" . $this->varDump($value));
 
1284
                if($use == 'encoded' && $encodingStyle) {
 
1285
                        $encodingStyle = ' SOAP-ENV:encodingStyle="' . $encodingStyle . '"';
 
1286
                }
 
1287
 
 
1288
                // if a soapval has been supplied, let its type override the WSDL
 
1289
        if (is_object($value) && get_class($value) == 'soapval') {
 
1290
                if ($value->type_ns) {
 
1291
                        $type = $value->type_ns . ':' . $value->type;
 
1292
                        $forceType = true;
 
1293
                        $this->debug("in serializeType: soapval overrides type to $type");
 
1294
                } elseif ($value->type) {
 
1295
                        $type = $value->type;
 
1296
                        $forceType = true;
 
1297
                        $this->debug("in serializeType: soapval overrides type to $type");
 
1298
                } else {
 
1299
                        $forceType = false;
 
1300
                        $this->debug("in serializeType: soapval does not override type");
 
1301
                }
 
1302
                $attrs = $value->attributes;
 
1303
                $value = $value->value;
 
1304
                $this->debug("in serializeType: soapval overrides value to $value");
 
1305
                if ($attrs) {
 
1306
                        if (!is_array($value)) {
 
1307
                                $value['!'] = $value;
 
1308
                        }
 
1309
                        foreach ($attrs as $n => $v) {
 
1310
                                $value['!' . $n] = $v;
 
1311
                        }
 
1312
                        $this->debug("in serializeType: soapval provides attributes");
 
1313
                    }
 
1314
        } else {
 
1315
                $forceType = false;
 
1316
        }
 
1317
 
 
1318
                $xml = '';
 
1319
                if (strpos($type, ':')) {
 
1320
                        $uqType = substr($type, strrpos($type, ':') + 1);
 
1321
                        $ns = substr($type, 0, strrpos($type, ':'));
 
1322
                        $this->debug("in serializeType: got a prefixed type: $uqType, $ns");
 
1323
                        if ($this->getNamespaceFromPrefix($ns)) {
 
1324
                                $ns = $this->getNamespaceFromPrefix($ns);
 
1325
                                $this->debug("in serializeType: expanded prefixed type: $uqType, $ns");
 
1326
                        }
 
1327
 
 
1328
                        if($ns == $this->XMLSchemaVersion || $ns == 'http://schemas.xmlsoap.org/soap/encoding/'){
 
1329
                                $this->debug('in serializeType: type namespace indicates XML Schema or SOAP Encoding type');
 
1330
                                if ($unqualified && $use == 'literal') {
 
1331
                                        $elementNS = " xmlns=\"\"";
 
1332
                                } else {
 
1333
                                        $elementNS = '';
 
1334
                                }
 
1335
                                if (is_null($value)) {
 
1336
                                        if ($use == 'literal') {
 
1337
                                                // TODO: depends on minOccurs
 
1338
                                                $xml = "<$name$elementNS/>";
 
1339
                                        } else {
 
1340
                                                // TODO: depends on nillable, which should be checked before calling this method
 
1341
                                                $xml = "<$name$elementNS xsi:nil=\"true\" xsi:type=\"" . $this->getPrefixFromNamespace($ns) . ":$uqType\"/>";
 
1342
                                        }
 
1343
                                        $this->debug("in serializeType: returning: $xml");
 
1344
                                        return $xml;
 
1345
                                }
 
1346
                                if ($uqType == 'Array') {
 
1347
                                        // JBoss/Axis does this sometimes
 
1348
                                        return $this->serialize_val($value, $name, false, false, false, false, $use);
 
1349
                                }
 
1350
                        if ($uqType == 'boolean') {
 
1351
                                if ((is_string($value) && $value == 'false') || (! $value)) {
 
1352
                                                $value = 'false';
 
1353
                                        } else {
 
1354
                                                $value = 'true';
 
1355
                                        }
 
1356
                                } 
 
1357
                                if ($uqType == 'string' && gettype($value) == 'string') {
 
1358
                                        $value = $this->expandEntities($value);
 
1359
                                }
 
1360
                                if (($uqType == 'long' || $uqType == 'unsignedLong') && gettype($value) == 'double') {
 
1361
                                        $value = sprintf("%.0lf", $value);
 
1362
                                }
 
1363
                                // it's a scalar
 
1364
                                // TODO: what about null/nil values?
 
1365
                                // check type isn't a custom type extending xmlschema namespace
 
1366
                                if (!$this->getTypeDef($uqType, $ns)) {
 
1367
                                        if ($use == 'literal') {
 
1368
                                                if ($forceType) {
 
1369
                                                        $xml = "<$name$elementNS xsi:type=\"" . $this->getPrefixFromNamespace($ns) . ":$uqType\">$value</$name>";
 
1370
                                                } else {
 
1371
                                                        $xml = "<$name$elementNS>$value</$name>";
 
1372
                                                }
 
1373
                                        } else {
 
1374
                                                $xml = "<$name$elementNS xsi:type=\"" . $this->getPrefixFromNamespace($ns) . ":$uqType\"$encodingStyle>$value</$name>";
 
1375
                                        }
 
1376
                                        $this->debug("in serializeType: returning: $xml");
 
1377
                                        return $xml;
 
1378
                                }
 
1379
                                $this->debug('custom type extends XML Schema or SOAP Encoding namespace (yuck)');
 
1380
                        } else if ($ns == 'http://xml.apache.org/xml-soap') {
 
1381
                                $this->debug('in serializeType: appears to be Apache SOAP type');
 
1382
                                if ($uqType == 'Map') {
 
1383
                                        $tt_prefix = $this->getPrefixFromNamespace('http://xml.apache.org/xml-soap');
 
1384
                                        if (! $tt_prefix) {
 
1385
                                                $this->debug('in serializeType: Add namespace for Apache SOAP type');
 
1386
                                                $tt_prefix = 'ns' . rand(1000, 9999);
 
1387
                                                $this->namespaces[$tt_prefix] = 'http://xml.apache.org/xml-soap';
 
1388
                                                // force this to be added to usedNamespaces
 
1389
                                                $tt_prefix = $this->getPrefixFromNamespace('http://xml.apache.org/xml-soap');
 
1390
                                        }
 
1391
                                        $contents = '';
 
1392
                                        foreach($value as $k => $v) {
 
1393
                                                $this->debug("serializing map element: key $k, value $v");
 
1394
                                                $contents .= '<item>';
 
1395
                                                $contents .= $this->serialize_val($k,'key',false,false,false,false,$use);
 
1396
                                                $contents .= $this->serialize_val($v,'value',false,false,false,false,$use);
 
1397
                                                $contents .= '</item>';
 
1398
                                        }
 
1399
                                        if ($use == 'literal') {
 
1400
                                                if ($forceType) {
 
1401
                                                        $xml = "<$name xsi:type=\"" . $tt_prefix . ":$uqType\">$contents</$name>";
 
1402
                                                } else {
 
1403
                                                        $xml = "<$name>$contents</$name>";
 
1404
                                                }
 
1405
                                        } else {
 
1406
                                                $xml = "<$name xsi:type=\"" . $tt_prefix . ":$uqType\"$encodingStyle>$contents</$name>";
 
1407
                                        }
 
1408
                                        $this->debug("in serializeType: returning: $xml");
 
1409
                                        return $xml;
 
1410
                                }
 
1411
                                $this->debug('in serializeType: Apache SOAP type, but only support Map');
 
1412
                        }
 
1413
                } else {
 
1414
                        // TODO: should the type be compared to types in XSD, and the namespace
 
1415
                        // set to XSD if the type matches?
 
1416
                        $this->debug("in serializeType: No namespace for type $type");
 
1417
                        $ns = '';
 
1418
                        $uqType = $type;
 
1419
                }
 
1420
                if(!$typeDef = $this->getTypeDef($uqType, $ns)){
 
1421
                        $this->setError("$type ($uqType) is not a supported type.");
 
1422
                        $this->debug("in serializeType: $type ($uqType) is not a supported type.");
 
1423
                        return false;
 
1424
                } else {
 
1425
                        $this->debug("in serializeType: found typeDef");
 
1426
                        $this->appendDebug('typeDef=' . $this->varDump($typeDef));
 
1427
                        if (substr($uqType, -1) == '^') {
 
1428
                                $uqType = substr($uqType, 0, -1);
 
1429
                        }
 
1430
                }
 
1431
                $phpType = $typeDef['phpType'];
 
1432
                $this->debug("in serializeType: uqType: $uqType, ns: $ns, phptype: $phpType, arrayType: " . (isset($typeDef['arrayType']) ? $typeDef['arrayType'] : '') ); 
 
1433
                // if php type == struct, map value to the <all> element names
 
1434
                if ($phpType == 'struct') {
 
1435
                        if (isset($typeDef['typeClass']) && $typeDef['typeClass'] == 'element') {
 
1436
                                $elementName = $uqType;
 
1437
                                if (isset($typeDef['form']) && ($typeDef['form'] == 'qualified')) {
 
1438
                                        $elementNS = " xmlns=\"$ns\"";
 
1439
                                } else {
 
1440
                                        $elementNS = " xmlns=\"\"";
 
1441
                                }
 
1442
                        } else {
 
1443
                                $elementName = $name;
 
1444
                                if ($unqualified) {
 
1445
                                        $elementNS = " xmlns=\"\"";
 
1446
                                } else {
 
1447
                                        $elementNS = '';
 
1448
                                }
 
1449
                        }
 
1450
                        if (is_null($value)) {
 
1451
                                if ($use == 'literal') {
 
1452
                                        // TODO: depends on minOccurs
 
1453
                                        $xml = "<$elementName$elementNS/>";
 
1454
                                } else {
 
1455
                                        $xml = "<$elementName$elementNS xsi:nil=\"true\" xsi:type=\"" . $this->getPrefixFromNamespace($ns) . ":$uqType\"/>";
 
1456
                                }
 
1457
                                $this->debug("in serializeType: returning: $xml");
 
1458
                                return $xml;
 
1459
                        }
 
1460
                        if (is_object($value)) {
 
1461
                                $value = get_object_vars($value);
 
1462
                        }
 
1463
                        if (is_array($value)) {
 
1464
                                $elementAttrs = $this->serializeComplexTypeAttributes($typeDef, $value, $ns, $uqType);
 
1465
                                if ($use == 'literal') {
 
1466
                                        if ($forceType) {
 
1467
                                                $xml = "<$elementName$elementNS$elementAttrs xsi:type=\"" . $this->getPrefixFromNamespace($ns) . ":$uqType\">";
 
1468
                                        } else {
 
1469
                                                $xml = "<$elementName$elementNS$elementAttrs>";
 
1470
                                        }
 
1471
                                } else {
 
1472
                                        $xml = "<$elementName$elementNS$elementAttrs xsi:type=\"" . $this->getPrefixFromNamespace($ns) . ":$uqType\"$encodingStyle>";
 
1473
                                }
 
1474
        
 
1475
                                $xml .= $this->serializeComplexTypeElements($typeDef, $value, $ns, $uqType, $use, $encodingStyle);
 
1476
                                $xml .= "</$elementName>";
 
1477
                        } else {
 
1478
                                $this->debug("in serializeType: phpType is struct, but value is not an array");
 
1479
                                $this->setError("phpType is struct, but value is not an array: see debug output for details");
 
1480
                                $xml = '';
 
1481
                        }
 
1482
                } elseif ($phpType == 'array') {
 
1483
                        if (isset($typeDef['form']) && ($typeDef['form'] == 'qualified')) {
 
1484
                                $elementNS = " xmlns=\"$ns\"";
 
1485
                        } else {
 
1486
                                if ($unqualified) {
 
1487
                                        $elementNS = " xmlns=\"\"";
 
1488
                                } else {
 
1489
                                        $elementNS = '';
 
1490
                                }
 
1491
                        }
 
1492
                        if (is_null($value)) {
 
1493
                                if ($use == 'literal') {
 
1494
                                        // TODO: depends on minOccurs
 
1495
                                        $xml = "<$name$elementNS/>";
 
1496
                                } else {
 
1497
                                        $xml = "<$name$elementNS xsi:nil=\"true\" xsi:type=\"" .
 
1498
                                                $this->getPrefixFromNamespace('http://schemas.xmlsoap.org/soap/encoding/') .
 
1499
                                                ":Array\" " .
 
1500
                                                $this->getPrefixFromNamespace('http://schemas.xmlsoap.org/soap/encoding/') .
 
1501
                                                ':arrayType="' .
 
1502
                                                $this->getPrefixFromNamespace($this->getPrefix($typeDef['arrayType'])) .
 
1503
                                                ':' .
 
1504
                                                $this->getLocalPart($typeDef['arrayType'])."[0]\"/>";
 
1505
                                }
 
1506
                                $this->debug("in serializeType: returning: $xml");
 
1507
                                return $xml;
 
1508
                        }
 
1509
                        if (isset($typeDef['multidimensional'])) {
 
1510
                                $nv = array();
 
1511
                                foreach($value as $v) {
 
1512
                                        $cols = ',' . sizeof($v);
 
1513
                                        $nv = array_merge($nv, $v);
 
1514
                                } 
 
1515
                                $value = $nv;
 
1516
                        } else {
 
1517
                                $cols = '';
 
1518
                        } 
 
1519
                        if (is_array($value) && sizeof($value) >= 1) {
 
1520
                                $rows = sizeof($value);
 
1521
                                $contents = '';
 
1522
                                foreach($value as $k => $v) {
 
1523
                                        $this->debug("serializing array element: $k, $v of type: $typeDef[arrayType]");
 
1524
                                        //if (strpos($typeDef['arrayType'], ':') ) {
 
1525
                                        if (!in_array($typeDef['arrayType'],$this->typemap['http://www.w3.org/2001/XMLSchema'])) {
 
1526
                                            $contents .= $this->serializeType('item', $typeDef['arrayType'], $v, $use);
 
1527
                                        } else {
 
1528
                                            $contents .= $this->serialize_val($v, 'item', $typeDef['arrayType'], null, $this->XMLSchemaVersion, false, $use);
 
1529
                                        } 
 
1530
                                }
 
1531
                        } else {
 
1532
                                $rows = 0;
 
1533
                                $contents = null;
 
1534
                        }
 
1535
                        // TODO: for now, an empty value will be serialized as a zero element
 
1536
                        // array.  Revisit this when coding the handling of null/nil values.
 
1537
                        if ($use == 'literal') {
 
1538
                                $xml = "<$name$elementNS>"
 
1539
                                        .$contents
 
1540
                                        ."</$name>";
 
1541
                        } else {
 
1542
                                $xml = "<$name$elementNS xsi:type=\"".$this->getPrefixFromNamespace('http://schemas.xmlsoap.org/soap/encoding/').':Array" '.
 
1543
                                        $this->getPrefixFromNamespace('http://schemas.xmlsoap.org/soap/encoding/')
 
1544
                                        .':arrayType="'
 
1545
                                        .$this->getPrefixFromNamespace($this->getPrefix($typeDef['arrayType']))
 
1546
                                        .":".$this->getLocalPart($typeDef['arrayType'])."[$rows$cols]\">"
 
1547
                                        .$contents
 
1548
                                        ."</$name>";
 
1549
                        }
 
1550
                } elseif ($phpType == 'scalar') {
 
1551
                        if (isset($typeDef['form']) && ($typeDef['form'] == 'qualified')) {
 
1552
                                $elementNS = " xmlns=\"$ns\"";
 
1553
                        } else {
 
1554
                                if ($unqualified) {
 
1555
                                        $elementNS = " xmlns=\"\"";
 
1556
                                } else {
 
1557
                                        $elementNS = '';
 
1558
                                }
 
1559
                        }
 
1560
                        if ($use == 'literal') {
 
1561
                                if ($forceType) {
 
1562
                                        $xml = "<$name$elementNS xsi:type=\"" . $this->getPrefixFromNamespace($ns) . ":$uqType\">$value</$name>";
 
1563
                                } else {
 
1564
                                        $xml = "<$name$elementNS>$value</$name>";
 
1565
                                }
 
1566
                        } else {
 
1567
                                $xml = "<$name$elementNS xsi:type=\"" . $this->getPrefixFromNamespace($ns) . ":$uqType\"$encodingStyle>$value</$name>";
 
1568
                        }
 
1569
                }
 
1570
                $this->debug("in serializeType: returning: $xml");
 
1571
                return $xml;
 
1572
        }
 
1573
        
 
1574
        /**
 
1575
         * serializes the attributes for a complexType
 
1576
         *
 
1577
         * @param array $typeDef our internal representation of an XML schema type (or element)
 
1578
         * @param mixed $value a native PHP value (parameter value)
 
1579
         * @param string $ns the namespace of the type
 
1580
         * @param string $uqType the local part of the type
 
1581
         * @return string value serialized as an XML string
 
1582
         * @access private
 
1583
         */
 
1584
        function serializeComplexTypeAttributes($typeDef, $value, $ns, $uqType) {
 
1585
                $xml = '';
 
1586
                if (isset($typeDef['attrs']) && is_array($typeDef['attrs'])) {
 
1587
                        $this->debug("serialize attributes for XML Schema type $ns:$uqType");
 
1588
                        if (is_array($value)) {
 
1589
                                $xvalue = $value;
 
1590
                        } elseif (is_object($value)) {
 
1591
                                $xvalue = get_object_vars($value);
 
1592
                        } else {
 
1593
                                $this->debug("value is neither an array nor an object for XML Schema type $ns:$uqType");
 
1594
                                $xvalue = array();
 
1595
                        }
 
1596
                        foreach ($typeDef['attrs'] as $aName => $attrs) {
 
1597
                                if (isset($xvalue['!' . $aName])) {
 
1598
                                        $xname = '!' . $aName;
 
1599
                                        $this->debug("value provided for attribute $aName with key $xname");
 
1600
                                } elseif (isset($xvalue[$aName])) {
 
1601
                                        $xname = $aName;
 
1602
                                        $this->debug("value provided for attribute $aName with key $xname");
 
1603
                                } elseif (isset($attrs['default'])) {
 
1604
                                        $xname = '!' . $aName;
 
1605
                                        $xvalue[$xname] = $attrs['default'];
 
1606
                                        $this->debug('use default value of ' . $xvalue[$aName] . ' for attribute ' . $aName);
 
1607
                                } else {
 
1608
                                        $xname = '';
 
1609
                                        $this->debug("no value provided for attribute $aName");
 
1610
                                }
 
1611
                                if ($xname) {
 
1612
                                        $xml .=  " $aName=\"" . $this->expandEntities($xvalue[$xname]) . "\"";
 
1613
                                }
 
1614
                        } 
 
1615
                } else {
 
1616
                        $this->debug("no attributes to serialize for XML Schema type $ns:$uqType");
 
1617
                }
 
1618
                if (isset($typeDef['extensionBase'])) {
 
1619
                        $ns = $this->getPrefix($typeDef['extensionBase']);
 
1620
                        $uqType = $this->getLocalPart($typeDef['extensionBase']);
 
1621
                        if ($this->getNamespaceFromPrefix($ns)) {
 
1622
                                $ns = $this->getNamespaceFromPrefix($ns);
 
1623
                        }
 
1624
                        if ($typeDef = $this->getTypeDef($uqType, $ns)) {
 
1625
                                $this->debug("serialize attributes for extension base $ns:$uqType");
 
1626
                                $xml .= $this->serializeComplexTypeAttributes($typeDef, $value, $ns, $uqType);
 
1627
                        } else {
 
1628
                                $this->debug("extension base $ns:$uqType is not a supported type");
 
1629
                        }
 
1630
                }
 
1631
                return $xml;
 
1632
        }
 
1633
 
 
1634
        /**
 
1635
         * serializes the elements for a complexType
 
1636
         *
 
1637
         * @param array $typeDef our internal representation of an XML schema type (or element)
 
1638
         * @param mixed $value a native PHP value (parameter value)
 
1639
         * @param string $ns the namespace of the type
 
1640
         * @param string $uqType the local part of the type
 
1641
         * @param string $use use for part (encoded|literal)
 
1642
         * @param string $encodingStyle SOAP encoding style for the value (if different than the enclosing style)
 
1643
         * @return string value serialized as an XML string
 
1644
         * @access private
 
1645
         */
 
1646
        function serializeComplexTypeElements($typeDef, $value, $ns, $uqType, $use='encoded', $encodingStyle=false) {
 
1647
                $xml = '';
 
1648
                if (isset($typeDef['elements']) && is_array($typeDef['elements'])) {
 
1649
                        $this->debug("in serializeComplexTypeElements, serialize elements for XML Schema type $ns:$uqType");
 
1650
                        if (is_array($value)) {
 
1651
                                $xvalue = $value;
 
1652
                        } elseif (is_object($value)) {
 
1653
                                $xvalue = get_object_vars($value);
 
1654
                        } else {
 
1655
                                $this->debug("value is neither an array nor an object for XML Schema type $ns:$uqType");
 
1656
                                $xvalue = array();
 
1657
                        }
 
1658
                        // toggle whether all elements are present - ideally should validate against schema
 
1659
                        if (count($typeDef['elements']) != count($xvalue)){
 
1660
                                $optionals = true;
 
1661
                        }
 
1662
                        foreach ($typeDef['elements'] as $eName => $attrs) {
 
1663
                                if (!isset($xvalue[$eName])) {
 
1664
                                        if (isset($attrs['default'])) {
 
1665
                                                $xvalue[$eName] = $attrs['default'];
 
1666
                                                $this->debug('use default value of ' . $xvalue[$eName] . ' for element ' . $eName);
 
1667
                                        }
 
1668
                                }
 
1669
                                // if user took advantage of a minOccurs=0, then only serialize named parameters
 
1670
                                if (isset($optionals)
 
1671
                                    && (!isset($xvalue[$eName])) 
 
1672
                                        && ( (!isset($attrs['nillable'])) || $attrs['nillable'] != 'true')
 
1673
                                        ){
 
1674
                                        if (isset($attrs['minOccurs']) && $attrs['minOccurs'] <> '0') {
 
1675
                                                $this->debug("apparent error: no value provided for element $eName with minOccurs=" . $attrs['minOccurs']);
 
1676
                                        }
 
1677
                                        // do nothing
 
1678
                                        $this->debug("no value provided for complexType element $eName and element is not nillable, so serialize nothing");
 
1679
                                } else {
 
1680
                                        // get value
 
1681
                                        if (isset($xvalue[$eName])) {
 
1682
                                            $v = $xvalue[$eName];
 
1683
                                        } else {
 
1684
                                            $v = null;
 
1685
                                        }
 
1686
                                        if (isset($attrs['form'])) {
 
1687
                                                $unqualified = ($attrs['form'] == 'unqualified');
 
1688
                                        } else {
 
1689
                                                $unqualified = false;
 
1690
                                        }
 
1691
                                        if (isset($attrs['maxOccurs']) && ($attrs['maxOccurs'] == 'unbounded' || $attrs['maxOccurs'] > 1) && isset($v) && is_array($v) && $this->isArraySimpleOrStruct($v) == 'arraySimple') {
 
1692
                                                $vv = $v;
 
1693
                                                foreach ($vv as $k => $v) {
 
1694
                                                        if (isset($attrs['type']) || isset($attrs['ref'])) {
 
1695
                                                                // serialize schema-defined type
 
1696
                                                            $xml .= $this->serializeType($eName, isset($attrs['type']) ? $attrs['type'] : $attrs['ref'], $v, $use, $encodingStyle, $unqualified);
 
1697
                                                        } else {
 
1698
                                                                // serialize generic type (can this ever really happen?)
 
1699
                                                            $this->debug("calling serialize_val() for $v, $eName, false, false, false, false, $use");
 
1700
                                                            $xml .= $this->serialize_val($v, $eName, false, false, false, false, $use);
 
1701
                                                        }
 
1702
                                                }
 
1703
                                        } else {
 
1704
                                                if (isset($attrs['type']) || isset($attrs['ref'])) {
 
1705
                                                        // serialize schema-defined type
 
1706
                                                    $xml .= $this->serializeType($eName, isset($attrs['type']) ? $attrs['type'] : $attrs['ref'], $v, $use, $encodingStyle, $unqualified);
 
1707
                                                } else {
 
1708
                                                        // serialize generic type (can this ever really happen?)
 
1709
                                                    $this->debug("calling serialize_val() for $v, $eName, false, false, false, false, $use");
 
1710
                                                    $xml .= $this->serialize_val($v, $eName, false, false, false, false, $use);
 
1711
                                                }
 
1712
                                        }
 
1713
                                }
 
1714
                        } 
 
1715
                } else {
 
1716
                        $this->debug("no elements to serialize for XML Schema type $ns:$uqType");
 
1717
                }
 
1718
                if (isset($typeDef['extensionBase'])) {
 
1719
                        $ns = $this->getPrefix($typeDef['extensionBase']);
 
1720
                        $uqType = $this->getLocalPart($typeDef['extensionBase']);
 
1721
                        if ($this->getNamespaceFromPrefix($ns)) {
 
1722
                                $ns = $this->getNamespaceFromPrefix($ns);
 
1723
                        }
 
1724
                        if ($typeDef = $this->getTypeDef($uqType, $ns)) {
 
1725
                                $this->debug("serialize elements for extension base $ns:$uqType");
 
1726
                                $xml .= $this->serializeComplexTypeElements($typeDef, $value, $ns, $uqType, $use, $encodingStyle);
 
1727
                        } else {
 
1728
                                $this->debug("extension base $ns:$uqType is not a supported type");
 
1729
                        }
 
1730
                }
 
1731
                return $xml;
 
1732
        }
 
1733
 
 
1734
        /**
 
1735
        * adds an XML Schema complex type to the WSDL types
 
1736
        *
 
1737
        * @param string $name
 
1738
        * @param string $typeClass (complexType|simpleType|attribute)
 
1739
        * @param string $phpType currently supported are array and struct (php assoc array)
 
1740
        * @param string $compositor (all|sequence|choice)
 
1741
        * @param string $restrictionBase namespace:name (http://schemas.xmlsoap.org/soap/encoding/:Array)
 
1742
        * @param array $elements e.g. array ( name => array(name=>'',type=>'') )
 
1743
        * @param array $attrs e.g. array(array('ref'=>'SOAP-ENC:arrayType','wsdl:arrayType'=>'xsd:string[]'))
 
1744
        * @param string $arrayType as namespace:name (xsd:string)
 
1745
        * @see nusoap_xmlschema
 
1746
        * @access public
 
1747
        */
 
1748
        function addComplexType($name,$typeClass='complexType',$phpType='array',$compositor='',$restrictionBase='',$elements=array(),$attrs=array(),$arrayType='') {
 
1749
                if (count($elements) > 0) {
 
1750
                        $eElements = array();
 
1751
                foreach($elements as $n => $e){
 
1752
                    // expand each element
 
1753
                    $ee = array();
 
1754
                    foreach ($e as $k => $v) {
 
1755
                            $k = strpos($k,':') ? $this->expandQname($k) : $k;
 
1756
                            $v = strpos($v,':') ? $this->expandQname($v) : $v;
 
1757
                            $ee[$k] = $v;
 
1758
                        }
 
1759
                        $eElements[$n] = $ee;
 
1760
                }
 
1761
                $elements = $eElements;
 
1762
                }
 
1763
                
 
1764
                if (count($attrs) > 0) {
 
1765
                foreach($attrs as $n => $a){
 
1766
                    // expand each attribute
 
1767
                    foreach ($a as $k => $v) {
 
1768
                            $k = strpos($k,':') ? $this->expandQname($k) : $k;
 
1769
                            $v = strpos($v,':') ? $this->expandQname($v) : $v;
 
1770
                            $aa[$k] = $v;
 
1771
                        }
 
1772
                        $eAttrs[$n] = $aa;
 
1773
                }
 
1774
                $attrs = $eAttrs;
 
1775
                }
 
1776
 
 
1777
                $restrictionBase = strpos($restrictionBase,':') ? $this->expandQname($restrictionBase) : $restrictionBase;
 
1778
                $arrayType = strpos($arrayType,':') ? $this->expandQname($arrayType) : $arrayType;
 
1779
 
 
1780
                $typens = isset($this->namespaces['types']) ? $this->namespaces['types'] : $this->namespaces['tns'];
 
1781
                $this->schemas[$typens][0]->addComplexType($name,$typeClass,$phpType,$compositor,$restrictionBase,$elements,$attrs,$arrayType);
 
1782
        }
 
1783
 
 
1784
        /**
 
1785
        * adds an XML Schema simple type to the WSDL types
 
1786
        *
 
1787
        * @param string $name
 
1788
        * @param string $restrictionBase namespace:name (http://schemas.xmlsoap.org/soap/encoding/:Array)
 
1789
        * @param string $typeClass (should always be simpleType)
 
1790
        * @param string $phpType (should always be scalar)
 
1791
        * @param array $enumeration array of values
 
1792
        * @see nusoap_xmlschema
 
1793
        * @access public
 
1794
        */
 
1795
        function addSimpleType($name, $restrictionBase='', $typeClass='simpleType', $phpType='scalar', $enumeration=array()) {
 
1796
                $restrictionBase = strpos($restrictionBase,':') ? $this->expandQname($restrictionBase) : $restrictionBase;
 
1797
 
 
1798
                $typens = isset($this->namespaces['types']) ? $this->namespaces['types'] : $this->namespaces['tns'];
 
1799
                $this->schemas[$typens][0]->addSimpleType($name, $restrictionBase, $typeClass, $phpType, $enumeration);
 
1800
        }
 
1801
 
 
1802
        /**
 
1803
        * adds an element to the WSDL types
 
1804
        *
 
1805
        * @param array $attrs attributes that must include name and type
 
1806
        * @see nusoap_xmlschema
 
1807
        * @access public
 
1808
        */
 
1809
        function addElement($attrs) {
 
1810
                $typens = isset($this->namespaces['types']) ? $this->namespaces['types'] : $this->namespaces['tns'];
 
1811
                $this->schemas[$typens][0]->addElement($attrs);
 
1812
        }
 
1813
 
 
1814
        /**
 
1815
        * register an operation with the server
 
1816
        * 
 
1817
        * @param string $name operation (method) name
 
1818
        * @param array $in assoc array of input values: key = param name, value = param type
 
1819
        * @param array $out assoc array of output values: key = param name, value = param type
 
1820
        * @param string $namespace optional The namespace for the operation
 
1821
        * @param string $soapaction optional The soapaction for the operation
 
1822
        * @param string $style (rpc|document) optional The style for the operation Note: when 'document' is specified, parameter and return wrappers are created for you automatically
 
1823
        * @param string $use (encoded|literal) optional The use for the parameters (cannot mix right now)
 
1824
        * @param string $documentation optional The description to include in the WSDL
 
1825
        * @param string $encodingStyle optional (usually 'http://schemas.xmlsoap.org/soap/encoding/' for encoded)
 
1826
        * @access public 
 
1827
        */
 
1828
        function addOperation($name, $in = false, $out = false, $namespace = false, $soapaction = false, $style = 'rpc', $use = 'encoded', $documentation = '', $encodingStyle = ''){
 
1829
                if ($use == 'encoded' && $encodingStyle == '') {
 
1830
                        $encodingStyle = 'http://schemas.xmlsoap.org/soap/encoding/';
 
1831
                }
 
1832
 
 
1833
                if ($style == 'document') {
 
1834
                        $elements = array();
 
1835
                        foreach ($in as $n => $t) {
 
1836
                                $elements[$n] = array('name' => $n, 'type' => $t);
 
1837
                        }
 
1838
                        $this->addComplexType($name . 'RequestType', 'complexType', 'struct', 'all', '', $elements);
 
1839
                        $this->addElement(array('name' => $name, 'type' => $name . 'RequestType'));
 
1840
                        $in = array('parameters' => 'tns:' . $name . '^');
 
1841
 
 
1842
                        $elements = array();
 
1843
                        foreach ($out as $n => $t) {
 
1844
                                $elements[$n] = array('name' => $n, 'type' => $t);
 
1845
                        }
 
1846
                        $this->addComplexType($name . 'ResponseType', 'complexType', 'struct', 'all', '', $elements);
 
1847
                        $this->addElement(array('name' => $name . 'Response', 'type' => $name . 'ResponseType', 'form' => 'qualified'));
 
1848
                        $out = array('parameters' => 'tns:' . $name . 'Response' . '^');
 
1849
                }
 
1850
 
 
1851
                // get binding
 
1852
                $this->bindings[ $this->serviceName . 'Binding' ]['operations'][$name] =
 
1853
                array(
 
1854
                'name' => $name,
 
1855
                'binding' => $this->serviceName . 'Binding',
 
1856
                'endpoint' => $this->endpoint,
 
1857
                'soapAction' => $soapaction,
 
1858
                'style' => $style,
 
1859
                'input' => array(
 
1860
                        'use' => $use,
 
1861
                        'namespace' => $namespace,
 
1862
                        'encodingStyle' => $encodingStyle,
 
1863
                        'message' => $name . 'Request',
 
1864
                        'parts' => $in),
 
1865
                'output' => array(
 
1866
                        'use' => $use,
 
1867
                        'namespace' => $namespace,
 
1868
                        'encodingStyle' => $encodingStyle,
 
1869
                        'message' => $name . 'Response',
 
1870
                        'parts' => $out),
 
1871
                'namespace' => $namespace,
 
1872
                'transport' => 'http://schemas.xmlsoap.org/soap/http',
 
1873
                'documentation' => $documentation); 
 
1874
                // add portTypes
 
1875
                // add messages
 
1876
                if($in)
 
1877
                {
 
1878
                        foreach($in as $pName => $pType)
 
1879
                        {
 
1880
                                if(strpos($pType,':')) {
 
1881
                                        $pType = $this->getNamespaceFromPrefix($this->getPrefix($pType)).":".$this->getLocalPart($pType);
 
1882
                                }
 
1883
                                $this->messages[$name.'Request'][$pName] = $pType;
 
1884
                        }
 
1885
                } else {
 
1886
            $this->messages[$name.'Request']= '0';
 
1887
        }
 
1888
                if($out)
 
1889
                {
 
1890
                        foreach($out as $pName => $pType)
 
1891
                        {
 
1892
                                if(strpos($pType,':')) {
 
1893
                                        $pType = $this->getNamespaceFromPrefix($this->getPrefix($pType)).":".$this->getLocalPart($pType);
 
1894
                                }
 
1895
                                $this->messages[$name.'Response'][$pName] = $pType;
 
1896
                        }
 
1897
                } else {
 
1898
            $this->messages[$name.'Response']= '0';
 
1899
        }
 
1900
                return true;
 
1901
        } 
 
1902
}
 
1903
 
1904
1904
?>
 
 
b'\\ No newline at end of file'