1<?php
2//
3// +----------------------------------------------------------------------+
4// | PHP Version 4                                                        |
5// +----------------------------------------------------------------------+
6// | Copyright (c) 1997-2003 The PHP Group                                |
7// +----------------------------------------------------------------------+
8// | This source file is subject to version 2.02 of the PHP license,      |
9// | that is bundled with this package in the file LICENSE, and is        |
10// | available through the world-wide-web at                              |
11// | http://www.php.net/license/2_02.txt.                                 |
12// | If you did not receive a copy of the PHP license and are unable to   |
13// | obtain it through the world-wide-web, please send a note to          |
14// | license@php.net so we can mail you a copy immediately.               |
15// +----------------------------------------------------------------------+
16// | Authors: Shane Caraveo <Shane@Caraveo.com>                           |
17// +----------------------------------------------------------------------+
18//
19// $Id$
20//
21require_once 'DB.php'; // PEAR/DB
22require_once 'client_round2_params.php';
23require_once 'test.utility.php';
24require_once 'config.php';
25
26error_reporting(E_ALL ^ E_NOTICE);
27
28class Interop_Client
29{
30    // database DNS
31    var $DSN = "";
32
33    var $baseURL = "";
34
35    // our central interop server, where we can get the list of endpoints
36    var $interopServer = "http://www.whitemesa.net/wsdl/interopInfo.wsdl";
37
38    // our local endpoint, will always get added to the database for all tests
39    var $localEndpoint;
40
41    // specify testing
42    var $currentTest = 'base';      // see $tests above
43    var $paramType = 'php';     // 'php' or 'soapval'
44    var $useWSDL = 0;           // 1= do wsdl tests
45    var $numServers = 0;        // 0 = all
46    var $specificEndpoint = ''; // test only this endpoint
47    var $testMethod = '';       // test only this method
48    var $skipEndpointList = array(); // endpoints to skip
49    var $nosave = 0;
50    var $startAt = ''; // start in list at this endpoint
51    // debug output
52    var $show = 1;
53    var $debug = 0;
54    var $showFaults = 0; // used in result table output
55
56    // PRIVATE VARIABLES
57    var $dbc = NULL;
58    var $totals = array();
59    var $tests = array('base','GroupB', 'GroupC');
60    var $paramTypes = array('php', 'soapval');
61    var $endpoints = array();
62    var $html = 1;
63
64    function Interop_Client() {
65        global $interopConfig;
66        $this->DSN = $interopConfig['DSN'];
67        $this->baseURL = $interopConfig['baseURL'];
68        //$this->baseURL = 'http://'.$_SERVER['HTTP_HOST'].dirname($_SERVER['PHP_SELF']);
69        // set up the database connection
70        $this->dbc = DB::connect($this->DSN, true);
71        // if it errors out, just ignore it and rely on regular methods
72        if (DB::isError($this->dbc)) {
73            echo $this->dbc->getMessage();
74            $this->dbc = NULL;
75        }
76        // set up local endpoint
77        $this->localEndpoint['base'] = (object)array(
78                                'endpointName'=>'PHP ext/soap',
79                                'endpointURL'=>$this->baseURL.'/server_round2_base.php',
80                                'wsdlURL'=>$this->baseURL.'/interop.wsdl.php'
81                              );
82        $this->localEndpoint['GroupB'] = (object)array(
83                                'endpointName'=>'PHP ext/soap',
84                                'endpointURL'=>$this->baseURL.'/server_round2_groupB.php',
85                                'wsdlURL'=>$this->baseURL.'/interopB.wsdl.php'
86                              );
87        $this->localEndpoint['GroupC'] = (object)array(
88                                'endpointName'=>'PHP ext/soap',
89                                'endpointURL'=>$this->baseURL.'/server_round2_groupC.php',
90                                'wsdlURL'=>$this->baseURL.'/echoheadersvc.wsdl.php');
91    }
92
93    function _fetchEndpoints(&$soapclient, $test) {
94        $this->_getEndpoints($test, 1);
95
96        // retrieve endpoints from the endpoint server
97        $endpointArray = $soapclient->__soapCall("GetEndpointInfo",array("groupName"=>$test),array('soapaction'=>"http://soapinterop.org/",'uri'=>"http://soapinterop.org/"));
98        if (is_soap_fault($endpointArray) || PEAR::isError($endpointArray)) {
99            if ($this->html) print "<pre>";
100            print $soapclient->wire."\n";
101            print_r($endpointArray);
102            if ($this->html) print "</pre>";
103            print "\n";
104            return;
105        }
106
107        // add our local endpoint
108        if ($this->localEndpoint[$test]) {
109          array_push($endpointArray, $this->localEndpoint[$test]);
110        }
111
112        if (!$endpointArray) return;
113
114        // reset the status to zero
115        $res = $this->dbc->query("update endpoints set status = 0 where class='$test'");
116        if (DB::isError($res)) {
117            die ($res->getMessage());
118        }
119        if (is_object($res)) $res->free();
120        // save new endpoints into database
121        foreach($endpointArray as $k => $v){
122            if (array_key_exists($v->endpointName,$this->endpoints)) {
123                $res = $this->dbc->query("update endpoints set endpointURL='{$v->endpointURL}', wsdlURL='{$v->wsdlURL}', status=1 where id={$this->endpoints[$v->endpointName]['id']}");
124            } else {
125                $res = $this->dbc->query("insert into endpoints (endpointName,endpointURL,wsdlURL,class) values('{$v->endpointName}','{$v->endpointURL}','{$v->wsdlURL}','$test')");
126            }
127            if (DB::isError($res)) {
128                die ($res->getMessage());
129            }
130            if (is_object($res)) $res->free();
131        }
132    }
133
134    /**
135    *  fetchEndpoints
136    * retrieve endpoints interop server
137    *
138    * @return boolean result
139    * @access private
140    */
141    function fetchEndpoints($test = NULL) {
142        // fetch from the interop server
143        try {
144            $soapclient = new SoapClient($this->interopServer);
145            if ($test) {
146                $this->_fetchEndpoints($soapclient, $test);
147            } else {
148                foreach ($this->tests as $test) {
149                    $this->_fetchEndpoints($soapclient, $test);
150                }
151                $test = 'base';
152            }
153        } catch (SoapFault $fault) {
154            if ($this->html) {
155                echo "<pre>$fault</pre>\n";
156            } else {
157                echo "$fault\n";
158            }
159            return NULL;
160        }
161        // retrieve all endpoints now
162        $this->currentTest = $test;
163        $x = $this->_getEndpoints($test);
164        return $x;
165    }
166
167    /**
168    *  getEndpoints
169    * retrieve endpoints from either database or interop server
170    *
171    * @param string base (see local var $tests)
172    * @param boolean all (if false, only get valid endpoints, status=1)
173    * @return boolean result
174    * @access private
175    */
176    function getEndpoints($base = 'base', $all = 0) {
177        if (!$this->_getEndpoints($base, $all)) {
178            return $this->fetchEndpoints($base);
179        }
180        return TRUE;
181    }
182
183    /**
184    *  _getEndpoints
185    * retrieve endpoints from database
186    *
187    * @param string base (see local var $tests)
188    * @param boolean all (if false, only get valid endpoints, status=1)
189    * @return boolean result
190    * @access private
191    */
192    function _getEndpoints($base = "", $all = 0) {
193        $this->endpoints = array();
194
195        // build sql
196        $sql = "select * from endpoints ";
197        if ($base) {
198            $sql .= "where class='$base' ";
199            if (!$all) $sql .= "and status=1";
200        } else
201        if (!$all) $sql .= "where status=1";
202        $sql .= " order by endpointName";
203
204
205        $db_ep = $this->dbc->getAll($sql,NULL, DB_FETCHMODE_ASSOC );
206        if (DB::isError($db_ep)) {
207            echo $sql."\n";
208            echo $db_ep->getMessage();
209            return FALSE;
210        }
211        // rearange the array
212        foreach ($db_ep as $entry) {
213            $this->endpoints[$entry['endpointName']] = $entry;
214        }
215
216        if (count($this->endpoints) > 0) {
217            $this->currentTest = $base;
218            return TRUE;
219        }
220        return FALSE;
221    }
222
223    /**
224    *  getResults
225    * retrieve results from the database, stuff them into the endpoint array
226    *
227    * @access private
228    */
229    function getResults($test = 'base', $type = 'php', $wsdl = 0) {
230        // be sure we have the right endpoints for this test result
231        $this->getEndpoints($test);
232
233        // retrieve the results and put them into the endpoint info
234        $sql = "select * from results where class='$test' and type='$type' and wsdl=$wsdl";
235        $results = $this->dbc->getAll($sql,NULL, DB_FETCHMODE_ASSOC );
236        foreach ($results as $result) {
237            // find the endpoint
238            foreach ($this->endpoints as $epn => $epi) {
239                if ($epi['id'] == $result['endpoint']) {
240                    // store the info
241                    $this->endpoints[$epn]['methods'][$result['function']] = $result;
242                    break;
243                }
244            }
245        }
246    }
247
248    /**
249    *  saveResults
250    * save the results of a method test into the database
251    *
252    * @access private
253    */
254    function _saveResults($endpoint_id, &$soap_test) {
255        if ($this->nosave) return;
256
257        $result = $soap_test->result;
258        $wire = $result['wire'];
259        if ($result['success']) {
260            $success = 'OK';
261            $error = '';
262        } else {
263            $success = $result['fault']->faultcode;
264            $pos = strpos($success,':');
265            if ($pos !== false) {
266              $success = substr($success,$pos+1);
267            }
268            $error = $result['fault']->faultstring;
269            if (!$wire) $wire= $result['fault']->detail;
270        }
271
272        $test_name = $soap_test->test_name;
273
274        $sql = "delete from results where endpoint=$endpoint_id ".
275                    "and class='$this->currentTest' and type='$this->paramType' ".
276                    "and wsdl=$this->useWSDL and function=".
277                    $this->dbc->quote($test_name);
278        #echo "\n".$sql;
279        $res = $this->dbc->query($sql);
280        if (DB::isError($res)) {
281            die ($res->getMessage());
282        }
283        if (is_object($res)) $res->free();
284
285        $sql = "insert into results (endpoint,stamp,class,type,wsdl,function,result,error,wire) ".
286                    "values($endpoint_id,".time().",'$this->currentTest',".
287                    "'$this->paramType',$this->useWSDL,".
288                    $this->dbc->quote($test_name).",".
289                    $this->dbc->quote($success).",".
290                    $this->dbc->quote($error).",".
291                    ($wire?$this->dbc->quote($wire):"''").")";
292        #echo "\n".$sql;
293        $res = $this->dbc->query($sql);
294
295        if (DB::isError($res)) {
296            die ($res->getMessage());
297        }
298        if (is_object($res)) $res->free();
299    }
300
301    /**
302    *  decodeSoapval
303    * decodes a soap value to php type, used for test result comparisons
304    *
305    * @param SOAP_Value soapval
306    * @return mixed result
307    * @access public
308    */
309    function decodeSoapval($soapval)
310    {
311        if (gettype($soapval) == "object" &&
312            (strcasecmp(get_class($soapval),"SoapParam") == 0 ||
313             strcasecmp(get_class($soapval),"SoapVar") == 0)) {
314                if (strcasecmp(get_class($soapval),"SoapParam") == 0)
315                    $val = $soapval->param_data->enc_value;
316                else
317                    $val = $soapval->enc_value;
318        } else {
319            $val = $soapval;
320        }
321        if (is_array($val)) {
322            foreach($val as $k => $v) {
323                if (gettype($v) == "object" &&
324                    (strcasecmp(get_class($soapval),"SoapParam") == 0 ||
325                    strcasecmp(get_class($soapval),"SoapVar") == 0)) {
326                    $val[$k] = $this->decodeSoapval($v);
327                }
328            }
329        }
330        return $val;
331    }
332
333    /**
334    *  compareResult
335    * compare two php types for a match
336    *
337    * @param string expect
338    * @param string test_result
339    * @return boolean result
340    * @access public
341    */
342    function compareResult($expect, $result, $type = NULL)
343    {
344      return compare($expect, $result);
345    }
346
347
348    /**
349    *  doEndpointMethod
350    *  run a method on an endpoint and store it's results to the database
351    *
352    * @param array endpoint_info
353    * @param SOAP_Test test
354    * @return boolean result
355    * @access public
356    */
357    function doEndpointMethod(&$endpoint_info, &$soap_test) {
358        $ok = FALSE;
359
360        // prepare a holder for the test results
361        $soap_test->result['class'] = $this->currentTest;
362        $soap_test->result['type'] = $this->paramType;
363        $soap_test->result['wsdl'] = $this->useWSDL;
364
365        if ($this->useWSDL) {
366            if (array_key_exists('wsdlURL',$endpoint_info)) {
367                if (!array_key_exists('client',$endpoint_info)) {
368                    try {
369                        $endpoint_info['client'] = new SoapClient($endpoint_info['wsdlURL'], array("trace"=>1));
370                    } catch (SoapFault $ex) {
371                        $endpoint_info['client']->wsdl->fault = $ex;
372                    }
373                }
374                $soap =& $endpoint_info['client'];
375
376                # XXX how do we determine a failure on retrieving/parsing wsdl?
377                if ($soap->wsdl->fault) {
378                    $fault = $soap->wsdl->fault;
379                    $soap_test->setResult(0,'WSDL',
380                                          $fault->faultstring."\n\n".$fault->detail,
381                                          $fault->faultstring,
382                                          $fault
383                                          );
384                    return FALSE;
385                }
386            } else {
387                $fault = new SoapFault('WSDL',"no WSDL defined for $endpoint");
388                $soap_test->setResult(0,'WSDL',
389                                      $fault->faultstring,
390                                      $fault->faultstring,
391                                      $fault
392                                      );
393                return FALSE;
394            }
395            $namespace = false;
396            $soapaction = false;
397        } else {
398            $namespace = $soapaction = 'http://soapinterop.org/';
399            // hack to make tests work with MS SoapToolkit
400            // it's the only one that uses this soapaction, and breaks if
401            // it isn't right.  Can't wait for soapaction to be fully deprecated
402            if ($this->currentTest == 'base' &&
403                strstr($endpoint_info['endpointName'],'MS SOAP ToolKit 2.0')) {
404                $soapaction = 'urn:soapinterop';
405            }
406            if (!array_key_exists('client',$endpoint_info)) {
407                $endpoint_info['client'] = new SoapClient(null,array('location'=>$endpoint_info['endpointURL'],'uri'=>$soapaction,'trace'=>1));
408            }
409            $soap = $endpoint_info['client'];
410        }
411//        // add headers to the test
412//        if ($soap_test->headers) {
413//            // $header is already a SOAP_Header class
414//            foreach ($soap_test->headers as $header) {
415//              $soap->addHeader($header);
416//            }
417//        }
418        // XXX no way to set encoding
419        // this lets us set UTF-8, US-ASCII or other
420        //$soap->setEncoding($soap_test->encoding);
421try {
422        if ($this->useWSDL && !$soap_test->headers && !$soap_test->headers_expect) {
423            $args = '';
424            foreach ($soap_test->method_params as $pname => $param) {
425                $arg = '$soap_test->method_params["'.$pname.'"]';
426                $args .= $args?','.$arg:$arg;
427            }
428            $return = eval('return $soap->'.$soap_test->method_name.'('.$args.');');
429        } else {
430          if ($soap_test->headers || $soap_test->headers_expect) {
431            $return = $soap->__soapCall($soap_test->method_name,$soap_test->method_params,array('soapaction'=>$soapaction,'uri'=>$namespace), $soap_test->headers, $result_headers);
432          } else {
433            $return = $soap->__soapCall($soap_test->method_name,$soap_test->method_params,array('soapaction'=>$soapaction,'uri'=>$namespace));
434          }
435        }
436} catch (SoapFault $ex) {
437  $return = $ex;
438}
439
440        if(!is_soap_fault($return)){
441            if ($soap_test->expect !== NULL) {
442                $sent = $soap_test->expect;
443            } else if (is_array($soap_test->method_params) && count($soap_test->method_params) == 1) {
444                reset($soap_test->method_params);
445                $sent = current($soap_test->method_params);
446            } else if (is_array($soap_test->method_params) && count($soap_test->method_params) == 0) {
447                $sent = null;
448            } else {
449                $sent = $soap_test->method_params;
450            }
451
452            // compare header results
453            $headers_ok = TRUE;
454            if ($soap_test->headers || $soap_test->headers_expect) {
455              $headers_ok = $this->compareResult($soap_test->headers_expect, $result_headers);
456            }
457
458            # we need to decode what we sent so we can compare!
459            $sent_d = $this->decodeSoapval($sent);
460
461            $soap_test->result['sent'] = $sent;
462            $soap_test->result['return'] = $return;
463
464            // compare the results with what we sent
465
466            if ($soap_test->cmp_func !== NULL) {
467              $cmp_func = $soap_test->cmp_func;
468              $ok = $cmp_func($sent_d,$return);
469            } else {
470              $ok = $this->compareResult($sent_d,$return, $sent->type);
471              if (!$ok && $soap_test->expect) {
472                $ok = $this->compareResult($soap_test->expect,$return);
473              }
474            }
475
476            // save the wire
477            $wire = "REQUEST:\n".str_replace('" ',"\" \n",str_replace('>',">\n",$soap->__getlastrequest()))."\n\n".
478                    "RESPONSE:\n".str_replace('" ',"\" \n",str_replace('>',">\n",$soap->__getlastresponse()))."\n\n".
479                    "EXPECTED:\n".var_dump_str($sent_d)."\n".
480                    "RESULTL:\n".var_dump_str($return);
481            if ($soap_test->headers_expect) {
482              $wire .= "\nEXPECTED HEADERS:\n".var_dump_str($soap_test->headers_expect)."\n".
483                       "RESULT HEADERS:\n".var_dump_str($result_headers);
484            }
485            #print "Wire:".htmlentities($wire);
486
487            if($ok){
488                if (!$headers_ok) {
489                    $fault = new SoapFault('HEADER','The returned result did not match what we expected to receive');
490                    $soap_test->setResult(0,$fault->faultcode,
491                                      $wire,
492                                      $fault->faultstring,
493                                      $fault
494                                      );
495                } else {
496                    $soap_test->setResult(1,'OK',$wire);
497                    $success = TRUE;
498                }
499            } else {
500                $fault = new SoapFault('RESULT','The returned result did not match what we expected to receive');
501                $soap_test->setResult(0,$fault->faultcode,
502                                  $wire,
503                                  $fault->faultstring,
504                                  $fault
505                                  );
506            }
507        } else {
508            $fault = $return;
509            if ($soap_test->expect_fault) {
510                $ok = 1;
511                $res = 'OK';
512            } else {
513                $ok = 0;
514                $res =$fault->faultcode;
515                $pos = strpos($res,':');
516                if ($pos !== false) {
517                  $res = substr($res,$pos+1);
518                }
519            }
520            // save the wire
521            $wire = "REQUEST:\n".str_replace('" ',"\" \n",str_replace('>',">\n",$soap->__getlastrequest()))."\n\n".
522                    "RESPONSE:\n".str_replace('" ',"\" \n",str_replace('>',">\n",$soap->__getlastresponse()))."\n".
523                    "RESULTL:\n".var_dump_str($return);
524            #print "Wire:".htmlentities($wire);
525
526            $soap_test->setResult($ok,$res, $wire,$fault->faultstring, $fault);
527
528        }
529        return $ok;
530    }
531
532
533    /**
534    *  doTest
535    *  run a single round of tests
536    *
537    * @access public
538    */
539    function doTest() {
540        global $soap_tests;
541        // get endpoints for this test
542        $this->getEndpoints($this->currentTest);
543        #clear totals
544        $this->totals = array();
545
546        $i = 0;
547        foreach($this->endpoints as $endpoint => $endpoint_info){
548
549            // if we specify an endpoint, skip until we find it
550            if ($this->specificEndpoint && $endpoint != $this->specificEndpoint) continue;
551            if ($this->useWSDL && !$endpoint_info['endpointURL']) continue;
552
553            $skipendpoint = FALSE;
554            $this->totals['servers']++;
555            #$endpoint_info['tests'] = array();
556
557            if ($this->show) {
558              print "Processing $endpoint at {$endpoint_info['endpointURL']}";
559              if ($this->html) print "<br>\n"; else print "\n";
560            }
561
562            foreach($soap_tests[$this->currentTest] as $soap_test) {
563            //foreach(array_keys($method_params[$this->currentTest][$this->paramType]) as $method)
564
565                // only run the type of test we're looking for (php or soapval)
566                if ($soap_test->type != $this->paramType) continue;
567
568                // if we haven't reached our startpoint, skip
569                if ($this->startAt && $this->startAt != $endpoint_info['endpointName']) continue;
570                $this->startAt = '';
571
572                // if this is in our skip list, skip it
573                if (in_array($endpoint, $this->skipEndpointList)) {
574                    $skipendpoint = TRUE;
575                    $skipfault = new SoapFault('SKIP','endpoint skipped');
576                    $soap_test->setResult(0,$fault->faultcode, '',
577                                  $skipfault->faultstring,
578                                  $skipfault
579                                  );
580                    #$endpoint_info['tests'][] = &$soap_test;
581                    #$soap_test->showTestResult($this->debug, $this->html);
582                    #$this->_saveResults($endpoint_info['id'], $soap_test->method_name);
583                    $soap_test->result = NULL;
584                    continue;
585                }
586
587                // if we're looking for a specific method, skip unless we have it
588                if ($this->testMethod && strcmp($this->testMethod,$soap_test->test_name) != 0) continue;
589
590                // if we are skipping the rest of the tests (due to error) note a fault
591                if ($skipendpoint) {
592                    $soap_test->setResult(0,$fault->faultcode, '',
593                                  $skipfault->faultstring,
594                                  $skipfault
595                                  );
596                    #$endpoint_info['tests'][] = &$soap_test;
597                    $this->totals['fail']++;
598                } else {
599                    // run the endpoint test
600                    if ($this->doEndpointMethod($endpoint_info, $soap_test)) {
601                        $this->totals['success']++;
602                    } else {
603                        $skipendpoint = $soap_test->result['fault']->faultcode=='HTTP'
604                            && strstr($soap_test->result['fault']->faultstring,'Connect Error');
605                        $skipfault = $soap_test->result['fault'];
606                        $this->totals['fail']++;
607                    }
608                    #$endpoint_info['tests'][] = &$soap_test;
609                }
610                $soap_test->showTestResult($this->debug, $this->html);
611                $this->_saveResults($endpoint_info['id'], $soap_test);
612                $soap_test->result = NULL;
613                $this->totals['calls']++;
614            }
615            if ($this->numservers && ++$i >= $this->numservers) break;
616        }
617    }
618
619    function doGroupTests() {
620        $dowsdl = array(0,1);
621        foreach($dowsdl as $usewsdl) {
622            $this->useWSDL = $usewsdl;
623            foreach($this->paramTypes as $ptype) {
624                // skip a pointless test
625                if ($usewsdl && $ptype == 'soapval') break;
626                $this->paramType = $ptype;
627                $this->doTest();
628            }
629        }
630    }
631
632    /**
633    *  doTests
634    *  go all out.  This takes time.
635    *
636    * @access public
637    */
638    function doTests() {
639        // the mother of all interop tests
640        $dowsdl = array(0,1);
641        foreach($this->tests as $test) {
642            $this->currentTest = $test;
643            foreach($dowsdl as $usewsdl) {
644                $this->useWSDL = $usewsdl;
645                foreach($this->paramTypes as $ptype) {
646                    // skip a pointless test
647                    if ($usewsdl && $ptype == 'soapval') break;
648                    $this->paramType = $ptype;
649                    $this->doTest();
650                }
651            }
652        }
653    }
654
655    // ***********************************************************
656    // output functions
657
658    /**
659    *  getResults
660    * retrieve results from the database, stuff them into the endpoint array
661    *
662    * @access private
663    */
664    function getMethodList($test = 'base') {
665        // retrieve the results and put them into the endpoint info
666        $sql = "select distinct(function) from results where class='$test' order by function";
667        $results = $this->dbc->getAll($sql);
668        $ar = array();
669        foreach($results as $result) {
670            $ar[] = $result[0];
671        }
672        return $ar;
673    }
674
675    function outputTable()
676    {
677        $methods = $this->getMethodList($this->currentTest);
678        if (!$methods) return;
679        $this->getResults($this->currentTest,$this->paramType,$this->useWSDL);
680
681        echo "<b>Testing $this->currentTest ";
682        if ($this->useWSDL) echo "using WSDL ";
683        else echo "using Direct calls ";
684        echo "with $this->paramType values</b><br>\n";
685
686        // calculate totals for this table
687        $this->totals['success'] = 0;
688        $this->totals['fail'] = 0;
689        $this->totals['servers'] = 0; #count($this->endpoints);
690        foreach ($this->endpoints as $endpoint => $endpoint_info) {
691            if (count($endpoint_info['methods']) > 0) {
692                $this->totals['servers']++;
693                foreach ($methods as $method) {
694                    $r = $endpoint_info['methods'][$method]['result'];
695                    if ($r == 'OK') $this->totals['success']++;
696                    else $this->totals['fail']++;
697                }
698            } else {
699                unset($this->endpoints[$endpoint]);
700            }
701        }
702        $this->totals['calls'] = count($methods) * $this->totals['servers'];
703
704        echo "\n\n<b>Servers: {$this->totals['servers']} Calls: {$this->totals['calls']} Success: {$this->totals['success']} Fail: {$this->totals['fail']}</b><br>\n";
705
706        echo "<table border=\"1\" cellspacing=\"0\" cellpadding=\"2\">\n";
707        echo "<tr><td class=\"BLANK\">Endpoint</td>\n";
708        foreach ($methods as $method) {
709            $info = split(':', $method);
710            echo "<td class='BLANK' valign='top'>";
711            foreach ($info as $m) {
712                $hi = split(',',$m);
713                echo '<b>'.$hi[0]."</b><br>\n";
714                if (count($hi) > 1) {
715                    echo "&nbsp;&nbsp;Actor=".($hi[1]?'Target':'Not Target')."<br>\n";
716                    echo "&nbsp;&nbsp;MustUnderstand=$hi[2]<br>\n";
717                }
718            }
719            echo "</td>\n";
720        }
721        echo "</tr>\n";
722        $faults = array();
723        $fi = 0;
724        foreach ($this->endpoints as $endpoint => $endpoint_info) {
725            if (array_key_exists('wsdlURL',$endpoint_info)) {
726                echo "<tr><td class=\"BLANK\"><a href=\"{$endpoint_info['wsdlURL']}\">$endpoint</a></td>\n";
727            } else {
728                echo "<tr><td class=\"BLANK\">$endpoint</td>\n";
729            }
730            foreach ($methods as $method) {
731                $id = $endpoint_info['methods'][$method]['id'];
732                $r = $endpoint_info['methods'][$method]['result'];
733                $e = $endpoint_info['methods'][$method]['error'];
734                if ($e) {
735                    $faults[$fi++] = $e;
736                }
737                if ($r) {
738                    echo "<td class='$r'><a href='$PHP_SELF?wire=$id'>$r</a></td>\n";
739                } else {
740                    echo "<td class='untested'>untested</td>\n";
741                }
742            }
743            echo "</tr>\n";
744        }
745        echo "</table><br>\n";
746        if ($this->showFaults && count($faults) > 0) {
747            echo "<b>ERROR Details:</b><br>\n<ul>\n";
748            # output more error detail
749            foreach ($faults as $fault) {
750                echo '<li>'.HTMLSpecialChars($fault)."</li>\n";
751            }
752        }
753        echo "</ul><br><br>\n";
754    }
755
756    function outputTables() {
757        // the mother of all interop tests
758        $dowsdl = array(0,1);
759        foreach($this->tests as $test) {
760            $this->currentTest = $test;
761            foreach($dowsdl as $usewsdl) {
762                $this->useWSDL = $usewsdl;
763                foreach($this->paramTypes as $ptype) {
764                    // skip a pointless test
765                    if ($usewsdl && $ptype == 'soapval') break;
766                    $this->paramType = $ptype;
767                    $this->outputTable();
768                }
769            }
770        }
771    }
772
773    function showWire($id) {
774        $results = $this->dbc->getAll("select * from results where id=$id",NULL, DB_FETCHMODE_ASSOC );
775        #$wire = preg_replace("/>/",">\n",$results[0]['wire']);
776        $wire = $results[0]['wire'];
777        if ($this->html) print "<pre>";
778        echo "\n".HTMLSpecialChars($wire);
779        if ($this->html) print "</pre>";
780        print "\n";
781    }
782
783}
784
785?>