00001 <?php
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
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);
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
00115
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
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
00141 if (is_array($this->bindings[$binding]['operations'][$operation])) {
00142 $opData = $this->bindings[$binding]['operations'][$operation];
00143 }
00144
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
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
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
00234 if (!array_key_exists($namespace, $this->ns)) {
00235 $this->ns = array_flip($this->namespaces);
00236 }
00237
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
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
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
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
00351 $primaryBinding = $port['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
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
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
00392 }
00393 if (isset($el['elements'])) {
00394 foreach ($el['elements'] as $elname => $elattrs) {
00395
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 }
00403
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
00413 $comments = $this->_elementArg($args, $argarray, $_argtype, $_argtype['type']);
00414 } else {
00415
00416 $comments = $this->_complexTypeArg($args, $argarray, $_argtype, $_argname);
00417 }
00418 }
00419 }
00420 }
00421
00422
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
00501 $t = $this->_getComplexTypeForElement($name, $ns);
00502 if ($t) {
00503
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
00622
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
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
00668 var $currentMessage;
00669 var $currentOperation;
00670 var $currentPortType;
00671 var $currentBinding;
00672 var $currentPort;
00673
00674
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
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
00705 $fd = $this->cache->get($uri, $this->wsdl->proxy);
00706 if (PEAR::isError($fd)) {
00707 return $this->_raiseSoapFault($fd);
00708 }
00709
00710
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
00722 return $this->_raiseSoapFault("Unable to parse WSDL file $uri\n$detail");
00723 }
00724 xml_parser_free($parser);
00725 return TRUE;
00726 }
00727
00728
00729 function startElement($parser, $name, $attrs) {
00730
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
00747 switch($this->status) {
00748 case 'types':
00749
00750
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
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
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
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
00898 case 'documentation':
00899 break;
00900 default:
00901 break;
00902 }
00903 break;
00904 case 'portType':
00905
00906 switch($qname->name) {
00907 case 'operation':
00908
00909
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
00918
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
00943 switch($qname->name) {
00944 case 'binding':
00945
00946
00947
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
00953
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
00959
00960
00961
00962
00963 $this->wsdl->bindings[$this->currentBinding]
00964 ['operations'][$this->currentOperation][$this->opStatus] = $attrs;
00965 break;
00966 case 'fault':
00967
00968
00969 $this->wsdl->bindings[$this->currentBinding]
00970 ['operations'][$this->currentOperation][$this->opStatus] = $attrs;
00971 break;
00972 case 'header':
00973
00974
00975 $this->wsdl->bindings[$this->currentBinding]
00976 ['operations'][$this->currentOperation][$this->opStatus]['headers'][] = $attrs;
00977 break;
00978 case 'headerfault':
00979
00980
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
00990 break;
00991 }
00992 break;
00993 case SCHEMA_WSDL:
00994
00995
00996
00997 switch($qname->name) {
00998 case 'operation':
00999
01000
01001 $this->currentOperation = $attrs['name'];
01002 break;
01003 case 'output':
01004 case 'input':
01005 case 'fault':
01006
01007
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
01020
01021
01022 $this->wsdl->bindings[$this->currentBinding] = array_merge($this->wsdl->bindings[$this->currentBinding],$attrs);
01023 break;
01024 case 'operation':
01025
01026
01027
01028 $this->wsdl->bindings[$this->currentBinding]['operations']
01029 [$this->currentOperation] = $attrs;
01030 break;
01031 case 'urlEncoded':
01032
01033
01034
01035 $this->wsdl->bindings[$this->currentBinding]['operations'][$this->opStatus]
01036 [$this->currentOperation]['uri'] = 'urlEncoded';
01037 break;
01038 case 'urlReplacement':
01039
01040
01041
01042 $this->wsdl->bindings[$this->currentBinding]['operations'][$this->opStatus]
01043 [$this->currentOperation]['uri'] = 'urlReplacement';
01044 break;
01045 case 'documentation':
01046 break;
01047 default:
01048
01049 break;
01050 }
01051 case SCHEMA_MIME:
01052
01053
01054
01055 switch($qname->name) {
01056 case 'content':
01057
01058
01059
01060
01061
01062 case 'multipartRelated':
01063
01064 case 'part':
01065 case 'mimeXml':
01066
01067
01068
01069 case 'documentation':
01070 break;
01071 default:
01072
01073 break;
01074 }
01075 case SCHEMA_DIME:
01076
01077
01078
01079
01080 switch($qname->name) {
01081 case 'message':
01082
01083
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
01099 $this->currentPort = $attrs['name'];
01100 $this->wsdl->services[$this->currentService]['ports'][$this->currentPort] = $attrs;
01101
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
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
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
01131
01132 switch($qname->name) {
01133 case 'import':
01134
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
01152 $this->status = 'types';
01153 break;
01154 case 'message':
01155
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
01164
01165
01166 $this->status = 'portType';
01167 $this->currentPortType = $attrs['name'];
01168 $this->wsdl->portTypes[$this->currentPortType] = array();
01169 break;
01170 case 'binding':
01171
01172
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
01182 $this->currentService = $attrs['name'];
01183 $this->wsdl->services[$this->currentService]['ports'] = array();
01184 $this->status = 'service';
01185 break;
01186 case 'definitions':
01187
01188
01189
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
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
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
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
01258
01259
01260
01261 }
01262
01263
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
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 ?>