2001-07-16 08:05:33 +02:00
< ? php
2001-12-10 03:09:17 +01:00
// SOAP server class
2001-07-16 08:05:33 +02:00
2001-12-10 03:09:17 +01:00
// for example usage, see the test_server.php file.
2001-07-30 05:40:08 +02:00
2001-08-18 16:37:52 +02:00
class soap_server
2001-07-16 08:05:33 +02:00
{
2001-12-10 03:09:17 +01:00
function soap_server ( $data = '' , $serviceNow = False )
2001-07-16 08:05:33 +02:00
{
2001-08-18 16:37:52 +02:00
// create empty dispatch map
$this -> dispatch_map = array ();
$this -> debug_flag = True ;
$this -> debug_str = '' ;
$this -> headers = '' ;
$this -> request = '' ;
2001-12-10 03:09:17 +01:00
$this -> result = 'successful' ;
2001-08-18 16:37:52 +02:00
$this -> fault = false ;
$this -> fault_code = '' ;
$this -> fault_str = '' ;
$this -> fault_actor = '' ;
2001-12-10 03:09:17 +01:00
if ( $serviceNow == 1 )
{
$this -> service ( $data );
}
2001-07-16 08:05:33 +02:00
}
2001-08-18 16:37:52 +02:00
// parses request and posts response
function service ( $data )
2001-07-16 08:05:33 +02:00
{
2001-08-18 16:37:52 +02:00
// $response is a soap_msg object
2005-09-10 12:39:36 +02:00
$response = get_class ( $data ) == 'soapmsg' ? $date : $this -> parseRequest ( $data );
2001-08-18 16:37:52 +02:00
$this -> debug ( " parsed request and got an object of this class ' " . get_class ( $response ) . " ' " );
$this -> debug ( " server sending... " );
// pass along the debug string
if ( $this -> debug_flag )
2001-07-16 08:05:33 +02:00
{
2001-08-18 16:37:52 +02:00
$response -> debug ( $this -> debug_str );
2001-07-16 08:05:33 +02:00
}
2001-08-18 16:37:52 +02:00
$payload = $response -> serialize ();
// print headers
if ( $this -> fault )
2001-07-16 08:05:33 +02:00
{
2001-08-18 16:37:52 +02:00
$header [] = " HTTP/1.0 500 Internal Server Error \r \n " ;
2001-07-16 08:05:33 +02:00
}
2001-08-18 16:37:52 +02:00
else
2001-07-30 05:40:08 +02:00
{
2001-08-18 16:37:52 +02:00
$header [] = " HTTP/1.0 200 OK \r \n " ;
$header [] = " Status: 200 \r \n " ;
2001-07-30 05:40:08 +02:00
}
2001-08-18 16:37:52 +02:00
$header [] = " Server: SOAPx4 Server v0.344359s \r \n " ;
$header [] = " Connection: Close \r \n " ;
2001-12-10 03:09:17 +01:00
$header [] = " Content-Type: text/xml; charset=UTF-8 \r \n " ;
2001-08-18 16:37:52 +02:00
$header [] = " Content-Length: " . strlen ( $payload ) . " \r \n \r \n " ;
2001-12-10 03:09:17 +01:00
reset ( $header );
foreach ( $header as $hdr )
2001-07-30 05:40:08 +02:00
{
2001-08-18 16:37:52 +02:00
header ( $hdr );
2001-07-30 05:40:08 +02:00
}
2001-08-18 16:37:52 +02:00
print $payload ;
2001-07-16 08:05:33 +02:00
}
2001-08-02 10:31:48 +02:00
2001-12-10 03:09:17 +01:00
function parseRequest ( $data = " " )
2001-07-16 08:05:33 +02:00
{
2001-08-18 16:37:52 +02:00
global $HTTP_SERVER_VARS ;
2001-07-16 22:36:22 +02:00
2001-12-10 03:09:17 +01:00
$this -> debug ( " entering parseRequest() on " . date ( " H:i Y-m-d " ));
$request_uri = $HTTP_SERVER_VARS [ " REQUEST_URI " ];
2001-08-18 16:37:52 +02:00
$this -> debug ( " request uri: $request_uri " );
// get headers
2001-12-10 03:09:17 +01:00
$headers_array = getallheaders ();
foreach ( $headers_array as $k => $v )
2001-08-18 16:37:52 +02:00
{
2001-12-10 03:09:17 +01:00
$dump .= " $k : $v\r\n " ;
}
$dump .= " \r \n \r \n " . $data ;
$this -> headers = $headers_array ;
$this -> request = $dump ;
// get SOAPAction header -> methodname
if ( $headers_array [ " SOAPAction " ])
{
$action = str_replace ( '"' , '' , $headers_array [ " SOAPAction " ]);
if ( ereg ( " ^urn: " , $action ))
2001-08-18 16:37:52 +02:00
{
2001-12-10 03:09:17 +01:00
$this -> service = substr ( $action , 4 );
2001-08-18 16:37:52 +02:00
}
2001-12-10 03:09:17 +01:00
elseif ( ereg ( " .php " , $action ))
2001-08-18 16:37:52 +02:00
{
2001-12-10 03:09:17 +01:00
$this -> service = ereg_replace ( '"|/' , '' , substr ( strrchr ( $action , " .php " ), 4 , strlen ( strrchr ( $action , " / " ))));
2001-08-18 16:37:52 +02:00
}
2001-12-10 03:09:17 +01:00
$this -> debug ( " got service: $this->service " );
}
else
{
// throw a fault if no soapaction
$this -> debug ( " ERROR: no SOAPAction header found " );
2001-08-18 16:37:52 +02:00
}
2001-12-10 03:09:17 +01:00
// NOTE:::: throw a fault for no/bad soapaction here?
2001-08-18 16:37:52 +02:00
// parse response, get soap parser obj
$parser = CreateObject ( 'phpgwapi.soap_parser' , $data );
// get/set methodname
$this -> methodname = $parser -> root_struct_name ;
$this -> debug ( " method name: $this->methodname " );
2001-08-18 22:31:47 +02:00
2001-08-18 16:37:52 +02:00
// does method exist?
2001-12-10 03:09:17 +01:00
$test = ereg_replace ( " \ . " , '_' , $this -> methodname );
if ( function_exists ( $test ))
2001-07-16 08:05:33 +02:00
{
2001-12-10 03:09:17 +01:00
$method = $this -> methodname = $test ;
2001-08-18 16:37:52 +02:00
$this -> debug ( " method ' $this->methodname ' exists " );
}
else
{
2004-05-05 14:06:13 +02:00
/* egroupware customization - createobject based on methodname */
2001-08-18 16:37:52 +02:00
list ( $app , $class , $method ) = explode ( '.' , $this -> methodname );
2001-12-10 03:09:17 +01:00
if ( ereg ( " ^service " , $app ))
{
$args = $class ;
$class = 'service' ;
$app = 'phpgwapi' ;
$obj = CreateObject ( sprintf ( '%s.%s' , $app , $class ), $args );
unset ( $args );
}
else
{
$obj = CreateObject ( sprintf ( '%s.%s' , $app , $class ));
}
$this -> debug ( 'app: ' . $app . ', class: ' . $class . ', method: ' . $method );
2001-08-18 16:37:52 +02:00
/*
// "method not found" fault here
$this -> debug ( " method ' $obj->method ' not found! " );
$this -> result = " fault: method not found " ;
$this -> make_fault ( " Server " , " method ' $obj->method ' not defined in service ' $this->service ' " );
return $this -> fault ();
*/
}
// if fault occurred during message parsing
if ( $parser -> fault ())
{
// parser debug
$this -> debug ( $parser -> debug_str );
2001-12-10 03:09:17 +01:00
$this -> result = " fault: error in msg parsing or eval " ;
2001-08-18 16:37:52 +02:00
$this -> make_fault ( " Server " , " error in msg parsing or eval: \n " . $parser -> get_response ());
// return soapresp
2001-07-16 08:05:33 +02:00
return $this -> fault ();
2001-12-10 03:09:17 +01:00
// else successfully parsed request into soapval object
2001-07-16 08:05:33 +02:00
}
2001-08-18 16:37:52 +02:00
else
2001-07-16 08:05:33 +02:00
{
2001-08-18 16:37:52 +02:00
// get eval_str
2001-12-10 03:09:17 +01:00
$this -> debug ( " calling parser->get_response() " );
2001-08-18 16:37:52 +02:00
// evaluate it, getting back a soapval object
if ( ! $request_val = $parser -> get_response ())
2001-07-16 22:36:22 +02:00
{
2001-08-18 16:37:52 +02:00
return $this -> fault ();
2001-07-16 22:36:22 +02:00
}
2001-08-18 16:37:52 +02:00
// parser debug
$this -> debug ( $parser -> debug_str );
2001-12-10 03:09:17 +01:00
if ( get_class ( $request_val ) == " soapval " )
2001-07-16 08:05:33 +02:00
{
2001-08-18 16:37:52 +02:00
if ( is_object ( $obj ))
2001-07-16 22:36:22 +02:00
{
2001-08-18 16:37:52 +02:00
/* Add the function to the server map */
$in = " array(' " . implode ( " ',' " , $obj -> soap_functions [ $method ][ 'in' ]) . " ') " ;
$out = " array(' " . implode ( " ',' " , $obj -> soap_functions [ $method ][ 'out' ]) . " ') " ;
$evalmap = " \$ this->add_to_map( \$ this->methodname, $in , $out ); " ;
eval ( $evalmap );
2001-07-16 08:05:33 +02:00
}
2001-08-18 16:37:52 +02:00
/* verify that soapval objects in request match the methods signature */
if ( $this -> verify_method ( $request_val ))
2001-07-16 08:05:33 +02:00
{
2001-08-18 16:37:52 +02:00
$this -> debug ( " request data - name: $request_val->name , type: $request_val->type , value: $request_val->value " );
if ( $this -> input_value )
2001-07-16 08:05:33 +02:00
{
2001-08-18 16:37:52 +02:00
/* decode the soapval object, and pass resulting values to the requested method */
if ( ! $request_data = $request_val -> decode ())
2001-07-16 22:36:22 +02:00
{
2001-08-18 16:37:52 +02:00
$this -> make_fault ( " Server " , " Unable to decode response from soapval object into native php type. " );
return $this -> fault ();
2001-07-16 22:36:22 +02:00
}
2001-08-18 16:37:52 +02:00
$this -> debug ( " request data: $request_data " );
}
2001-08-18 22:31:47 +02:00
2001-08-18 16:37:52 +02:00
/* if there are return values */
if ( $this -> return_type = $this -> get_return_type ())
{
$this -> debug ( " got return type: ' $this->return_type ' " );
/* if there are parameters to pass */
if ( $request_data )
2001-07-16 08:05:33 +02:00
{
2001-08-18 16:37:52 +02:00
if ( is_object ( $obj ))
{
2001-12-10 03:09:17 +01:00
$code = " \$ method_response = call_user_method( $method , $obj , " ;
$this -> debug ( " about to call object method ' $class\ - \ > $method ' with args " );
2001-08-18 16:37:52 +02:00
}
else
{
2001-12-10 03:09:17 +01:00
$code = '$method_response = ' . $this -> methodname . " (' " ;
$args = implode ( " ',' " , $request_data [ 'return' ]);
$this -> debug ( " about to call method ' $this->methodname ' with args: $args " );
2001-08-18 16:37:52 +02:00
}
/* call method with parameters */
2001-12-10 03:09:17 +01:00
$code .= implode ( " ',' " , $request_data [ 'return' ]);
/*
2001-08-18 16:37:52 +02:00
while ( list ( $x , $y ) = each ( $request_data ))
{
$code .= " \$ request_data[ $x ] " . ',' ;
}
2001-12-10 03:09:17 +01:00
$code = substr ( $code , 0 , - 1 ) . " ); " ;
*/
$code .= " '); " ;
$this -> debug ( 'CODE: ' . $code );
2001-08-18 16:37:52 +02:00
if ( eval ( $code ))
{
if ( is_object ( $obj ))
{
2001-12-10 03:09:17 +01:00
$this -> make_fault ( " Server " , " Object method call failed for ' $class\ - \ > $method ' with params: " . join ( ',' , $request_data ));
2001-08-18 16:37:52 +02:00
}
else
{
2001-12-10 03:09:17 +01:00
$this -> make_fault ( " Server " , " Method call failed for ' $this->methodname ' with params: " . join ( ',' , $request_data ));
2001-08-18 16:37:52 +02:00
}
return $this -> fault ();
}
2001-12-10 03:09:17 +01:00
$this -> debug ( 'Response: ' . $method_response );
// _debug_array($method_response);
2001-07-16 22:36:22 +02:00
}
2001-08-18 16:37:52 +02:00
else
2001-07-16 22:36:22 +02:00
{
2001-08-18 16:37:52 +02:00
/* call method w/ no parameters */
2001-07-16 22:36:22 +02:00
if ( is_object ( $obj ))
{
2001-12-10 03:09:17 +01:00
$this -> debug ( " about to call object method ' $obj\ - \ > $method ' " );
2001-08-18 16:37:52 +02:00
if ( ! $method_response = call_user_method ( $method , $obj ))
{
$this -> make_fault ( " Server " , " Method call failed for ' $obj->method ' with no params " );
return $this -> fault ();
}
2001-07-16 22:36:22 +02:00
}
else
{
2001-08-18 16:37:52 +02:00
$this -> debug ( " about to call method ' $this->methodname ' " );
if ( ! $method_response = call_user_func ( $this -> methodname ))
{
$this -> make_fault ( " Server " , " Method call failed for ' $this->methodname ' with no params " );
return $this -> fault ();
}
2001-07-16 22:36:22 +02:00
}
2001-07-16 08:05:33 +02:00
}
2001-12-10 03:09:17 +01:00
/* no return values */
2001-07-16 08:05:33 +02:00
}
else
{
2001-08-18 16:37:52 +02:00
if ( $request_data )
2001-07-16 08:05:33 +02:00
{
2001-08-18 16:37:52 +02:00
/* call method with parameters */
$code = " \$ method_response = call_user_method( \$ method, \$ obj, " ;
while ( list ( $x , $y ) = each ( $request_data ))
2001-07-16 22:36:22 +02:00
{
2001-08-18 16:37:52 +02:00
$code .= " \$ request_data[ $x ] " . ',' ;
2001-07-16 22:36:22 +02:00
}
2001-12-10 03:09:17 +01:00
$code = substr ( $code , 0 , - 1 ) . " ); " ;
$this -> debug ( " about to call object method ' $obj\ - \ > $method ' " );
2001-08-18 16:37:52 +02:00
eval ( $code );
2001-07-16 22:36:22 +02:00
}
else
{
2001-08-18 16:37:52 +02:00
/* call method w/ no parameters */
2001-12-10 03:09:17 +01:00
if ( is_object ( $obj ))
{
$this -> debug ( " about to call object method ' $obj\ - \ > $method ' " );
call_user_method ( $method , $obj );
}
else
{
$this -> debug ( " about to call method ' $method ' " );
call_user_func ( $method );
}
2001-07-16 08:05:33 +02:00
}
}
2001-12-10 03:09:17 +01:00
/* create soap_val object w/ return values from method, use method signature to determine type */
if ( get_class ( $method_response ) != 'soapval' )
2001-07-16 08:05:33 +02:00
{
2001-12-10 03:09:17 +01:00
$return_val = CreateObject ( 'phpgwapi.soapval' , $method , $this -> return_type , $method_response );
2001-07-16 08:05:33 +02:00
}
else
{
2001-12-10 03:09:17 +01:00
$return_val = $method_response ;
2001-07-16 08:05:33 +02:00
}
2001-12-10 03:09:17 +01:00
$this -> debug ( $return_val -> debug_str );
/* response object is a soap_msg object */
$return_msg = CreateObject ( 'phpgwapi.soapmsg' , $method . 'Response' , array ( $return_val ), $this -> service );
2001-08-18 16:37:52 +02:00
if ( $this -> debug_flag )
2001-07-30 05:40:08 +02:00
{
2001-08-18 16:37:52 +02:00
$return_msg -> debug_flag = true ;
2001-07-30 05:40:08 +02:00
}
2001-12-10 03:09:17 +01:00
$this -> result = " successful " ;
2001-08-18 16:37:52 +02:00
return $return_msg ;
2001-07-16 08:05:33 +02:00
}
else
{
2001-08-18 16:37:52 +02:00
// debug
$this -> debug ( " ERROR: request not verified against method signature " );
$this -> result = " fault: request failed validation against method signature " ;
// return soapresp
return $this -> fault ();
2001-07-16 08:05:33 +02:00
}
}
else
{
// debug
2001-08-18 16:37:52 +02:00
$this -> debug ( " ERROR: parser did not return soapval object: $request_val " . get_class ( $request_val ));
$this -> result = " fault: parser did not return soapval object: $request_val " ;
// return fault
2001-12-10 03:09:17 +01:00
$this -> make_fault ( " Server " , " parser did not return soapval object: $request_val " );
2001-07-16 08:05:33 +02:00
return $this -> fault ();
}
}
}
2001-08-18 16:37:52 +02:00
function verify_method ( $request )
2001-07-16 08:05:33 +02:00
{
2001-08-18 16:37:52 +02:00
//return true;
2001-12-10 03:09:17 +01:00
$this -> debug ( " entered verify_method() w/ request name: " . $request -> name );
2001-08-18 16:37:52 +02:00
$params = $request -> value ;
// if there are input parameters required...
if ( $sig = $this -> dispatch_map [ $this -> methodname ][ " in " ])
2001-07-16 08:05:33 +02:00
{
2001-08-18 16:37:52 +02:00
$this -> input_value = count ( $sig );
if ( is_array ( $params ))
2001-07-16 08:05:33 +02:00
{
2001-12-10 03:09:17 +01:00
$this -> debug ( " entered verify_method() with " . count ( $params ) . " parameters " );
foreach ( $params as $v )
2001-07-16 08:05:33 +02:00
{
2001-08-18 16:37:52 +02:00
$this -> debug ( " param ' $v->name ' of type ' $v->type ' " );
2001-07-16 08:05:33 +02:00
}
2001-08-18 16:37:52 +02:00
// validate the number of parameters
if ( count ( $params ) == count ( $sig ))
2001-07-16 08:05:33 +02:00
{
2001-08-18 16:37:52 +02:00
$this -> debug ( " got correct number of parameters: " . count ( $sig ));
// make array of param types
2001-12-10 03:09:17 +01:00
foreach ( $params as $param )
2001-08-18 16:37:52 +02:00
{
$p [] = strtolower ( $param -> type );
}
// validate each param's type
for ( $i = 0 ; $i < count ( $p ); $i ++ )
2001-07-16 08:05:33 +02:00
{
2001-08-18 16:37:52 +02:00
// type not match
if ( strtolower ( $sig [ $i ]) != strtolower ( $p [ $i ]))
{
$this -> debug ( " mismatched parameter types: $sig[$i] != $p[$i] " );
2001-12-10 03:09:17 +01:00
$this -> make_fault ( " Client " , " soap request contained mismatching parameters of name $v->name had type $p[$i] , which did not match signature's type: $sig[$i] " );
2001-08-18 16:37:52 +02:00
return false ;
}
$this -> debug ( " parameter type match: $sig[$i] = $p[$i] " );
2001-07-16 08:05:33 +02:00
}
2001-08-18 16:37:52 +02:00
return true ;
2001-12-10 03:09:17 +01:00
// oops, wrong number of paramss
2001-08-18 16:37:52 +02:00
}
else
{
2001-12-10 03:09:17 +01:00
$this -> debug ( " oops, wrong number of parameter! " );
$this -> make_fault ( " Client " , " soap request contained incorrect number of parameters. method ' $this->methodname ' required " . count ( $sig ) . " and request provided " . count ( $params ));
2001-08-18 16:37:52 +02:00
return false ;
2001-07-16 08:05:33 +02:00
}
2001-12-10 03:09:17 +01:00
// oops, no params...
2001-07-16 08:05:33 +02:00
}
else
{
2001-08-18 16:37:52 +02:00
$this -> debug ( " oops, no parameters sent! Method ' $this->methodname ' requires " . count ( $sig ) . " input parameters! " );
2001-12-10 03:09:17 +01:00
$this -> make_fault ( " Client " , " soap request contained incorrect number of parameters. method ' $this->methodname ' requires " . count ( $sig ) . " parameters, and request provided none " );
2001-07-16 08:05:33 +02:00
return false ;
}
2001-08-18 16:37:52 +02:00
// no params
}
elseif ( ( count ( $params ) == 0 ) && ( count ( $sig ) <= 1 ) )
{
$this -> input_values = 0 ;
return true ;
2001-07-16 08:05:33 +02:00
}
else
{
2001-08-18 16:37:52 +02:00
//$this->debug("well, request passed parameters to a method that requires none?");
//$this->make_fault("Client","method '$this->methodname' requires no parameters. The request passed in ".count($params).": ".@implode(" param: ",$params) );
return true ;
2001-07-16 08:05:33 +02:00
}
}
2001-08-18 16:37:52 +02:00
// get string return type from dispatch map
function get_return_type ()
2001-07-16 08:05:33 +02:00
{
2001-12-10 03:09:17 +01:00
if ( count ( $this -> dispatch_map [ $this -> methodname ][ " out " ]) >= 1 )
2001-08-18 16:37:52 +02:00
{
2001-12-10 03:09:17 +01:00
$type = array_shift ( $this -> dispatch_map [ $this -> methodname ][ " out " ]);
2001-08-18 16:37:52 +02:00
$this -> debug ( " got return type from dispatch map: ' $type ' " );
return $type ;
}
return false ;
2001-07-16 08:05:33 +02:00
}
2001-08-18 16:37:52 +02:00
// dbg
function debug ( $string )
2001-07-16 08:05:33 +02:00
{
2001-08-18 16:37:52 +02:00
if ( $this -> debug_flag )
{
$this -> debug_str .= " $string\n " ;
}
2001-07-16 08:05:33 +02:00
}
2001-08-18 16:37:52 +02:00
// add a method to the dispatch map
function add_to_map ( $methodname , $in , $out )
2001-07-16 08:05:33 +02:00
{
2001-12-10 03:09:17 +01:00
$this -> dispatch_map [ $methodname ][ " in " ] = $in ;
$this -> dispatch_map [ $methodname ][ " out " ] = $out ;
2001-07-16 08:05:33 +02:00
}
2001-08-18 16:37:52 +02:00
// set up a fault
function fault ()
2001-07-16 08:05:33 +02:00
{
2001-08-18 16:37:52 +02:00
return CreateObject ( 'phpgwapi.soapmsg' ,
2001-12-10 03:09:17 +01:00
" Fault " ,
array (
" faultcode " => $this -> fault_code ,
" faultstring " => $this -> fault_str ,
" faultactor " => $this -> fault_actor ,
" faultdetail " => $this -> fault_detail . $this -> debug_str
),
" http://schemas.xmlphpgwapi.org/soap/envelope/ "
);
}
2001-07-16 08:05:33 +02:00
2001-12-10 03:09:17 +01:00
function make_fault ( $fault_code , $fault_string )
{
$this -> fault_code = $fault_code ;
$this -> fault_str = $fault_string ;
$this -> fault = true ;
2001-07-16 08:05:33 +02:00
}
2001-12-10 03:09:17 +01:00
}
2001-07-16 08:05:33 +02:00
?>