This brings the SOAP server up to date as of 27 July 01 with the developers release code.

This commit is contained in:
skeeter 2001-07-30 03:40:08 +00:00
parent f3397a4e27
commit 83086f8900
5 changed files with 117 additions and 65 deletions

View File

@ -15,6 +15,19 @@ by Victor Zou (C) 2000-2001 <victor@gigaideas.com.cn>
*/
/* changelog:
2001-07-04
- abstract type system to support either 1999 or 2001 schema (arg, typing still needs much
solidification.)
- implemented proxy support, based on sample code from miles lott <milos@speakeasy.net>
- much general cleanup of code & cleaned out what was left of original xml-rpc/gigaideas code
- implemented a transport argument into send() that allows you to specify different transports
(assuming you have implemented the function, and added it to the conditional statement in send()
- abstracted the determination of charset in Content-type header
2001-07-5
- fixed more weird type/namespace issues
*/
// $path can be a complete endpoint url, with the other parameters left blank:
// $soap_client = new soap_client("http://path/to/soap/server");
class soap_client
@ -68,7 +81,7 @@ class soap_client
function send($msg, $action, $timeout=0)
{
// where msg is an soapmsg
$msg->debug = $this->debug;
$msg->debug_flag = $this->debug_flag;
$this->action = $action;
return $this->sendPayloadHTTP10(
$msg,
@ -124,13 +137,12 @@ class soap_client
// get reponse
while($data = fread($fp, 32768))
{
$incoming_payload .= $data;
$incoming_payload .= $data;
}
fclose($fp);
$this->incoming_payload = $incoming_payload;
// $response is a soapmsg object
//$msg->debug_flag = true;
$this->response = $msg->parseResponse($incoming_payload);
$this->debug($msg->debug_str);
return $this->response;

View File

@ -1,15 +1,16 @@
<?php
class soap_parser
{
function soap_parser($xml='')
function soap_parser($xml='',$encoding='UTF-8')
{
global $soapTypes;
$this->soapTypes = $soapTypes;
$this->xml = $xml;
$this->xml_encoding = "UTF-8";
$this->xml_encoding = $encoding;
$this->root_struct = "";
// options: envelope,header,body,method
// determines where in the message we are (envelope,header,body,method)
$this->status = "";
$this->position = 0;
$this->pos_stat = 0;
@ -215,7 +216,8 @@ class soap_parser
// get type if not set already
if($this->message[$pos]["type"] == "")
{
if($this->message[$pos]["cdata"] == "" && $this->message[$pos]["children"] != "")
// if($this->message[$pos]["cdata"] == "" && $this->message[$pos]["children"] != "")
if($this->message[$pos]["children"] != "")
{
$this->message[$pos]["type"] = "SOAPStruct";
}
@ -282,7 +284,7 @@ class soap_parser
}
// set parent back to my parent
$this->parent = $this->message[$pos]["parent"];
//$this->debug("parsed $name end, eval_str = '".trim($this->message[$pos]["eval_str"])."' and children = ".$this->message[$pos]["children"]);
$this->debug("parsed $name end, type '".$this->message[$pos]["type"]."'eval_str = '".trim($this->message[$pos]["eval_str"])."' and children = ".$this->message[$pos]["children"]);
}
// element content handler

View File

@ -3,9 +3,26 @@
// for example usage, see the test_server.php file.
/* changelog:
2001-07-05
- detection of character encoding in Content-Type header. server
will now call the soap_parser object with the specified encoding
- server will now return the Content-Type header with the sender's encoding type specified
must still learn more bout encoding, and figure out what i have to do to be able to
make sure that my response is *actually* encoded correctly
2001-07-21
- force proper error reporting for windows compatibility
2001-07-27
- get_all_headers() check for windows compatibility
*/
// make errors handle properly in windows
error_reporting(2039);
class soap_server
{
function soap_server($data='',$serviceNow=False)
function soap_server()
{
// create empty dispatch map
$this->dispatch_map = array();
@ -13,23 +30,20 @@ class soap_server
$this->debug_str = '';
$this->headers = '';
$this->request = '';
$this->result = 'successful';
$this->xml_encoding = 'UTF-8';
$this->fault = false;
$this->fault_code = '';
$this->fault_str = '';
$this->fault_actor = '';
if($serviceNow == 1)
{
$this->service($data);
}
// for logging interop results to db
$this->result = 'successful';
}
// parses request and posts response
function service($data)
{
// $response is a soap_msg object
$response = $this->parseRequest($data);
$response = $this->parse_request($data);
$this->debug("parsed request and got an object of this class '".get_class($response)."'");
$this->debug("server sending...");
// pass along the debug string
@ -50,8 +64,9 @@ class soap_server
}
$header[] = "Server: SOAPx4 Server v0.344359s\r\n";
$header[] = "Connection: Close\r\n";
$header[] = "Content-Type: text/xml; charset=UTF-8\r\n";
$header[] = "Content-Type: text/xml; charset=$this->xml_encoding\r\n";
$header[] = "Content-Length: ".strlen($payload)."\r\n\r\n";
reset($header);
foreach($header as $hdr)
{
header($hdr);
@ -59,50 +74,46 @@ class soap_server
print $payload;
}
function parseRequest($data="")
function parse_request($data='')
{
global $HTTP_SERVER_VARS;
$this->debug("entering parseRequest() on ".date("H:i Y-m-d"));
$this->debug("entering parse_request() on ".date("H:i Y-m-d"));
$request_uri = $HTTP_SERVER_VARS["REQUEST_URI"];
$this->debug("request uri: $request_uri");
// get headers
$headers_array = getallheaders();
foreach($headers_array as $k=>$v)
// get headers
if(function_exists("getallheaders"))
{
$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))
$this->headers = getallheaders();
foreach($headers_array as $k=>$v)
{
$this->service = substr($action,4);
$dump .= "$k: $v\r\n";
}
elseif(ereg(".php",$action))
// get SOAPAction header
if($headers_array["SOAPAction"])
{
$this->service = ereg_replace('"|/','',substr(strrchr($action,".php"),4,strlen(strrchr($action,"/"))));
$this->SOAPAction = str_replace('"','',$headers_array["SOAPAction"]);
$this->service = $this->SOAPAction;
}
$this->debug("got service: $this->service");
// get character encoding
if(ereg("=",$headers_array["Content-Type"]))
{
$this->xml_encoding = str_replace("\"","",substr(strstr($headers_array["Content-Type"],"="),1));
}
elseif(ereg("^text/xml",$headers_array["Content-Type"]))
{
$this->xml_encoding = "us-ascii";
}
$this->debug("got encoding: $this->xml_encoding");
}
else
{
// throw a fault if no soapaction
$this->debug("ERROR: no SOAPAction header found");
}
// NOTE:::: throw a fault for no/bad soapaction here?
$this->request = $dump."\r\n\r\n".$data;
// 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");
// does method exist?
if(function_exists($this->methodname))
{
@ -251,19 +262,32 @@ class soap_server
call_user_method($method,$obj);
}
}
/* create soap_val object w/ return values from method, use method signature to determine type */
if(get_class($method_response) != "soapval")
/* return fault */
if(get_class($method_response) == "soapmsg")
{
$return_val = CreateObject('phpgwapi.soapval',$method,$this->return_type,$method_response);
if(eregi("fault",$method_response->value->name))
{
$this->fault = True;
}
$return_msg = $method_response;
}
else
{
$return_val = $method_response;
/* return soapval object */
if(get_class($method_response) == "soapval")
{
$return_val = $method_response;
/* create soap_val object w/ return values from method, use method signature to determine type */
}
else
{
$return_val = CreateObject('phpgwapi.soapval',$method,$this->return_type,$method_response);
}
$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);
}
$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);
if($this->debug_flag)
{
$return_msg->debug_flag = true;
@ -400,7 +424,7 @@ class soap_server
"faultactor" => $this->fault_actor,
"faultdetail" => $this->fault_detail.$this->debug_str
),
"http://schemas.xmlphpgwapi.org/soap/envelope/"
"http://schemas.xmlsoap.org/soap/envelope/"
);
}

