1 | <?php
|
---|
2 | /**
|
---|
3 | * This file contains the code for the DISCO server, providing DISO and WSDL
|
---|
4 | * services.
|
---|
5 | *
|
---|
6 | * PHP versions 4 and 5
|
---|
7 | *
|
---|
8 | * LICENSE: This source file is subject to version 2.02 of the PHP license,
|
---|
9 | * that is bundled with this package in the file LICENSE, and is available at
|
---|
10 | * through the world-wide-web at http://www.php.net/license/2_02.txt. If you
|
---|
11 | * did not receive a copy of the PHP license and are unable to obtain it
|
---|
12 | * through the world-wide-web, please send a note to license@php.net so we can
|
---|
13 | * mail you a copy immediately.
|
---|
14 | *
|
---|
15 | * @category Web Services
|
---|
16 | * @package SOAP
|
---|
17 | * @author Dmitri Vinogradov <dimitri@vinogradov.de>
|
---|
18 | * @author Chuck Hagenbuch <chuck@horde.org>
|
---|
19 | * @author Jan Schneider <jan@horde.org>
|
---|
20 | * @copyright 2003-2005 The PHP Group
|
---|
21 | * @license http://www.php.net/license/2_02.txt PHP License 2.02
|
---|
22 | * @link http://pear.php.net/package/SOAP
|
---|
23 | */
|
---|
24 |
|
---|
25 | require_once 'SOAP/Base.php';
|
---|
26 |
|
---|
27 | class SOAP_DISCO_Server extends SOAP_Base_Object {
|
---|
28 |
|
---|
29 | var $namespaces = array(SCHEMA_WSDL => 'wsdl', SCHEMA_SOAP => 'soap');
|
---|
30 | var $import_ns = array();
|
---|
31 | var $wsdl = '';
|
---|
32 | var $disco = '';
|
---|
33 | var $_wsdl = array();
|
---|
34 | var $_disco = array();
|
---|
35 | var $_service_name = '';
|
---|
36 | var $_service_ns = '';
|
---|
37 | var $_service_desc = '';
|
---|
38 | var $_portname = '';
|
---|
39 | var $_bindingname = '';
|
---|
40 | var $soap_server = NULL;
|
---|
41 |
|
---|
42 |
|
---|
43 | function SOAP_DISCO_Server($soap_server, $service_name, $service_desc = '',
|
---|
44 | $import_ns = null)
|
---|
45 | {
|
---|
46 | parent::SOAP_Base_Object('Server');
|
---|
47 |
|
---|
48 | if ( !is_object($soap_server)
|
---|
49 | || !get_class($soap_server) == 'soap_server') return;
|
---|
50 |
|
---|
51 | $this->_service_name = $service_name;
|
---|
52 | $this->_service_ns = "urn:$service_name";
|
---|
53 | $this->_service_desc = $service_desc;
|
---|
54 | $this->import_ns = isset($import_ns) ? $import_ns : $this->import_ns;
|
---|
55 | $this->soap_server = $soap_server;
|
---|
56 | $this->host = isset($_SERVER['HTTP_HOST']) ? $_SERVER['HTTP_HOST'] : 'localhost';
|
---|
57 | }
|
---|
58 |
|
---|
59 | function getDISCO()
|
---|
60 | {
|
---|
61 | $this->_generate_DISCO();
|
---|
62 | return $this->disco;
|
---|
63 | }
|
---|
64 |
|
---|
65 | function getWSDL()
|
---|
66 | {
|
---|
67 | $this->_generate_WSDL();
|
---|
68 | return $this->wsdl;
|
---|
69 | }
|
---|
70 |
|
---|
71 | function _generate_DISCO()
|
---|
72 | {
|
---|
73 | // DISCO
|
---|
74 | $this->_disco['disco:discovery']['attr']['xmlns:disco'] = SCHEMA_DISCO;
|
---|
75 | $this->_disco['disco:discovery']['attr']['xmlns:scl'] = SCHEMA_DISCO_SCL;
|
---|
76 | $this->_disco['disco:discovery']['scl:contractRef']['attr']['ref'] =
|
---|
77 | (array_key_exists('HTTPS', $_SERVER) && $_SERVER['HTTPS'] == 'on')
|
---|
78 | ? 'https://' . $this->host . $_SERVER['PHP_SELF'] . '?wsdl'
|
---|
79 | : 'http://' . $this->host . $_SERVER['PHP_SELF'] . '?wsdl';
|
---|
80 |
|
---|
81 | // generate disco xml
|
---|
82 | $this->_generate_DISCO_XML($this->_disco);
|
---|
83 | }
|
---|
84 |
|
---|
85 | function _generate_WSDL()
|
---|
86 | {
|
---|
87 | // WSDL
|
---|
88 | if (is_array($this->soap_server->_namespaces)) {
|
---|
89 | // need to get: typens, xsd & SOAP-ENC
|
---|
90 | $flipped = array_flip($this->soap_server->_namespaces);
|
---|
91 | $this->namespaces[$this->_service_ns] = 'tns';
|
---|
92 | $this->namespaces[$flipped['xsd']] = 'xsd';
|
---|
93 | $this->namespaces[$flipped['SOAP-ENC']] = 'SOAP-ENC';
|
---|
94 | }
|
---|
95 |
|
---|
96 | // DEFINITIONS
|
---|
97 | $this->_wsdl['definitions']['attr']['name'] = $this->_service_name;
|
---|
98 | $this->_wsdl['definitions']['attr']['targetNamespace'] = $this->_service_ns;
|
---|
99 | foreach ($this->namespaces as $ns => $prefix) {
|
---|
100 | $this->_wsdl['definitions']['attr']['xmlns:' . $prefix] = $ns;
|
---|
101 | }
|
---|
102 | $this->_wsdl['definitions']['attr']['xmlns'] = SCHEMA_WSDL;
|
---|
103 |
|
---|
104 | // Import namespaces. Seems to not work yet: wsdl.exe fom .NET can't
|
---|
105 | // handle imported complete wsdl-definitions.
|
---|
106 | if (count($this->import_ns)) {
|
---|
107 | $i = 0;
|
---|
108 | foreach ($this->import_ns as $_ns => $_location) {
|
---|
109 | $this->_wsdl['definitions']['import'][$i]['attr']['location'] = $_location;
|
---|
110 | $this->_wsdl['definitions']['import'][$i]['attr']['namespace'] = $_ns;
|
---|
111 | $i++;
|
---|
112 | }
|
---|
113 | }
|
---|
114 | $this->_wsdl['definitions']['types']['attr']['xmlns']='http://schemas.xmlsoap.org/wsdl/';
|
---|
115 | $this->_wsdl['definitions']['types']['schema']=array();
|
---|
116 |
|
---|
117 | // Placeholder for messages
|
---|
118 | $this->_wsdl['definitions']['message'] = array();
|
---|
119 |
|
---|
120 | // PORTTYPE-NAME
|
---|
121 | $this->_portname = $this->_service_name . 'Port';
|
---|
122 | $this->_wsdl['definitions']['portType']['attr']['name'] = $this->_portname;
|
---|
123 |
|
---|
124 | // BINDING-NAME
|
---|
125 | $this->_bindingname = $this->_service_name . 'Binding';
|
---|
126 | $this->_wsdl['definitions']['binding']['attr']['name'] = $this->_bindingname;
|
---|
127 | $this->_wsdl['definitions']['binding']['attr']['type'] = 'tns:' . $this->_portname;
|
---|
128 | $this->_wsdl['definitions']['binding']['soap:binding']['attr']['style'] = 'rpc';
|
---|
129 | $this->_wsdl['definitions']['binding']['soap:binding']['attr']['transport'] = SCHEMA_SOAP_HTTP;
|
---|
130 |
|
---|
131 | // SERVICE
|
---|
132 | $this->_wsdl['definitions']['service']['attr']['name'] = $this->_service_name . 'Service';
|
---|
133 | $this->_wsdl['definitions']['service']['documentation']['attr'] = '';
|
---|
134 | $this->_wsdl['definitions']['service']['documentation'] = htmlentities($this->_service_desc);
|
---|
135 | $this->_wsdl['definitions']['service']['port']['attr']['name'] = $this->_portname;
|
---|
136 | $this->_wsdl['definitions']['service']['port']['attr']['binding'] = 'tns:' . $this->_bindingname;
|
---|
137 | $this->_wsdl['definitions']['service']['port']['soap:address']['attr']['location'] =
|
---|
138 | (array_key_exists('HTTPS', $_SERVER) && $_SERVER['HTTPS'] == 'on')
|
---|
139 | ? 'https://' . $this->host . $_SERVER['PHP_SELF']
|
---|
140 | : 'http://' . $this->host . $_SERVER['PHP_SELF'];
|
---|
141 |
|
---|
142 | //
|
---|
143 | $dispatch_keys = array_keys($this->soap_server->dispatch_objects);
|
---|
144 | $dc = count($dispatch_keys);
|
---|
145 | for ($di = 0; $di < $dc; $di++) {
|
---|
146 | $namespace = $dispatch_keys[$di];
|
---|
147 | $namespace_objects =& $this->soap_server->dispatch_objects[$namespace];
|
---|
148 | $oc = count($namespace_objects);
|
---|
149 | for ($oi = 0; $oi < $oc; $oi++) {
|
---|
150 | $object = $namespace_objects[$oi];
|
---|
151 | // types definitions
|
---|
152 | $this->addSchemaFromMap($object->__typedef);
|
---|
153 | // MESSAGES
|
---|
154 | $this->addMethodsFromMap($object->__dispatch_map, $namespace, get_class($object));
|
---|
155 | }
|
---|
156 | }
|
---|
157 | if (isset($this->soap_server->dispatch_map)) {
|
---|
158 | $this->addMethodsFromMap($this->soap_server->dispatch_map, $namespace);
|
---|
159 | }
|
---|
160 |
|
---|
161 | // generate wsdl
|
---|
162 | $this->_generate_WSDL_XML();
|
---|
163 | }
|
---|
164 |
|
---|
165 | function &_getSchema($namespace)
|
---|
166 | {
|
---|
167 | // SCHEMA
|
---|
168 | $c = count($this->_wsdl['definitions']['types']['schema']);
|
---|
169 | for($i = 0; $i < $c; $i++) {
|
---|
170 | if ($this->_wsdl['definitions']['types']['schema'][$i]['attr']['targetNamespace'] == $namespace) {
|
---|
171 | return $this->_wsdl['definitions']['types']['schema'][$i];
|
---|
172 | }
|
---|
173 | }
|
---|
174 |
|
---|
175 | // don't have this namespace
|
---|
176 | $schema = array();
|
---|
177 | $schema['attr'] = array();
|
---|
178 | $schema['complexType'] = array();
|
---|
179 | $schema['attr']['xmlns'] = array_search('xsd',$this->namespaces);
|
---|
180 | $schema['attr']['targetNamespace'] = $namespace;
|
---|
181 | $this->_wsdl['definitions']['types']['schema'][] =& $schema;
|
---|
182 |
|
---|
183 | return $schema;
|
---|
184 | }
|
---|
185 |
|
---|
186 | function addSchemaFromMap(&$map)
|
---|
187 | {
|
---|
188 | if (!$map) {
|
---|
189 | return;
|
---|
190 | }
|
---|
191 |
|
---|
192 | foreach ($map as $_type_name => $_type_def) {
|
---|
193 | list($typens,$type) = $this->_getTypeNs($_type_name);
|
---|
194 | if ($typens == 'xsd') {
|
---|
195 | // cannot add to xsd, lets use method_namespace
|
---|
196 | $typens = 'tns';
|
---|
197 | }
|
---|
198 | $schema =& $this->_getSchema(array_search($typens, $this->namespaces));
|
---|
199 | if (!$this->_ifComplexTypeExists($schema['complexType'], $type)) {
|
---|
200 | $ctype =& $schema['complexType'][];
|
---|
201 | $ctype['attr']['name'] = $type;
|
---|
202 | foreach ($_type_def as $_varname => $_vartype) {
|
---|
203 | if (!is_int($_varname)) {
|
---|
204 | list($_vartypens,$_vartype) = $this->_getTypeNs($_vartype);
|
---|
205 | $ctype['all']['attr'] = '';
|
---|
206 | $el =& $ctype['all']['element'][];
|
---|
207 | $el['attr']['name'] = $_varname;
|
---|
208 | $el['attr']['type'] = $_vartypens . ':' . $_vartype;
|
---|
209 | } else {
|
---|
210 | $ctype['complexContent']['attr'] = '';
|
---|
211 | $ctype['complexContent']['restriction']['attr']['base'] = 'SOAP-ENC:Array';
|
---|
212 | foreach ($_vartype as $array_type) {
|
---|
213 | list($_vartypens, $_vartype) = $this->_getTypeNs($array_type);
|
---|
214 | $ctype['complexContent']['restriction']['attribute']['attr']['ref'] = 'SOAP-ENC:arrayType';
|
---|
215 | $ctype['complexContent']['restriction']['attribute']['attr']['wsdl:arrayType'] = $_vartypens . ':' . $_vartype . '[]';
|
---|
216 | }
|
---|
217 | }
|
---|
218 | }
|
---|
219 | }
|
---|
220 | }
|
---|
221 | }
|
---|
222 |
|
---|
223 | function addMethodsFromMap(&$map, $namespace, $classname = null)
|
---|
224 | {
|
---|
225 | if (!$map) {
|
---|
226 | return;
|
---|
227 | }
|
---|
228 |
|
---|
229 | foreach ($map as $method_name => $method_types) {
|
---|
230 | if (array_key_exists('namespace', $method_types)) {
|
---|
231 | $method_namespace = $method_types['namespace'];
|
---|
232 | } else {
|
---|
233 | $method_namespace = $namespace;
|
---|
234 | }
|
---|
235 |
|
---|
236 | // INPUT
|
---|
237 | $input_message = array('attr' => array('name' => $method_name . 'Request'));
|
---|
238 | if (isset($method_types['in']) && is_array($method_types['in'])) {
|
---|
239 | foreach ($method_types['in'] as $name => $type) {
|
---|
240 | list($typens, $type) = $this->_getTypeNs($type);
|
---|
241 | $part = array();
|
---|
242 | $part['attr']['name'] = $name;
|
---|
243 | $part['attr']['type'] = $typens . ':' . $type;
|
---|
244 | $input_message['part'][] = $part;
|
---|
245 | }
|
---|
246 | }
|
---|
247 | $this->_wsdl['definitions']['message'][] = $input_message;
|
---|
248 |
|
---|
249 | // OUTPUT
|
---|
250 | $output_message = array('attr' => array('name' => $method_name . 'Response'));
|
---|
251 | if (isset($method_types['out']) && is_array($method_types['out'])) {
|
---|
252 | foreach ($method_types['out'] as $name => $type) {
|
---|
253 | list($typens, $type) = $this->_getTypeNs($type);
|
---|
254 | $part = array();
|
---|
255 | $part['attr']['name'] = $name;
|
---|
256 | $part['attr']['type'] = $typens . ':' . $type;
|
---|
257 | $output_message['part'][] = $part;
|
---|
258 | }
|
---|
259 | }
|
---|
260 | $this->_wsdl['definitions']['message'][] = $output_message;
|
---|
261 |
|
---|
262 | // PORTTYPES
|
---|
263 | $operation = array();
|
---|
264 | $operation['attr']['name'] = $method_name;
|
---|
265 | // INPUT
|
---|
266 | $operation['input']['attr']['message'] = 'tns:' . $input_message['attr']['name'];
|
---|
267 | // OUTPUT
|
---|
268 | $operation['output']['attr']['message'] = 'tns:' . $output_message['attr']['name'];
|
---|
269 | $this->_wsdl['definitions']['portType']['operation'][] = $operation;
|
---|
270 |
|
---|
271 | // BINDING
|
---|
272 | $binding = array();
|
---|
273 | $binding['attr']['name'] = $method_name;
|
---|
274 | $action = $method_namespace . '#' . ($classname ? $classname . '#' : '') . $method_name;
|
---|
275 | $binding['soap:operation']['attr']['soapAction'] = $action;
|
---|
276 | // INPUT
|
---|
277 | $binding['input']['attr'] = '';
|
---|
278 | $binding['input']['soap:body']['attr']['use'] = 'encoded';
|
---|
279 | $binding['input']['soap:body']['attr']['namespace'] = $method_namespace;
|
---|
280 | $binding['input']['soap:body']['attr']['encodingStyle'] = SOAP_SCHEMA_ENCODING;
|
---|
281 | // OUTPUT
|
---|
282 | $binding['output']['attr'] = '';
|
---|
283 | $binding['output']['soap:body']['attr']['use'] = 'encoded';
|
---|
284 | $binding['output']['soap:body']['attr']['namespace'] = $method_namespace;
|
---|
285 | $binding['output']['soap:body']['attr']['encodingStyle'] = SOAP_SCHEMA_ENCODING;
|
---|
286 | $this->_wsdl['definitions']['binding']['operation'][] = $binding;
|
---|
287 | }
|
---|
288 | }
|
---|
289 |
|
---|
290 | function _generate_DISCO_XML($disco_array)
|
---|
291 | {
|
---|
292 | $disco = '<?xml version="1.0"?>';
|
---|
293 | foreach ($disco_array as $key => $val) {
|
---|
294 | $disco .= $this->_arrayToNode($key,$val);
|
---|
295 | }
|
---|
296 | $this->disco = $disco;
|
---|
297 | }
|
---|
298 |
|
---|
299 | function _generate_WSDL_XML()
|
---|
300 | {
|
---|
301 | $wsdl = '<?xml version="1.0"?>';
|
---|
302 | foreach ($this->_wsdl as $key => $val) {
|
---|
303 | $wsdl .= $this->_arrayToNode($key, $val);
|
---|
304 | }
|
---|
305 | $this->wsdl = $wsdl;
|
---|
306 | }
|
---|
307 |
|
---|
308 | function _arrayToNode($node_name = '', $array)
|
---|
309 | {
|
---|
310 | $return = '';
|
---|
311 | if (is_array($array)) {
|
---|
312 | // we have a node if there's key 'attr'
|
---|
313 | if (array_key_exists('attr',$array)) {
|
---|
314 | $return .= "<$node_name";
|
---|
315 | if (is_array($array['attr'])) {
|
---|
316 | foreach ($array['attr'] as $attr_name => $attr_value) {
|
---|
317 | $return .= " $attr_name=\"$attr_value\"";
|
---|
318 | }
|
---|
319 | }
|
---|
320 |
|
---|
321 | // unset 'attr' and proceed other childs...
|
---|
322 | unset($array['attr']);
|
---|
323 |
|
---|
324 | if (count($array) > 0) {
|
---|
325 | $i = 0;
|
---|
326 | foreach ($array as $child_node_name => $child_node_value) {
|
---|
327 | $return .= $i == 0 ? ">\n" : '';
|
---|
328 | $return .= $this->_arrayToNode($child_node_name,$child_node_value);
|
---|
329 | $i++;
|
---|
330 | }
|
---|
331 | $return .= "</$node_name>\n";
|
---|
332 | } else {
|
---|
333 | $return .= " />\n";
|
---|
334 | }
|
---|
335 | } else {
|
---|
336 | // we have no 'attr' key in array - so it's list of nodes with
|
---|
337 | // the same name ...
|
---|
338 | foreach ($array as $child_node_name => $child_node_value) {
|
---|
339 | $return .= $this->_arrayToNode($node_name,$child_node_value);
|
---|
340 | }
|
---|
341 | }
|
---|
342 | } else {
|
---|
343 | // $array is not an array
|
---|
344 | if ($array !='') {
|
---|
345 | // and its not empty
|
---|
346 | $return .= "<$node_name>$array</$node_name>\n";
|
---|
347 | } else {
|
---|
348 | // and its empty...
|
---|
349 | $return .= "<$node_name />\n";
|
---|
350 | }
|
---|
351 | }
|
---|
352 | return $return;
|
---|
353 | }
|
---|
354 |
|
---|
355 | function _getTypeNs($type)
|
---|
356 | {
|
---|
357 | preg_match_all("'\{(.*)\}'sm", $type, $m);
|
---|
358 | if (isset($m[1][0]) && $m[1][0] != '') {
|
---|
359 | if (!array_key_exists($m[1][0],$this->namespaces)) {
|
---|
360 | $ns_pref = 'ns' . count($this->namespaces);
|
---|
361 | $this->namespaces[$m[1][0]] = $ns_pref;
|
---|
362 | $this->_wsdl['definitions']['attr']['xmlns:' . $ns_pref] = $m[1][0];
|
---|
363 | }
|
---|
364 | $typens = $this->namespaces[$m[1][0]];
|
---|
365 | $type = ereg_replace($m[0][0],'',$type);
|
---|
366 | } else {
|
---|
367 | $typens = 'xsd';
|
---|
368 | }
|
---|
369 | return array($typens,$type);
|
---|
370 | }
|
---|
371 |
|
---|
372 | function _ifComplexTypeExists($typesArray, $type_name)
|
---|
373 | {
|
---|
374 | if (is_array($typesArray)) {
|
---|
375 | foreach ($typesArray as $type_data) {
|
---|
376 | if ($type_data['attr']['name'] == $type_name) {
|
---|
377 | return true;
|
---|
378 | }
|
---|
379 | }
|
---|
380 | }
|
---|
381 | return false;
|
---|
382 | }
|
---|
383 | }
|
---|