• Main Page
  • Related Pages
  • Namespaces
  • Data Structures
  • Files
  • File List
  • Globals

payment/bmf/lib/SOAP/class.ilBMFWSDL.php

Go to the documentation of this file.
00001 <?php
00002 //
00003 // +----------------------------------------------------------------------+
00004 // | PHP Version 4                                                        |
00005 // +----------------------------------------------------------------------+
00006 // | Copyright (c) 1997-2002 The PHP Group                                |
00007 // +----------------------------------------------------------------------+
00008 // | This source file is subject to version 2.02 of the PHP license,      |
00009 // | that is bundled with this package in the file LICENSE, and is        |
00010 // | available at through the world-wide-web at                           |
00011 // | http://www.php.net/license/2_02.txt.                                 |
00012 // | If you did not receive a copy of the PHP license and are unable to   |
00013 // | obtain it through the world-wide-web, please send a note to          |
00014 // | license@php.net so we can mail you a copy immediately.               |
00015 // +----------------------------------------------------------------------+
00016 // | Authors: Shane Caraveo <Shane@Caraveo.com>   Port to PEAR and more   |
00017 // | Authors: Dietrich Ayala <dietrich@ganx4.com> Original Author         |
00018 // +----------------------------------------------------------------------+
00019 //
00020 // $Id: class.ilBMFWSDL.php 5974 2004-11-24 17:03:42Z smeyer $
00021 //
00022 require_once dirname(__FILE__).'/class.ilBMFBase.php';
00023 require_once dirname(__FILE__).'/class.ilBMFFault.php';
00024 require_once 'HTTP/Request.php';
00025 
00026 DEFINE("WSDL_CACHE_MAX_AGE",12*60*60);
00027 DEFINE("WSDL_CACHE_USE",0); // set to zero to turn off caching
00028 
00047 class ilBMFWSDL extends ilBMFBase
00048 {
00049     var $tns = NULL;
00050     var $definition = array();
00051     var $namespaces = array();
00052     var $ns = array();
00053     var $xsd = SOAP_XML_SCHEMA_VERSION;
00054     var $complexTypes = array();
00055     var $elements = array();
00056     var $messages = array();
00057     var $portTypes = array();
00058     var $bindings = array();
00059     var $imports = array();
00060     var $services = array();
00061     var $service = '';
00062     var $uri = '';
00063     var $proxy = NULL;
00064     var $trace = 0;
00072     function ilBMFWSDL($uri = false, $proxy=array()) {
00073         parent::ilBMFBase('WSDL');
00074         $this->uri = $uri;
00075         $this->proxy = $proxy;
00076         $this->parse($uri);
00077         reset($this->services);
00078         $this->service = key($this->services);
00079     }
00080 
00081     function set_service($service) {
00082         if (array_key_exists($service, $this->services)) {
00083             $this->service = $service;
00084         }
00085     }
00086     
00087     function parse($uri, $proxy=array()) {
00088         $parser = new ilBMFWSDL_Parser($uri, $this);
00089         if ($parser->fault) {
00090             $this->_raiseSoapFault($parser->fault);
00091         }
00092     }
00093     
00094     function getEndpoint($portName)
00095     {
00096         return (isset($this->services[$this->service]['ports'][$portName]['address']['location']))
00097                 ? $this->services[$this->service]['ports'][$portName]['address']['location']
00098                 : $this->_raiseSoapFault("no endpoint for port for $portName", $this->uri);
00099     }
00100     
00101     function _getPortName($operation,$service) {
00102         if (isset($this->services[$service]['ports'])) {
00103             foreach ($this->services[$service]['ports'] as $port => $portAttrs) {
00104                 $type = $this->services[$service]['ports'][$port]['type'];
00105                 if ($type == 'soap' &&
00106                     isset($this->bindings[$portAttrs['binding']]['operations'][$operation])) {
00107                         return $port;
00108                 }
00109             }
00110         }
00111         return NULL;
00112     }
00113     
00114     // find the name of the first port that contains an operation of name $operation
00115     // always returns a the soap portName
00116     function getPortName($operation, $service=NULL)
00117     {
00118         if (!$service) $service = $this->service;
00119         if (isset($this->services[$service]['ports'])) {
00120             $portName = $this->_getPortName($operation,$service);
00121             if ($portName) return $portName;
00122         }
00123         // try any service in the wsdl
00124         foreach ($this->services as $serviceName=>$service) {
00125             if (isset($this->services[$serviceName]['ports'])) {
00126                 $portName = $this->_getPortName($operation,$serviceName);
00127                 if ($portName) {
00128                     $this->service = $serviceName;
00129                     return $portName;
00130                 }
00131             }
00132         }
00133         return $this->_raiseSoapFault("no operation $operation in wsdl", $this->uri);
00134     }
00135     
00136     function getOperationData($portName,$operation)
00137     {
00138         if (isset($this->services[$this->service]['ports'][$portName]['binding'])
00139             && $binding = $this->services[$this->service]['ports'][$portName]['binding']) {
00140             // get operation data from binding
00141             if (is_array($this->bindings[$binding]['operations'][$operation])) {
00142                 $opData = $this->bindings[$binding]['operations'][$operation];
00143             }
00144             // get operation data from porttype
00145             $portType = $this->bindings[$binding]['type'];
00146             if (!$portType) {
00147                 return $this->_raiseSoapFault("no port type for binding $binding in wsdl " . $this->uri);
00148             }
00149             if (is_array($this->portTypes[$portType][$operation])) {
00150                 if (isset($this->portTypes[$portType][$operation]['parameterOrder']))
00151                     $opData['parameterOrder'] = $this->portTypes[$portType][$operation]['parameterOrder'];
00152                 $opData['input'] = array_merge($opData['input'], $this->portTypes[$portType][$operation]['input']);
00153                 $opData['output'] = array_merge($opData['output'], $this->portTypes[$portType][$operation]['output']);
00154             }
00155             if (!$opData) 
00156                 return $this->_raiseSoapFault("no operation $operation for port $portName, in wsdl", $this->uri);
00157             $opData['parameters'] = false;
00158             if (isset($this->bindings[$this->services[$this->service]['ports'][$portName]['binding']]['operations'][$operation]['input']['namespace']))
00159                 $opData['namespace'] = $this->bindings[$this->services[$this->service]['ports'][$portName]['binding']]['operations'][$operation]['input']['namespace'];
00160             // message data from messages
00161             $inputMsg = $opData['input']['message'];
00162             if (is_array($this->messages[$inputMsg])) {
00163             foreach ($this->messages[$inputMsg] as $pname => $pattrs) {
00164                 if ($opData['style'] == 'document' && $opData['input']['use'] == 'literal'
00165                     && $pname == 'parameters') {
00166                         $opData['parameters'] = true;
00167                         $opData['namespace'] = $this->namespaces[$pattrs['namespace']];
00168                         $el = $this->elements[$pattrs['namespace']][$pattrs['type']];
00169                         if (isset($el['elements'])) {
00170                             foreach ($el['elements'] as $elname => $elattrs) {
00171                                 $opData['input']['parts'][$elname] = $elattrs;
00172                             }
00173                         }
00174                 } else {
00175                     $opData['input']['parts'][$pname] = $pattrs;
00176                 }
00177             }
00178             }
00179             $outputMsg = $opData['output']['message'];
00180             if (is_array($this->messages[$outputMsg])) {
00181             foreach ($this->messages[$outputMsg] as $pname => $pattrs) {
00182                 if ($opData['style'] == 'document' && $opData['output']['use'] == 'literal'
00183                     && $pname == 'parameters') {
00184 
00185                         $el = $this->elements[$pattrs['namespace']][$pattrs['type']];
00186                         if (isset($el['elements'])) {
00187                             foreach ($el['elements'] as $elname => $elattrs) {
00188                                 $opData['output']['parts'][$elname] = $elattrs;
00189                             }
00190                         }
00191                         
00192                 } else {
00193                     $opData['output']['parts'][$pname] = $pattrs;
00194                 }
00195             }
00196             }
00197             return $opData;
00198         }
00199         return $this->_raiseSoapFault("no binding for port $portName in wsdl", $this->uri);
00200     }
00201     
00202     function matchMethod(&$operation) {
00203         // Overloading lowercases function names :(
00204         foreach ($this->services[$this->service]['ports'] as $port => $portAttrs) {
00205             foreach (array_keys($this->bindings[$portAttrs['binding']]['operations']) as $op) {
00206                 if (strcasecmp($op, $operation) == 0) {
00207                     $operation = $op;
00208                 }
00209             }
00210         }
00211     }
00212     
00213     function getSoapAction($portName, $operation)
00214     {
00215         if (isset($this->bindings[$this->services[$this->service]['ports'][$portName]['binding']]['operations'][$operation]['soapAction']) &&
00216             $soapAction = $this->bindings[$this->services[$this->service]['ports'][$portName]['binding']]['operations'][$operation]['soapAction']) {
00217             return $soapAction;
00218         }
00219         return false;
00220     }
00221     
00222     function getNamespace($portName, $operation)
00223     {
00224         if (isset($this->bindings[$this->services[$this->service]['ports'][$portName]['binding']]) &&
00225             isset($this->bindings[$this->services[$this->service]['ports'][$portName]['binding']]['operations'][$operation]['input']['namespace']) &&
00226             $namespace = $this->bindings[$this->services[$this->service]['ports'][$portName]['binding']]['operations'][$operation]['input']['namespace']) {
00227             return $namespace;
00228         }
00229         return false;
00230     }
00231 
00232     function getNamespaceAttributeName($namespace) {
00233         /* if it doesn't exist at first, flip the array and check again */
00234         if (!array_key_exists($namespace, $this->ns)) {
00235             $this->ns = array_flip($this->namespaces);
00236         }
00237         /* if it doesn't exist now, add it */
00238         if (!array_key_exists($namespace, $this->ns)) {
00239             return $this->addNamespace($namespace);
00240         }
00241         return $this->ns[$namespace];
00242     }
00243     
00244     function addNamespace($namespace) {
00245         if (array_key_exists($namespace, $this->ns)) {
00246             return $this->ns[$namespace];
00247         }
00248         $n = count($this->ns);
00249         $attr = 'ns'.$n;
00250         $this->namespaces['ns'.$n] = $namespace;
00251         $this->ns[$namespace] = $attr;
00252         return $attr;
00253     }
00254     
00255     function _validateString($string) {
00256         // XXX this should be done sooner or later
00257         return true;
00258         #if (preg_match("/^[\w_:#\/]+$/",$string)) return true;
00259         #return false;
00260     }
00261     
00262     function _addArg(&$args, &$argarray, $argname)
00263     {
00264         if ($args) $args .= ", ";
00265         $args .= "\$".$argname;
00266         if (!$this->_validateString($argname)) return NULL;
00267         if ($argarray) $argarray .= ", ";
00268         $argarray .= "\"$argname\"=>\$".$argname;
00269     }
00270     
00271     function _elementArg(&$args, &$argarray, &$_argtype, $_argname)
00272     {
00273         $comments = '';
00274         $el = $this->elements[$_argtype['namespace']][$_argtype['type']];
00275         $tns = isset($this->ns[$el['namespace']])?$this->ns[$el['namespace']]:$_argtype['namespace'];
00276         if (isset($this->complexTypes[$tns][$el['type']])) {
00277             // the element is actually a complex type!
00278             $comments = "        // {$el['type']} is a ComplexType, refer to wsdl for more info\n";
00279             $attrname = "{$_argtype['type']}_attr";
00280             if (isset($this->complexTypes[$tns][$el['type']]['attribute'])) {
00281                 $comments .= "        // {$el['type']} may require attributes, refer to wsdl for more info\n";
00282             }
00283             $comments .= "        \${$attrname}['xmlns'] = '{$this->namespaces[$_argtype['namespace']]}';\n";
00284             $comments .= "        \${$_argtype['type']} = new ilBMFValue('{$_argtype['type']}',false,\${$_argtype['type']},\$$attrname);\n";
00285             $this->_addArg($args,$argarray,$_argtype['type']);
00286             if (isset($this->complexTypes[$tns][$el['type']]['attribute'])) {
00287                 if ($args) $args .= ", ";
00288                 $args .= "\$".$attrname;
00289             }
00290             #$comments = $this->_complexTypeArg($args,$argarray,$el,$_argtype['type']);
00291         } else if (isset($el['elements'])) {
00292             foreach ($el['elements'] as $ename => $element) {
00293                 $comments .= "        \$$ename = new ilBMFValue('{{$this->namespaces[$element['namespace']]}}$ename','{$element['type']}',\$$ename);\n";
00294                 $this->_addArg($args,$argarray,$ename);
00295             }
00296         } else {
00297             #$echoStringParam = new ilBMFValue('{http://soapinterop.org/xsd}echoStringParam',false,$echoStringParam);
00298             $comments .= "        \$$_argname = new ilBMFValue('{{$this->namespaces[$tns]}}$_argname','{$el['type']}',\$$_argname);\n";
00299             $this->_addArg($args,$argarray,$_argname);
00300         }
00301         return $comments;
00302     }
00303     
00304     function _complexTypeArg(&$args, &$argarray, &$_argtype, $_argname)
00305     {
00306         $comments = '';
00307         if (isset($this->complexTypes[$_argtype['namespace']][$_argtype['type']])) {
00308             $comments  = "        // $_argname is a ComplexType {$_argtype['type']},\n";
00309             $comments .= "        //refer to wsdl for more info\n";
00310             if (isset($this->complexTypes[$_argtype['namespace']][$_argtype['type']]['attribute'])) {
00311                 $comments .= "        // $_argname may require attributes, refer to wsdl for more info\n";
00312             }
00313             $wrapname = '{'.$this->namespaces[$_argtype['namespace']].'}'.$_argtype['type'];
00314             $comments .= "        \$$_argname = new ilBMFValue('$_argname','$wrapname',\$$_argname);\n";
00315             
00316         }
00317         $this->_addArg($args,$argarray,$_argname);
00318         return $comments;
00319     }
00320     
00325     function generateProxyCode($port = '', $classname='')
00326     {
00327         $multiport = count($this->services[$this->service]['ports']) > 1;
00328         if (!$port) {
00329             reset($this->services[$this->service]['ports']);
00330             $port = current($this->services[$this->service]['ports']);
00331         }
00332         // XXX currentPort is BAD
00333         $clienturl = $port['address']['location']; 
00334         if (!$classname) {
00335             if ($multiport || $port) {
00336                 $classname = 'WebService_'.$this->service.'_'.$port['name'];
00337             } else {
00338                 $classname = 'WebService_'.$this->service;
00339             }
00340             $classname = str_replace('.','_',$classname);
00341         }
00342         
00343         if (!$this->_validateString($classname)) return NULL;
00344         
00345         $class = "class $classname extends ilBMFClient {\n".
00346         "    function $classname() {\n".
00347         "        \$this->ilBMFClient(\"$clienturl\", 0);\n".
00348         "    }\n";
00349 
00350         // get the binding, from that get the port type
00351         $primaryBinding = $port['binding']; //$this->services[$this->service]['ports'][$port['name']]["binding"];
00352         $primaryBinding = preg_replace("/^(.*:)/","",$primaryBinding);
00353         $portType = $this->bindings[$primaryBinding]['type'];
00354         $portType = preg_replace("/^(.*:)/","",$portType);
00355         $style = $this->bindings[$primaryBinding]['style'];
00356         
00357         // XXX currentPortType is BAD
00358         foreach ($this->portTypes[$portType] as $opname => $operation) {
00359             $soapaction = $this->bindings[$primaryBinding]['operations'][$opname]['soapAction'];
00360             if (isset($this->bindings[$primaryBinding]['operations'][$opname]['style'])) {
00361                 $opstyle = $this->bindings[$primaryBinding]['operations'][$opname]['style'];
00362             } else {
00363                 $opstyle = $style;
00364             }
00365             $use = $this->bindings[$primaryBinding]['operations'][$opname]['input']['use'];
00366             if ($use == 'encoded') {
00367                 $namespace = $this->bindings[$primaryBinding]['operations'][$opname]['input']['namespace'];
00368             } else {
00369                 $bindingType = $this->bindings[$primaryBinding]['type'];
00370                 $ns = $this->portTypes[$bindingType][$opname]['input']['namespace'];
00371                 $namespace = $this->namespaces[$ns];
00372             }
00373 
00374             $args = '';
00375             $argarray = '';
00376             $comments = '';
00377             $wrappers = '';
00378             foreach ($operation['input'] as $argname => $argtype) {
00379                 if ($argname == "message") {
00380                     foreach ($this->messages[$argtype] as $_argname => $_argtype) {
00381                         $comments = '';
00382                         if ($opstyle == 'document' && $use == 'literal' &&
00383                             $_argtype['name'] == 'parameters') {
00384                                 // the type or element refered to is used for parameters!
00385                                 $elattrs = null;
00386                                 $element = $_argtype['element'];
00387                                 $el = $this->elements[$_argtype['namespace']][$_argtype['type']];
00388                                 
00389                                 if($el['complex']) {
00390                                     $namespace = $this->namespaces[$_argtype['namespace']];
00391                                     // XXX need to wrap the parameters in a soap_value
00392                                 }
00393                                 if (isset($el['elements'])) {
00394                                     foreach ($el['elements'] as $elname => $elattrs) {
00395                                         // is the element a complex type?
00396                                         if (isset($this->complexTypes[$elattrs['namespace']][$elname])) {
00397                                             $comments .= $this->_complexTypeArg($args, $argarray, $_argtype, $_argname);
00398                                         } else {
00399                                             $this->_addArg($args, $argarray, $elname);
00400                                         }
00401                                     }
00402                                 }/* else {
00403                                     $comments = $this->_complexTypeArg($args, $argarray, $elattrs, $elattrs['name']);
00404                                 }*/
00405                                 if($el['complex'] && $argarray) {
00406                                     $wrapname = '{'.$this->namespaces[$_argtype['namespace']].'}'.$el['name'];
00407                                     $comments .= "        \${$el['name']} = new ilBMFValue('$wrapname',false,array($argarray));\n";
00408                                     $argarray = "'{$el['name']}'=>\${$el['name']}";
00409                                 }
00410                         } else 
00411                         if (isset($_argtype['element'])) {
00412                             // element argument
00413                             $comments = $this->_elementArg($args, $argarray, $_argtype, $_argtype['type']);
00414                         } else {
00415                             // complex type argument
00416                             $comments = $this->_complexTypeArg($args, $argarray, $_argtype, $_argname);
00417                         }
00418                     }
00419                 }
00420             }
00421             
00422             // validate entries
00423             if (!$this->_validateString($opname)) return NULL;
00424             if (!$this->_validateString($namespace)) return NULL;
00425             if (!$this->_validateString($soapaction)) return NULL;
00426             
00427             if ($argarray) $argarray = "array($argarray)";
00428             else $argarray = 'NULL';
00429             $class .= "    function $opname($args) {\n$comments$wrappers".
00430             "        return \$this->call(\"$opname\", \n".
00431             "                        $argarray, \n".
00432             "                        array('namespace'=>'$namespace',\n".
00433             "                            'soapaction'=>'$soapaction',\n".
00434             "                            'style'=>'$opstyle',\n".
00435             "                            'use'=>'$use'".
00436             ($this->trace?",'trace'=>1":"")." ));\n".
00437             "    }\n";
00438         }    
00439         $class .= "}\n";
00440         return $class;
00441     }
00442 
00443     function generateAllProxies()
00444     {
00445         $proxycode = '';
00446         foreach (array_keys($this->services[$this->service]['ports']) as $key) {
00447             $port =& $this->services[$this->service]['ports'][$key];
00448             $proxycode .= $this->generateProxyCode($port);
00449         }
00450         return $proxycode;
00451     }
00452     
00453     function getProxy($port = '', $name='')
00454     {
00455         $multiport = count($this->services[$this->service]['ports']) > 1;
00456         if (!$port) {
00457             reset($this->services[$this->service]['ports']);
00458             $port = current($this->services[$this->service]['ports']);
00459         }
00460         if ($multiport || $port) {
00461             $classname = 'WebService_'.$this->service.'_'.$port['name'];
00462         } else {
00463             $classname = 'WebService_'.$this->service;
00464         }
00465         if ($name) $classname = $name.'_'.$classname;
00466         $classname = preg_replace('/[ .\(\)]+/','_',$classname);
00467         if (!class_exists($classname)) {
00468             $proxy = $this->generateProxyCode($port,$classname);
00469             eval($proxy);
00470         }
00471         return new $classname;
00472     }
00473     
00474     function &_getComplexTypeForElement($name, $namespace)
00475     {
00476         $t = NULL;
00477         if (isset($this->ns[$namespace]) && 
00478             isset($this->elements[$this->ns[$namespace]][$name]['type'])) {
00479             
00480             $type = $this->elements[$this->ns[$namespace]][$name]['type'];
00481             $ns = $this->elements[$this->ns[$namespace]][$name]['namespace'];
00482             
00483             if (isset($this->complexTypes[$ns][$type])) {
00484                 $t = $this->complexTypes[$ns][$type];
00485             }
00486         }
00487         return $t;
00488     }
00489 
00490     function getComplexTypeNameForElement($name, $namespace)
00491     {
00492         $t = $this->_getComplexTypeForElement($name, $namespace);
00493         if ($t) {
00494             return $t['name'];
00495         }
00496         return NULL;
00497     }
00498     
00499     function getComplexTypeChildType($ns, $name, $child_ns, $child_name) {
00500         // is the type an element?
00501         $t = $this->_getComplexTypeForElement($name, $ns);
00502         if ($t) {
00503             // no, get it from complex types directly
00504             if (isset($t['elements'][$child_name]['type']))
00505                 return $t['elements'][$child_name]['type'];
00506         }
00507         return NULL;
00508     }
00509     
00510     function getSchemaType($type, $name, $type_namespace)
00511     {
00512         # see if it's a complex type so we can deal properly with SOAPENC:arrayType
00513         if ($name && $type) {
00514             # XXX TODO:
00515             # look up the name in the wsdl and validate the type
00516             foreach ($this->complexTypes as $ns=> $types) {
00517                 if (array_key_exists($type, $types)) {
00518                     if (array_key_exists('type', $types[$type])) {
00519                         $arraytype = isset($types[$type]['arrayType'])?$types[$type]['arrayType']:NULL;
00520                         return array($types[$type]['type'],$arraytype,$this->namespaces[$types[$type]['namespace']]);
00521                     }
00522                     if (array_key_exists('arrayType', $types[$type])) {
00523                         return array('Array',$types[$type]['arrayType'],$this->namespaces[$types[$type]['namespace']]);
00524                     }
00525                     if (array_key_exists('elements', $types[$type]) &&
00526                         array_key_exists($name, $types[$type]['elements'])) {
00527                         $type = $types[$type]['elements']['type'];
00528                         return array($type,NULL,$this->namespaces[$types[$type]['namespace']]);
00529                     }
00530                 }
00531             }
00532         }
00533         if ($type && $type_namespace) {
00534             $arrayType = NULL;
00535             # XXX TODO:
00536             # this code currently handles only one way of encoding array types in wsdl
00537             # need to do a generalized function to figure out complex types
00538             $p = $this->ns[$type_namespace];
00539             if ($p &&
00540                 array_key_exists($p, $this->complexTypes) &&
00541                 array_key_exists($type, $this->complexTypes[$p])) {
00542                 if ($arrayType = $this->complexTypes[$p][$type]['arrayType']) {
00543                     $type = 'Array';
00544                 } else if ($this->complexTypes[$p][$type]['order']=='sequence' &&
00545                            array_key_exists('elements', $this->complexTypes[$p][$type])) {
00546                     reset($this->complexTypes[$p][$type]['elements']);
00547                     # assume an array
00548                     if (count($this->complexTypes[$p][$type]['elements']) == 1) {
00549                         $arg = current($this->complexTypes[$p][$type]['elements']);
00550                         $arrayType = $arg['type'];
00551                         $type = 'Array';
00552                     } else {
00553                         foreach($this->complexTypes[$p][$type]['elements'] as $element) {
00554                             if ($element['name'] == $type) {
00555                                 $arrayType = $element['type'];
00556                                 $type = $element['type'];
00557                             }
00558                         }
00559                     }
00560                 } else {
00561                     $type = 'Struct';
00562                 }
00563                 return array($type,$arrayType,$type_namespace);
00564             }
00565         }
00566         return array(NULL,NULL,NULL);
00567     }
00568     
00569     
00570 }
00571 
00572 class ilBMFWSDL_Cache extends ilBMFBase
00573 {
00574     function ilBMFWSDL_Cache() {
00575         parent::ilBMFBase('WSDLCACHE');
00576     }
00581     function _cacheDir() {
00582         $dir = getenv("WSDLCACHE");
00583         if (!$dir) $dir = "./wsdlcache";
00584         @mkdir($dir, 0700);
00585         return $dir;
00586     }
00587     
00593     function get($wsdl_fname, $proxy_params=array(), $cache=0) {
00594         $cachename = ilBMFWSDL_Cache::_cacheDir() . "/" . md5($wsdl_fname);
00595         $cacheinfo = $cachename.".info";
00596         $cachename .= ".wsdl";
00597         $md5_wsdl = "";
00598         $file_data = '';
00599         if (WSDL_CACHE_USE && file_exists($cachename)) {
00600             $wf = fopen($cachename,"rb");
00601             if ($wf) {
00602                 $file_data = fread($wf, filesize($cachename));
00603                 $md5_wsdl = md5($file_data);
00604                 fclose($wf);
00605             }
00606             if ($cache) {
00607                 if ($cache != $md5_wsdl) {
00608                     return $this->_raiseSoapFault("WSDL Checksum error!", $wsdl_fname);
00609                 }
00610             } else {
00611                 $fi = stat($cachename);
00612                 $cache_mtime = $fi[8];
00613                 #print cache_mtime, time()
00614                 if ($cache_mtime + WSDL_CACHE_MAX_AGE < time()) {
00615                     # expired
00616                     $md5_wsdl = ""; # refetch
00617                 }
00618             }
00619         }
00620         if (!$md5_wsdl) {
00621             // is it a local file?
00622             // this section should be replace by curl at some point
00623             if (!preg_match('/^(http|file):\/\//',$wsdl_fname)) {
00624                 if (!file_exists($wsdl_fname)) {
00625                     return $this->_raiseSoapFault("Unable to read local WSDL $wsdl_fname", $wsdl_fname);
00626                 }
00627                 if (function_exists('file_get_contents')) {
00628                     $file_data = file_get_contents($wsdl_fname);
00629                 } else {
00630                     $file_data = implode('',file($wsdl_fname));
00631                 }
00632             } else {
00633                 $uri = explode('?',$wsdl_fname);
00634                 $rq = new HTTP_Request($uri[0], $proxy_params);
00635                 // the user agent HTTP_Request uses fouls things up
00636                 if (isset($uri[1])) {
00637                     $rq->addRawQueryString($uri[1]);
00638                 }
00639                 $result = $rq->sendRequest();
00640                 if (PEAR::isError($result)) {
00641                     return $this->_raiseSoapFault("Unable to retrieve WSDL $wsdl_fname,".$rq->getResponseCode(), $wsdl_fname);
00642             }
00643                $file_data = $rq->getResponseBody();
00644                 if (!$file_data) {
00645                     return $this->_raiseSoapFault("Unable to retrieve WSDL $wsdl_fname, nohttp body", $wsdl_fname);
00646                 }
00647             }
00648             
00649             $md5_wsdl = md5($file_data);
00650             
00651             if (WSDL_CACHE_USE) {
00652                 $fp = fopen($cachename, "wb");
00653                 fwrite($fp, $file_data);
00654                 fclose($fp);
00655             }
00656         }
00657         if (WSDL_CACHE_USE && $cache && $cache != $md5_wsdl) {
00658             return $this->_raiseSoapFault("WSDL Checksum error!", $wsdl_fname);
00659         }
00660         return $file_data;
00661     }
00662     
00663 }
00664 
00665 class ilBMFWSDL_Parser extends ilBMFBase
00666 {
00667     // define internal arrays of bindings, ports, operations, messages, etc.
00668     var $currentMessage;
00669     var $currentOperation;
00670     var $currentPortType;
00671     var $currentBinding;
00672     var $currentPort;
00673     
00674     // parser vars
00675     var $cache;
00676 
00677     var $tns = NULL;
00678     var $soapns = array('soap');
00679     var $uri = '';
00680     var $wsdl = NULL;
00681 
00682     var $status = '';
00683     var $element_stack = array();
00684     var $parentElement = '';
00685 
00686     var $schema = '';
00687     var $schemaStatus = '';
00688     var $schema_stack = array();
00689     var $currentComplexType;
00690     var $schema_element_stack = array();
00691     var $currentElement;
00692     
00693     // constructor
00694     function ilBMFWSDL_Parser($uri, &$wsdl, $docs=false) {
00695         parent::ilBMFBase('WSDLPARSER');
00696         $this->cache = new ilBMFWSDL_Cache();
00697         $this->uri = $uri;
00698         $this->wsdl = &$wsdl;
00699         $this->docs = $docs;
00700         $this->parse($uri);
00701     }
00702     
00703     function parse($uri) {
00704         // Check whether content has been read.
00705         $fd = $this->cache->get($uri, $this->wsdl->proxy);
00706         if (PEAR::isError($fd)) {
00707             return $this->_raiseSoapFault($fd);
00708         }
00709 
00710         // Create an XML parser.
00711         $parser = xml_parser_create();
00712         xml_parser_set_option($parser, XML_OPTION_CASE_FOLDING, 0);
00713         xml_set_object($parser, $this);
00714         xml_set_element_handler($parser, 'startElement', 'endElement');
00715         if ($this->docs) xml_set_character_data_handler($parser, 'characterData');
00716     
00717         if (!xml_parse($parser,$fd, true)) {
00718             $detail = sprintf('XML error on line %d: %s',
00719                                     xml_get_current_line_number($parser),
00720                                     xml_error_string(xml_get_error_code($parser)));
00721             //print $fd;
00722             return $this->_raiseSoapFault("Unable to parse WSDL file $uri\n$detail");
00723         }
00724         xml_parser_free($parser);
00725         return TRUE;
00726     }
00727     
00728     // start-element handler
00729     function startElement($parser, $name, $attrs) {
00730         // get element prefix
00731         $qname = new QName($name);
00732         if ($qname->ns) {
00733             $ns = $qname->ns;
00734             if ($ns && ((!$this->tns && strcasecmp($qname->name,'definitions') == 0) || $ns == $this->tns)) {
00735                 $name = $qname->name;
00736             }
00737         }
00738         $this->currentTag = $qname->name;
00739         $this->parentElement = '';
00740         $stack_size = count($this->element_stack);
00741         if ($stack_size > 0) {
00742             $this->parentElement = $this->element_stack[$stack_size-1];
00743         }
00744         $this->element_stack[] = $this->currentTag;
00745         
00746         // find status, register data
00747         switch($this->status) {
00748         case 'types':
00749             // sect 2.2 wsdl:types
00750             // children: xsd:schema
00751             $parent_tag = '';
00752             $stack_size = count($this->schema_stack);
00753             if ($stack_size > 0) {
00754                 $parent_tag = $this->schema_stack[$stack_size-1];
00755             }
00756 
00757             switch($qname->name) {
00758             case 'schema':
00759                 // no parent should be in the stack
00760                 if (!$parent_tag || $parent_tag == 'types') {
00761                     if (array_key_exists('targetNamespace', $attrs)) {
00762                         $this->schema = $this->wsdl->getNamespaceAttributeName($attrs['targetNamespace']);
00763                     } else {
00764                         $this->schema = $this->wsdl->getNamespaceAttributeName($this->wsdl->tns);
00765                     }
00766                     $this->wsdl->complexTypes[$this->schema] = array();
00767                     $this->wsdl->elements[$this->schema] = array();
00768                 }
00769             break;
00770             case 'complexType':
00771                 if ($parent_tag == 'schema') {
00772                     $this->currentComplexType = $attrs['name'];
00773                     if (!isset($attrs['namespace'])) $attrs['namespace'] = $this->schema;
00774                     $this->wsdl->complexTypes[$this->schema][$this->currentComplexType] = $attrs;
00775                     if (array_key_exists('base',$attrs)) {
00776                         $qn = new QName($attrs['base']);
00777                         $this->wsdl->complexTypes[$this->schema][$this->currentComplexType]['type'] = $qn->name;
00778                         $this->wsdl->complexTypes[$this->schema][$this->currentComplexType]['namespace'] = $qn->ns;
00779                     } else {
00780                         $this->wsdl->complexTypes[$this->schema][$this->currentComplexType]['type'] = 'Struct';
00781                     }
00782                     $this->schemaStatus = 'complexType';
00783                 } else {
00784                     $this->wsdl->elements[$this->schema][$this->currentElement]['complex'] = TRUE;
00785                 }
00786             break;
00787             case 'element':
00788                 if (isset($attrs['type'])) {
00789                     $qn = new QName($attrs['type']);
00790                     $attrs['type'] = $qn->name;
00791                     #$this->wsdl->getNamespaceAttributeName
00792                     if ($qn->ns && array_key_exists($qn->ns, $this->wsdl->namespaces)) {
00793                         $attrs['namespace'] = $qn->ns;
00794                     }
00795                 }
00796                 
00797                 $parentElement = '';
00798                 $stack_size = count($this->schema_element_stack);
00799                 if ($stack_size > 0) {
00800                     $parentElement = $this->schema_element_stack[$stack_size-1];
00801                 }
00802 
00803                 if (isset($attrs['ref'])) {
00804                     $this->currentElement = $attrs['ref'];
00805                 } else {
00806                     $this->currentElement = $attrs['name'];
00807                 }
00808                 $this->schema_element_stack[] = $this->currentElement;
00809                 if (!isset($attrs['namespace'])) $attrs['namespace'] = $this->schema;
00810                 
00811                 if ($parent_tag == 'schema') {
00812                     $this->wsdl->elements[$this->schema][$this->currentElement] = $attrs;
00813                     $this->wsdl->elements[$this->schema][$this->currentElement]['complex'] = FALSE;
00814                     $this->schemaStatus = 'element';
00815                 } else if ($this->currentComplexType) {
00816                     // we're inside a complexType
00817                     if ($this->wsdl->complexTypes[$this->schema][$this->currentComplexType]['order'] == 'sequence'
00818                         && $this->wsdl->complexTypes[$this->schema][$this->currentComplexType]['type'] == 'Array') {
00819                             $this->wsdl->complexTypes[$this->schema][$this->currentComplexType]['arrayType'] = $attrs['type'];
00820                     }
00821                     $this->wsdl->complexTypes[$this->schema][$this->currentComplexType]['elements'][$this->currentElement] = $attrs;
00822                 } else {
00823                     $this->wsdl->elements[$this->schema][$parentElement]['elements'][$this->currentElement] = $attrs;
00824                 }
00825             break;
00826             case 'complexContent':
00827             case 'simpleContent':
00828             break;
00829             case 'extension':
00830             case 'restriction':
00831                 if ($this->schemaStatus == 'complexType') {
00832                     if ($attrs['base']) {
00833                         $qn = new QName($attrs['base']);
00834                         $this->wsdl->complexTypes[$this->schema][$this->currentComplexType]['type'] = $qn->name;
00835                         $this->wsdl->complexTypes[$this->schema][$this->currentComplexType]['namespace'] = $qn->ns;
00836                     } else {
00837                         $this->wsdl->complexTypes[$this->schema][$this->currentComplexType]['type'] = 'Struct';
00838                     }
00839                 }
00840             break;
00841             case 'sequence':
00842                 if ($this->schemaStatus == 'complexType') {
00843                     $this->wsdl->complexTypes[$this->schema][$this->currentComplexType]['order'] = 'sequence';
00844                     #if (!array_key_exists('type',$this->wsdl->complexTypes[$this->schema][$this->currentComplexType])) {
00845                         $this->wsdl->complexTypes[$this->schema][$this->currentComplexType]['type'] = 'Array';
00846                     #}
00847                 }
00848             break;
00849             case 'all':
00850                 $this->wsdl->complexTypes[$this->schema][$this->currentComplexType]['order'] = 'all';
00851                 if (!array_key_exists('type',$this->wsdl->complexTypes[$this->schema][$this->currentComplexType])) {
00852                     $this->wsdl->complexTypes[$this->schema][$this->currentComplexType]['type'] = 'Struct';
00853                 }
00854             break;
00855             case 'attribute':
00856                 if ($this->schemaStatus == 'complexType') {
00857                     if (isset($attrs['name'])) {
00858                         $this->wsdl->complexTypes[$this->schema][$this->currentComplexType]['attribute'][$attrs['name']] = $attrs;
00859                     } else
00860                     if (isset($attrs['ref'])) {
00861                         $q = new QName($attrs['ref']);
00862                         foreach ($attrs as $k => $v) {
00863                             if ($k != 'ref' && strstr($k, $q->name)) {
00864                                 $vq = new QName($v);
00865                                 if ($q->name == 'arrayType') {
00866                                     $this->wsdl->complexTypes[$this->schema][$this->currentComplexType][$q->name] = $vq->name.$vq->arrayInfo;
00867                                     $this->wsdl->complexTypes[$this->schema][$this->currentComplexType]['type'] = 'Array';
00868                                     $this->wsdl->complexTypes[$this->schema][$this->currentComplexType]['namespace'] = $vq->ns;
00869                                 } else {
00870                                     $this->wsdl->complexTypes[$this->schema][$this->currentComplexType][$q->name] = $vq->name;
00871                                 }
00872                             }
00873                         }
00874                     }
00875                 }
00876             break;
00877             }
00878             
00879             $this->schema_stack[] = $qname->name;
00880             
00881         break;
00882         case 'message':
00883             // sect 2.3 wsdl:message child wsdl:part
00884             switch($qname->name) {
00885             case 'part':
00886                 $qn = NULL;
00887                 if (isset($attrs['type'])) {
00888                     $qn = new QName($attrs['type']);
00889                 } else if (isset($attrs['element'])) {
00890                     $qn = new QName($attrs['element']);
00891                 }
00892                 if ($qn) {
00893                     $attrs['type'] = $qn->name;
00894                     $attrs['namespace'] = $qn->ns;
00895                 }
00896                 $this->wsdl->messages[$this->currentMessage][$attrs['name']] = $attrs;
00897                 // error in wsdl
00898             case 'documentation':
00899                 break;
00900             default:
00901                 break;
00902             }
00903         break;
00904         case 'portType':
00905             // sect 2.4
00906             switch($qname->name) {
00907             case 'operation':
00908                 // attributes: name
00909                 // children: wsdl:input wsdl:output wsdl:fault
00910                 $this->currentOperation = $attrs['name'];
00911                 #$this->wsdl->portTypes[$this->currentPortType][$this->currentOperation]['parameterOrder'] = $attrs['parameterOrder'];
00912                 $this->wsdl->portTypes[$this->currentPortType][$this->currentOperation] = $attrs;
00913                 break;
00914             case 'input':
00915             case 'output':
00916             case 'fault':
00917                 // wsdl:input wsdl:output wsdl:fault
00918                 // attributes: name message parameterOrder(optional)
00919                 if ($this->currentOperation) {
00920                     if (isset($this->wsdl->portTypes[$this->currentPortType][$this->currentOperation][$name])) {
00921                         $this->wsdl->portTypes[$this->currentPortType][$this->currentOperation][$name] = array_merge($this->wsdl->portTypes[$this->currentPortType][$this->currentOperation][$name],$attrs);
00922                     } else {
00923                         $this->wsdl->portTypes[$this->currentPortType][$this->currentOperation][$name] = $attrs;
00924                     }
00925                     if (array_key_exists('message',$attrs)) {
00926                         $qn = new QName($attrs['message']);
00927                         $this->wsdl->portTypes[$this->currentPortType][$this->currentOperation][$name]['message'] = $qn->name;
00928                         $this->wsdl->portTypes[$this->currentPortType][$this->currentOperation][$name]['namespace'] = $qn->ns;
00929                     }
00930                 }
00931                 break;
00932             case 'documentation':
00933                 break;
00934             default:
00935                 break;
00936             }
00937         break;
00938         case 'binding':
00939             $ns = $qname->ns?$this->wsdl->namespaces[strtolower($qname->ns)]:SCHEMA_WSDL;
00940             switch($ns) {
00941             case SCHEMA_SOAP:
00942                 // this deals with wsdl section 3 soap binding
00943                 switch($qname->name) {
00944                 case 'binding':
00945                     // sect 3.3
00946                     // soap:binding, attributes: transport(required), style(optional, default = document)
00947                     // if style is missing, it is assumed to be 'document'
00948                     if (!isset($attrs['style'])) $attrs['style'] = 'document'; 
00949                     $this->wsdl->bindings[$this->currentBinding] = array_merge($this->wsdl->bindings[$this->currentBinding],$attrs);
00950                     break;
00951                 case 'operation':
00952                     // sect 3.4
00953                     // soap:operation, attributes: soapAction(required), style(optional, default = soap:binding:style)
00954                     if (!isset($attrs['style'])) $attrs['style'] = $this->wsdl->bindings[$this->currentBinding]['style']; 
00955                     $this->wsdl->bindings[$this->currentBinding]['operations'][$this->currentOperation] = $attrs;
00956                     break;
00957                 case 'body':
00958                     // sect 3.5
00959                     // soap:body attributes:
00960                     // part - optional.  listed parts must appear in body, missing means all parts appear in body
00961                     // use - required. encoded|literal
00962                     // encodingStyle - optional.  space seperated list of encodings (uri's)
00963                     $this->wsdl->bindings[$this->currentBinding]
00964                                     ['operations'][$this->currentOperation][$this->opStatus] = $attrs;
00965                     break;
00966                 case 'fault':
00967                     // sect 3.6
00968                     // soap:fault attributes: name use  encodingStyle namespace
00969                     $this->wsdl->bindings[$this->currentBinding]
00970                                     ['operations'][$this->currentOperation][$this->opStatus] = $attrs;
00971                     break;
00972                 case 'header':
00973                     // sect 3.7
00974                     // soap:header attributes: message part use encodingStyle namespace
00975                     $this->wsdl->bindings[$this->currentBinding]
00976                                     ['operations'][$this->currentOperation][$this->opStatus]['headers'][] = $attrs;
00977                     break;
00978                 case 'headerfault':
00979                     // sect 3.7
00980                     // soap:header attributes: message part use encodingStyle namespace
00981                     $header = count($this->wsdl->bindings[$this->currentBinding]
00982                                     ['operations'][$this->currentOperation][$this->opStatus]['headers'])-1;
00983                     $this->wsdl->bindings[$this->currentBinding]
00984                                     ['operations'][$this->currentOperation][$this->opStatus]['headers'][$header]['fault'] = $attrs;
00985                     break;
00986                 case 'documentation':
00987                     break;
00988                 default:
00989                     // error!  not a valid element inside binding
00990                     break;
00991                 }
00992                 break;
00993             case SCHEMA_WSDL:
00994                 // XXX verify correct namespace
00995                 // for now, default is the 'wsdl' namespace
00996                 // other possible namespaces include smtp, http, etc. for alternate bindings
00997                 switch($qname->name) {
00998                 case 'operation':
00999                     // sect 2.5
01000                     // wsdl:operation attributes: name
01001                     $this->currentOperation = $attrs['name'];
01002                     break;            
01003                 case 'output':
01004                 case 'input':
01005                 case 'fault':
01006                     // sect 2.5
01007                     // wsdl:input attributes: name
01008                     $this->opStatus = $qname->name;
01009                     break;
01010                 case 'documentation':
01011                     break;
01012                 default:
01013                     break;                    
01014                 }
01015                 break;
01016             case SCHEMA_HTTP:
01017                 switch($qname->name) {
01018                 case 'binding':
01019                     // sect 4.4
01020                     // http:binding attributes: verb
01021                     // parent: wsdl:binding
01022                     $this->wsdl->bindings[$this->currentBinding] = array_merge($this->wsdl->bindings[$this->currentBinding],$attrs);
01023                     break;
01024                 case 'operation':
01025                     // sect 4.5
01026                     // http:operation attributes: location
01027                     // parent: wsdl:operation
01028                     $this->wsdl->bindings[$this->currentBinding]['operations']
01029                                                         [$this->currentOperation] = $attrs;
01030                     break;
01031                 case 'urlEncoded':
01032                     // sect 4.6
01033                     // http:urlEncoded attributes: location
01034                     // parent: wsdl:input wsdl:output etc.
01035                     $this->wsdl->bindings[$this->currentBinding]['operations'][$this->opStatus]
01036                                                         [$this->currentOperation]['uri'] = 'urlEncoded';
01037                     break;
01038                 case 'urlReplacement':
01039                     // sect 4.7
01040                     // http:urlReplacement attributes: location
01041                     // parent: wsdl:input wsdl:output etc.
01042                     $this->wsdl->bindings[$this->currentBinding]['operations'][$this->opStatus]
01043                                                         [$this->currentOperation]['uri'] = 'urlReplacement';
01044                     break;
01045                 case 'documentation':
01046                     break;
01047                 default:
01048                     // error
01049                     break;
01050                 }
01051             case SCHEMA_MIME:
01052                 // sect 5
01053                 // all mime parts are children of wsdl:input, wsdl:output, etc.
01054                 // unsuported as of yet
01055                 switch($qname->name) {
01056                 case 'content':
01057                     // sect 5.3 mime:content
01058                     // <mime:content part="nmtoken"? type="string"?/>
01059                     // part attribute only required if content is child of multipart related,
01060                     //        it contains the name of the part
01061                     // type attribute contains the mime type
01062                 case 'multipartRelated':
01063                     // sect 5.4 mime:multipartRelated
01064                 case 'part':
01065                 case 'mimeXml':
01066                     // sect 5.6 mime:mimeXml
01067                     // <mime:mimeXml part="nmtoken"?/>
01068                     // 
01069                 case 'documentation':
01070                     break;
01071                 default:
01072                     // error
01073                     break;
01074                 }
01075             case SCHEMA_DIME:
01076                 // DIME is defined in:
01077                 // http://gotdotnet.com/team/xml_wsspecs/dime/WSDL-Extension-for-DIME.htm
01078                 // all DIME parts are children of wsdl:input, wsdl:output, etc.
01079                 // unsuported as of yet
01080                 switch($qname->name) {
01081                 case 'message':
01082                     // sect 4.1 dime:message
01083                     // appears in binding section
01084                     $this->wsdl->bindings[$this->currentBinding]['dime'] = $attrs;
01085                     break;
01086                 default:
01087                     break;
01088                 }
01089             default:
01090                 break;
01091             }
01092         break;
01093         case 'service':
01094             $ns = $qname->ns?$this->wsdl->namespaces[strtolower($qname->ns)]:SCHEMA_WSDL;
01095             
01096             switch($qname->name) {
01097             case 'port':
01098                 // sect 2.6 wsdl:port attributes: name binding
01099                 $this->currentPort = $attrs['name'];
01100                 $this->wsdl->services[$this->currentService]['ports'][$this->currentPort] = $attrs;
01101                 // XXX hack to deal with binding namespaces
01102                 $qn = new QName($attrs['binding']);
01103                 $this->wsdl->services[$this->currentService]['ports'][$this->currentPort]['binding'] = $qn->name;
01104                 $this->wsdl->services[$this->currentService]['ports'][$this->currentPort]['namespace'] = $qn->ns;
01105             break;
01106             case 'address':
01107                 $this->wsdl->services[$this->currentService]['ports'][$this->currentPort]['address'] = $attrs;
01108                 // what TYPE of port is it?  SOAP or HTTP?
01109                 $ns = $qname->ns?$this->wsdl->namespaces[strtolower($qname->ns)]:SCHEMA_WSDL;
01110                 switch($ns) {
01111                 case SCHEMA_HTTP:
01112                     $this->wsdl->services[$this->currentService]['ports'][$this->currentPort]['type']='http';
01113                     break;
01114                 case SCHEMA_SOAP:
01115                     $this->wsdl->services[$this->currentService]['ports'][$this->currentPort]['type']='soap';
01116                     break;
01117                 default:
01118                     // shouldn't happen, we'll assume soap
01119                     $this->wsdl->services[$this->currentService]['ports'][$this->currentPort]['type']='soap';
01120                 }
01121                 
01122             break;
01123             case 'documentation':
01124                 break;
01125             default:
01126                 break;
01127             }
01128         }
01129         
01130         // top level elements found under wsdl:definitions
01131         // set status
01132         switch($qname->name) {
01133         case 'import':
01134             // sect 2.1.1 wsdl:import attributes: namespace location
01135             if (array_key_exists('location',$attrs)) {
01136                 $uri = $attrs['location'];
01137                 $location = parse_url($uri);
01138                 if (!isset($location['scheme'])) {
01139                     $base = parse_url($this->uri);
01140                     $uri = $this->merge_url($base,$uri);
01141                 }
01142                 $import_parser = new ilBMFWSDL_Parser($uri, $this->wsdl);
01143                 if ($import_parser->fault) {
01144                     return FALSE;
01145                 }
01146                 $this->currentImport = $attrs['namespace'];
01147                 $this->wsdl->imports[$this->currentImport] = $attrs;
01148             }
01149             $this->status = '';
01150         case 'types':
01151             // sect 2.2 wsdl:types
01152             $this->status = 'types';
01153         break;
01154         case 'message':
01155             // sect 2.3 wsdl:message attributes: name children:wsdl:part
01156             $this->status = 'message';
01157             if (isset($attrs['name'])) {
01158                 $this->currentMessage = $attrs['name'];
01159                 $this->wsdl->messages[$this->currentMessage] = array();
01160             }
01161         break;
01162         case 'portType':
01163             // sect 2.4 wsdl:portType
01164             // attributes: name
01165             // children: wsdl:operation
01166             $this->status = 'portType';
01167             $this->currentPortType = $attrs['name'];
01168             $this->wsdl->portTypes[$this->currentPortType] = array();
01169         break;
01170         case 'binding':
01171             // sect 2.5 wsdl:binding attributes: name type
01172             // children: wsdl:operation soap:binding http:binding
01173             if ($qname->ns && $qname->ns != $this->tns) break;
01174             $this->status = 'binding';
01175             $this->currentBinding = $attrs['name'];
01176             $qn = new QName($attrs['type']);
01177             $this->wsdl->bindings[$this->currentBinding]['type'] = $qn->name;
01178             $this->wsdl->bindings[$this->currentBinding]['namespace'] = $qn->ns;
01179         break;
01180         case 'service':
01181             // sect 2.7 wsdl:service attributes: name children: ports
01182             $this->currentService = $attrs['name'];
01183             $this->wsdl->services[$this->currentService]['ports'] = array();
01184             $this->status = 'service';
01185         break;
01186         case 'definitions':
01187             // sec 2.1 wsdl:definitions
01188             // attributes: name targetNamespace xmlns:*
01189             // children: wsdl:import wsdl:types wsdl:message wsdl:portType wsdl:binding wsdl:service
01190             #$this->status = 'definitions';
01191             $this->wsdl->definition = $attrs;
01192             foreach ($attrs as $key => $value) {
01193                 if (strstr($key,'xmlns:') !== FALSE) {
01194                     $qn = new QName($key);
01195                     // XXX need to refactor ns handling
01196                     $this->wsdl->namespaces[strtolower($qn->name)] = $value;
01197                     $this->wsdl->ns[$value] = $qn->name;
01198                     if ($key == 'targetNamespace' ||
01199                         strcasecmp($value,SOAP_SCHEMA)==0) {
01200                         $this->soapns[] = strtolower($qn->name);
01201                     } else
01202                     if (in_array($value, $this->_XMLSchema)) {
01203                         $this->wsdl->xsd = $value;
01204                     }
01205                 }
01206             }
01207             if (isset($ns) && $ns) {
01208                 $namespace = 'xmlns:'.$ns;
01209                 if (!$this->wsdl->definition[$namespace]) {
01210                     return $this->_raiseSoapFault("parse error, no namespace for $namespace",$this->uri);
01211                 }
01212                 $this->tns = $ns;
01213             }
01214         break;
01215         }
01216     }
01217     
01218     
01219     // end-element handler
01220     function endElement($parser, $name)
01221     {
01222         $stacksize = count($this->element_stack);
01223         if ($stacksize > 0) {
01224             if ($this->element_stack[count($this->element_stack)-1] ==  'definitions') {
01225                 $this->status = '';
01226             }
01227             array_pop($this->element_stack);
01228         }
01229         if (stristr($name,'schema')) {
01230             array_pop($this->schema_stack);
01231             $this->schema = '';
01232         }
01233         if ($this->schema) {
01234             array_pop($this->schema_stack);
01235             if (count($this->schema_stack) <= 1) {
01236                 /* correct the type for sequences with multiple elements */
01237                 if (isset($this->currentComplexType) && isset($this->wsdl->complexTypes[$this->schema][$this->currentComplexType]['type'])
01238                     && $this->wsdl->complexTypes[$this->schema][$this->currentComplexType]['type'] == 'Array'
01239                     && array_key_exists('elements',$this->wsdl->complexTypes[$this->schema][$this->currentComplexType])
01240                     && count($this->wsdl->complexTypes[$this->schema][$this->currentComplexType]['elements']) > 1) {
01241                         $this->wsdl->complexTypes[$this->schema][$this->currentComplexType]['type'] = 'Struct';
01242                 }
01243             }
01244             if (stristr($name,'complexType')) {
01245                 $this->currentComplexType = '';
01246                 if (count($this->schema_element_stack) > 0)
01247                     $this->currentElement = array_pop($this->schema_element_stack);
01248                 else
01249                     $this->currentElement = '';
01250             } else if (stristr($name,'element')) {
01251                 if (count($this->schema_element_stack) > 0)
01252                     $this->currentElement = array_pop($this->schema_element_stack);
01253                 else
01254                     $this->currentElement = '';
01255             }
01256         }
01257         // position of current element is equal to the last value left in depth_array for my depth
01258         //$pos = $this->depth_array[$this->depth];
01259         // bring depth down a notch
01260         //$this->depth--;
01261     }
01262     
01263     // element content handler
01264     function characterData($parser, $data)
01265     {
01266         # store the documentation in the WSDL file
01267         if ($this->currentTag == 'documentation') {
01268             if ($this->status ==  'service') {
01269                 $this->wsdl->services[$this->currentService][$this->currentTag] .= $data;
01270             } else if ($this->status ==  'portType') {
01271                 if ($this->wsdl->portTypes[$this->currentPortType][$this->currentOperation][$this->currentTag])
01272                     $this->wsdl->portTypes[$this->currentPortType][$this->currentOperation][$this->currentTag] .= data;
01273                 else
01274                     $this->wsdl->portTypes[$this->currentPortType][$this->currentOperation][$this->currentTag] = data;
01275             } else if ($this->status ==  'binding') {
01276                 if ($this->wsdl->bindings[$this->currentBinding][$this->currentTag])
01277                     $this->wsdl->bindings[$this->currentBinding][$this->currentTag] .= data;
01278                 else
01279                     $this->wsdl->bindings[$this->currentBinding][$this->currentTag] = data;
01280             } else if ($this->status ==  'message') {
01281                 if ($this->wsdl->messages[$this->currentMessage][$this->currentTag])
01282                     $this->wsdl->messages[$this->currentMessage][$this->currentTag] .= data;
01283                 else
01284                     $this->wsdl->messages[$this->currentMessage][$this->currentTag] = data;
01285             } else if ($this->status ==  'operation') {
01286                 if ($this->wsdl->portTypes[$this->currentPortType][$this->currentOperation][$this->currentTag])
01287                     $this->wsdl->portTypes[$this->currentPortType][$this->currentOperation][$this->currentTag] .= data;
01288                 else
01289                     $this->wsdl->portTypes[$this->currentPortType][$this->currentOperation][$this->currentTag] = data;
01290             }
01291         }
01292     }
01293 
01294 
01295     // $parsed is a parse_url() resulting array
01296     function merge_url($parsed,$path) { 
01297        
01298         if (! is_array($parsed)) return false;
01299 
01300         if (isset($parsed['scheme'])) {
01301             $sep = (strtolower($parsed['scheme']) == 'mailto' ? ':' : '://');
01302             $uri = $parsed['scheme'] . $sep;
01303         } else {
01304             $uri = '';
01305         }
01306 
01307         if (isset($parsed['pass'])) {
01308             $uri .= "$parsed[user]:$parsed[pass]@";
01309         } elseif (isset($parsed['user'])) {
01310             $uri .= "$parsed[user]@";
01311         }
01312 
01313         if (isset($parsed['host']))     $uri .= $parsed['host'];
01314         if (isset($parsed['port']))     $uri .= ":$parsed[port]";
01315         if ($path[0]!='/' && isset($parsed['path'])) {
01316             if ($parsed['path'][strlen($parsed['path'])-1] != '/') {
01317                 $path = dirname($parsed['path']).'/'.$path;
01318             } else {
01319                 $path = $parsed['path'].$path;
01320             }
01321             $path = $this->_normalize($path);
01322         }
01323         $sep = $path[0]=='/'?'':'/';
01324         $uri .= $sep.$path;
01325 
01326         return $uri; 
01327     }
01328     
01329     function _normalize($path_str){
01330         $pwd='';
01331         $strArr=preg_split("/(\/)/",$path_str,-1,PREG_SPLIT_NO_EMPTY);
01332         $pwdArr="";
01333         $j=0;
01334         for($i=0;$i<count($strArr);$i++){
01335             if($strArr[$i]!=".."){
01336                 if($strArr[$i]!="."){
01337                 $pwdArr[$j]=$strArr[$i];
01338                 $j++;
01339                 }
01340             }else{
01341                 array_pop($pwdArr);
01342                 $j--;
01343             }
01344         }
01345         $pStr=implode("/",$pwdArr);
01346         $pwd=(strlen($pStr)>0) ? ("/".$pStr) : "/";
01347         return $pwd;
01348     }    
01349 }
01350 
01351 ?>

Generated on Fri Dec 13 2013 09:06:37 for ILIAS Release_3_4_x_branch .rev 46804 by  doxygen 1.7.1