View File

@ -32,7 +32,7 @@ class soapmsg
{
$ns_string .= " xmlns:$v=\"$k\"";
}
return "<SOAP-ENV:Envelope $ns_string SOAP-ENV:encodingStyle=\"http://schemas.xmlphpgwapi.org/soap/encoding/\">\n"
return "<SOAP-ENV:Envelope $ns_string SOAP-ENV:encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\">\n"
. $payload . "</SOAP-ENV:Envelope>\n";
}
@ -72,20 +72,29 @@ class soapmsg
{
$this->debug("Entering parseResponse()");
//$this->debug(" w/ data $data");
// get rid of headers here
$clean_data = ereg_replace("\r\n","\n", $data);
if(ereg("^.*\r\n\r\n",$data))
// strip headers here
//$clean_data = ereg_replace("\r\n","\n", $data);
if(ereg("^.*\r\n\r\n<",$data))
{
$this->debug("found proper seperation of headers and document");
$this->debug("getting rid of headers, stringlen: ".strlen($data));
$clean_data = ereg_replace("^.*\r\n\r\n","", $data);
$clean_data = ereg_replace("^.*\r\n\r\n<","<", $data);
$this->debug("cleaned data, stringlen: ".strlen($clean_data));
}
elseif(ereg("^.*\n\n",$data))
else
{
$this->debug("getting rid of headers, stringlen: ".strlen($data));
$clean_data = ereg_replace("^.*\n\n","", $data);
$this->debug("cleaned data, stringlen: ".strlen($clean_data));
// return fault
return CreateObject('phpgwapi.soapval',
'fault',
'SOAPStruct',
Array(
CreateObject('phpgwapi.soapval','faultcode','string','SOAP-MSG'),
CreateObject('phpgwapi.soapval','faultstring','string','HTTP Error'),
CreateObject('phpgwapi.soapval','faultdetail','string','HTTP headers were not immediately followed by \'\r\n\r\n\'')
)
);
}
/*
// if response is a proper http response, and is not a 200
if(ereg("^HTTP",$clean_data) && !ereg("200$", $clean_data))
{
@ -101,6 +110,7 @@ class soapmsg
)
);
}
*/
$this->debug("about to create parser instance w/ data: $clean_data");
// parse response
$response = CreateObject('phpgwapi.soap_parser',$clean_data);

View File

@ -2,7 +2,8 @@
// soap value object
class soapval
{
function soapval($name='',$type=False,$value=-1,$namespace=False,$type_namespace=False)
// function soapval($name='',$type=False,$value=-1,$namespace=False,$type_namespace=False)
function soapval($name='',$type=False,$value=0,$namespace=False,$type_namespace=False)
{
global $soapTypes, $typemap, $namespaces, $methodNamespace;
@ -74,6 +75,7 @@ class soapval
}
$this->type_prefix = $namespaces[$type_namespace];
}
// if type namespace was not explicitly passed, and we're not in a method struct:
elseif(!$this->type_prefix && !isset($this->namespace))
{
@ -218,7 +220,8 @@ class soapval
break;
}
}
elseif(is_array($k) && in_array($k,array_keys($this->soapTypes)))
// elseif(is_array($k) && in_array($k,array_keys($this->soapTypes)))
elseif(is_array($k,in_array($k,array_keys($this->soapTypes))))
{
$this->debug("got type '$type' for value '$v' from soapTypes array!");
$type = $k;
@ -330,7 +333,7 @@ class soapval
function serialize()
{
return $this->serializeval($this);
}
}
function decode($soapval=false)
{
@ -382,7 +385,8 @@ class soapval
{
if ($type)
{
global $namespaces,$soapTypes,$typemap;
// global $namespaces,$soapTypes,$typemap;
global $namespaces,$typemap;
foreach($typemap as $namespace => $types)
{