1<?php 2 /** 3 * SOAPx4 ("XML-RPC for PHP" and "SOAP for PHP") 4 * @author Dietrich Ayala <dietrich@ganx4.com> 5 * @author Edd Dumbill 6 * @author Victor Zou <victor@gigaideas.com.cn> 7 * @copyright Copyright (C) 1999-2000 Edd Dumbill 8 * @copyright Copyright (C) 2000-2001 Victor Zou 9 * @copyright Copyright (C) 2001 Dietrich Ayala 10 * @copyright Portions Copyright (C) 2004 Free Software Foundation, Inc. http://www.fsf.org/ 11 * @package phpgwapi 12 * @subpackage communication 13 * @version $Id: class.wsdl.inc.php 14407 2004-02-10 13:51:20Z ceb $ 14 * @internal This project began based on code from the 2 projects below, 15 * @internal and still contains some original code. The licenses of both must be respected. 16 */ 17 18 /** 19 * SOAPx4 ("XML-RPC for PHP" and "SOAP for PHP") 20 * 21 * @package phpgwapi 22 * @subpackage communication 23 * This is a class that loads a wsdl file and makes it's data available to an application 24 * it should provide methods that allow both client and server usage of it 25 * Also should have methods for creating a wsdl file from scratch and 26 * serializing wsdl into valid markup 27 */ 28 class wsdl 29 { 30 // constructor 31 function wsdl($wsdl=False) 32 { 33 // define internal arrays of bindings, ports, operations, messages, etc. 34 $this->complexTypes = array(); 35 $this->messages = array(); 36 $this->currentMessage; 37 $this->portOperations = array(); 38 $this->currentOperation; 39 $this->portTypes = array(); 40 $this->currentPortType; 41 $this->bindings = array(); 42 $this->currentBinding; 43 // debug switch 44 $this->debug_flag = False; 45 // parser vars 46 $this->parser; 47 $this->position; 48 $this->depth; 49 $this->depth_array = array(); 50 51 if($wsdl == "-1") 52 { 53 $wsdl=False; 54 } 55 // Check whether content has been read. 56 if($wsdl) 57 { 58 $wsdl_string = join("",file($wsdl)); 59 // Create an XML parser. 60 $this->parser = xml_parser_create(); 61 // Set the options for parsing the XML data. 62 //xml_parser_set_option($parser, XML_OPTION_SKIP_WHITE, 1); 63 xml_parser_set_option($this->parser, XML_OPTION_CASE_FOLDING, 0); 64 // Set the object for the parser. 65 xml_set_object($this->parser, &$this); 66 // Set the element handlers for the parser. 67 xml_set_element_handler($this->parser, 'start_element','end_element'); 68 xml_set_character_data_handler($this->parser,'character_data'); 69 //xml_set_default_handler($this->parser, 'default_handler'); 70 71 // Parse the XML file. 72 if(!xml_parse($this->parser,$wsdl_string,True)) 73 { 74 // Display an error message. 75 $this->debug(sprintf('XML error on line %d: %s', 76 xml_get_current_line_number($this->parser), 77 xml_error_string(xml_get_error_code($this->parser)))); 78 $this->fault = True; 79 } 80 xml_parser_free($this->parser); 81 } 82 } 83 84 // start-element handler 85 function start_element($parser, $name, $attrs) 86 { 87 // position in the total number of elements, starting from 0 88 $pos = $this->position++; 89 $depth = $this->depth++; 90 // set self as current value for this depth 91 $this->depth_array[$depth] = $pos; 92 93 // find status, register data 94 switch($this->status) 95 { 96 case 'types': 97 switch($name) 98 { 99 case 'schema': 100 $this->schema = True; 101 break; 102 case 'complexType': 103 $this->currentElement = $attrs['name']; 104 $this->schemaStatus = 'complexType'; 105 break; 106 case 'element': 107 $this->complexTypes[$this->currentElement]['elements'][$attrs['name']] = $attrs; 108 break; 109 case 'complexContent': 110 break; 111 case 'restriction': 112 $this->complexTypes[$this->currentElement]['restrictionBase'] = $attrs['base']; 113 break; 114 case 'sequence': 115 $this->complexTypes[$this->currentElement]['order'] = 'sequence'; 116 break; 117 case "all": 118 $this->complexTypes[$this->currentElement]['order'] = 'all'; 119 break; 120 case 'attribute': 121 if($attrs['ref']) 122 { 123 $this->complexTypes[$this->currentElement]['attrs'][$attrs['ref']] = $attrs; 124 } 125 elseif($attrs['name']) 126 { 127 $this->complexTypes[$this->currentElement]['attrs'][$attrs['name']] = $attrs; 128 } 129 break; 130 } 131 break; 132 case 'message': 133 if($name == 'part') 134 { 135 $this->messages[$this->currentMessage][$attrs['name']] = $attrs['type']; 136 } 137 break; 138 case 'portType': 139 switch($name) 140 { 141 case 'operation': 142 $this->currentOperation = $attrs['name']; 143 $this->portTypes[$this->currentPortType][$attrs['name']] = $attrs['parameterOrder']; 144 break; 145 default: 146 $this->portOperations[$this->currentOperation][$name]= $attrs; 147 break; 148 } 149 break; 150 case 'binding': 151 switch($name) 152 { 153 case 'soap:binding': 154 $this->bindings[$this->currentBinding] = array_merge($this->bindings[$this->currentBinding],$attrs); 155 break; 156 case 'operation': 157 $this->currentOperation = $attrs['name']; 158 $this->bindings[$this->currentBinding]['operations'][$attrs['name']] = array(); 159 break; 160 case 'soap:operation': 161 $this->bindings[$this->currentBinding]['operations'][$this->currentOperation]['soapAction'] = $attrs['soapAction']; 162 break; 163 case 'input': 164 $this->opStatus = 'input'; 165 case 'soap:body': 166 $this->bindings[$this->currentBinding]['operations'][$this->currentOperation][$this->opStatus] = $attrs; 167 break; 168 case 'output': 169 $this->opStatus = 'output'; 170 break; 171 } 172 break; 173 case 'service': 174 switch($name) 175 { 176 case 'port': 177 $this->currentPort = $attrs['name']; 178 $this->ports[$attrs['name']] = $attrs; 179 break; 180 case 'soap:address': 181 $this->ports[$this->currentPort]['location'] = $attrs['location']; 182 break; 183 } 184 break; 185 } 186 // set status 187 switch($name) 188 { 189 case 'types': 190 $this->status = 'types'; 191 break; 192 case 'message': 193 $this->status = 'message'; 194 $this->messages[$attrs['name']] = array(); 195 $this->currentMessage = $attrs['name']; 196 break; 197 case 'portType': 198 $this->status = 'portType'; 199 $this->portTypes[$attrs['name']] = array(); 200 $this->currentPortType = $attrs['name']; 201 break; 202 case 'binding': 203 $this->status = 'binding'; 204 $this->currentBinding = $attrs['name']; 205 $this->bindings[$attrs['name']]['type'] = $attrs['type']; 206 break; 207 case 'service': 208 $this->status = 'service'; 209 break; 210 } 211 // get element prefix 212 if(ereg(":",$name)) 213 { 214 $prefix = substr($name,0,strpos($name,':')); 215 } 216 } 217 218 function getEndpoint($portName) 219 { 220 if($endpoint = $this->ports[$portName]['location']) 221 { 222 return $endpoint; 223 } 224 return False; 225 } 226 227 function getPortName($operation) 228 { 229 @reset($this->ports); 230 while(list($port,$portAttrs) = @each($this->ports)); 231 /* foreach($this->ports as $port => $portAttrs) */ 232 { 233 $binding = substr($portAttrs['binding'],4); 234 @reset($this->bindings[$binding]['operations']); 235 while(list($op,$opAttrs) = @each($this->bindings[$binding]['operations'])) 236 /* foreach($this->bindings[$binding]["operations"] as $op => $opAttrs) */ 237 { 238 if($op == $operation) 239 { 240 return $port; 241 } 242 } 243 } 244 } 245 246 function getSoapAction($portName,$operation) 247 { 248 if($binding = substr($this->ports[$portName]['binding'],4)) 249 { 250 if($soapAction = $this->bindings[$binding]['operations'][$operation]['soapAction']) 251 { 252 return $soapAction; 253 } 254 return False; 255 } 256 return False; 257 } 258 259 function getNamespace($portName,$operation) 260 { 261 if($binding = substr($this->ports[$portName]['binding'],4)) 262 { 263 //$this->debug("looking for namespace using binding '$binding', port '$portName', operation '$operation'"); 264 if($namespace = $this->bindings[$binding]['operations'][$operation]['input']['namespace']) 265 { 266 return $namespace; 267 } 268 return False; 269 } 270 return False; 271 } 272 273 // end-element handler 274 function end_element($parser, $name) 275 { 276 // position of current element is equal to the last value left in depth_array for my depth 277 $pos = $this->depth_array[$this->depth]; 278 // bring depth down a notch 279 $this->depth--; 280 } 281 282 // element content handler 283 function character_data($parser, $data) 284 { 285 $pos = $this->depth_array[$this->depth]; 286 $this->message[$pos]['cdata'] .= $data; 287 } 288 289 function debug($string) 290 { 291 if($this->debug_flag) 292 { 293 $this->debug_str .= "$string\n"; 294 } 295 } 296 } 297?> 298