prefix
$namespaces = array(
"http://schemas.xmlsoap.org/soap/envelope/" => "SOAP-ENV",
$XMLSchemaVersion => "xsd",
$XMLSchemaVersion."-instance" => "xsi",
"http://schemas.xmlsoap.org/soap/encoding/" => "SOAP-ENC",
"http://soapinterop.org/xsd"=>"si");
$xmlEntities = array("quot" => '"',"amp" => "&",
"lt" => "<","gt" => ">","apos" => "'");
//----------------------------------------------------------------------------
// $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
//----------------------------------------------------------------------------
{
function soap_client($path, $server=false, $port=false)
{
$this->port = 80;
$this->path = $path;
$this->server = $server;
$this->errno;
$this->errstring;
$this->debug_flag = false;
$this->debug_str = "";
$this->username = "";
$this->password = "";
$this->action = "";
$this->incoming_payload = "";
$this->outgoing_payload = "";
$this->response = "";
$this->action = "";
// endpoint mangling
if(ereg("^http://",$path))
{
$path = str_replace("http://","",$path);
$this->path = strstr($path,"/");
$this->debug("path = $this->path");
if(ereg(":",$path))
{
$this->server = substr($path,0,strpos($path,":"));
$this->port = substr(strstr($path,":"),1);
$this->port = substr($this->port,0,strpos($this->port,"/"));
}
else
{
$this->server = substr($path,0,strpos($path,"/"));
}
}
if($port)
{
$this->port = $port;
}
} // end function soap_client
function setCredentials($username, $pword) {
$this->username = $username;
$this->password = $pword;
}
function send($msg, $action = "", $timeout=0) {
// where msg is an soapmsg
if($this->debug_flag){
$msg->debug_flag = true;
}
$this->action = $action;
return $this->sendPayloadHTTP10(
$msg,
$this->server,
$this->port,
$timeout,
$this->username,
$this->password
);
} // end function send
function sendPayloadHTTP10($msg, $server, $port, $timeout=0, $username="", $password="") {
if($timeout > 0){
$fp = fsockopen($server, $port, $this->errno, $this->errstr, $timeout);
} else {
$fp = fsockopen($server, $port, $this->errno, $this->errstr);
}
if (!$fp) {
$this->debug("Couldn't open socket connection to server!");
$this->debug("Server: $this->server");
return 0;
}
$credentials = "";
if($username != "") {
$credentials = "Authorization: Basic ".base64_encode("$username:$password")."\r\n";
}
$soap_data = $msg->serialize();
$this->outgoing_payload =
"POST ".$this->path." HTTP/1.0\r\n".
"User-Agent: SOAPx4 v0.5\r\n".
"Host: ".$this->server."\r\n".
$credentials.
"Content-Type: text/xml\r\nContent-Length: ".strlen($soap_data)."\r\n".
"SOAPAction: \"$this->action\""."\r\n\r\n".
$soap_data;
// send
if(!fputs($fp, $this->outgoing_payload, strlen($this->outgoing_payload))) {
$this->debug("Write error");
}
// get reponse
while($data = fread($fp, 32768)) {
$incoming_payload .= $data;
}
fclose($fp);
$this->incoming_payload = $incoming_payload;
// $response is a soapmsg object
$this->response = $msg->parseResponse($incoming_payload);
$this->debug($msg->debug_str);
return $this->response;
} // end function sendPayloadHTTP10
function debug($string){
if($this->debug_flag){
$this->debug_str .= "soap_client: $string\n";
}
}
} // end class soap_client
//----------------------------------------------------------------------------
// soap message class
//----------------------------------------------------------------------------
class soapmsg
//----------------------------------------------------------------------------
{
// params is an array of soapval objects
function soapmsg($method, $params, $method_namespace = "http://testuri.org", $new_namespaces=false)
{
// globalize method namespace
global $methodNamespace;
$methodNamespace = $method_namespace;
// make method struct
$this->value = new soapval($method,"struct",$params,$method_namespace);
if(is_array($new_namespaces)){
global $namespaces;
$i = count($namespaces);
foreach($new_namespaces as $v){
$namespaces[$v] = "ns".$i++;
}
$this->namespaces = $namespaces;
}
$this->payload = "";
$this->debug_flag = false;
$this->debug_str = "entering soapmsg() with soapval ".$this->value->name."\n";
}
function make_envelope($payload) {
global $namespaces;
foreach($namespaces as $k => $v){
$ns_string .= "xmlns:$v=\"$k\" ";
}
return "\n".
$payload.
"\n";
}
function make_body($payload) {
return "\n".
$payload.
"\n";
}
function createPayload() {
$value = $this->value;
$payload = $this->make_envelope($this->make_body($value->serialize()));
$this->debug($value->debug_str);
$payload = "\n".$payload;
if($this->debug_flag){
$payload .= $this->serializeDebug();
}
$this->payload = str_replace("\n","\r\n", $payload);
}
function serialize(){
if($this->payload == ""){
$this->createPayload();
return $this->payload;
} else {
return $this->payload;
}
}
// returns a soapval object
function parseResponse($data) {
$this->debug("Entering parseResponse()");
//$this->debug(" w/ data $data");
if(ereg("^(.*)\r\n\r\n",$data)) {
$this->debug("found proper separation of headers and document");
$this->debug("getting rid of headers, stringlen: ".strlen($data));
// CHANGES BELOW
$offset = strpos($data, "\r\n\r\n<");
$clean_data = substr($data, $offset+2);
$clean_data = ereg_replace("\r\n","",$clean_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));
//$this->debug($clean_data);
} else {
// return fault
return new soapval("fault","SOAPStruct",array(new soapval("faultcode","string","SOAP-MSG"),new soapval("faultstring","string","HTTP error"),new soapval("faultdetail","string","HTTP headers were not immediately followed by '\r\n\r\n'")));
}
$this->debug("about to create parser instance w/ data");
// parse response
$response = new soap_parser($clean_data);
// return array of parameters
$ret = $response->get_response();
$this->debug($response->debug_str);
return $ret;
}
// dbg
function debug($string){
if($this->debug_flag){
$this->debug_str .= "soapmsg: $string\n";
}
}
// preps debug data for encoding into soapmsg
function serializeDebug() {
if($this->debug_flag){
return "\n";
} else {
return "";
}
}
} // end class soapmsg
//----------------------------------------------------------------------------
// soap value object
//----------------------------------------------------------------------------
class soapval {
//----------------------------------------------------------------------------
function soapval($name="",$type=false,$value=-1,$namespace=false,$type_namespace=false) {
global $soapTypes, $typemap, $namespaces, $methodNamespace, $XMLSchemaVersion;
// detect type if not passed
if(!$type){
$this->debug("soapval - DETECT TYPE: '$name' type: '$type' value: $value\n");
if(is_array($value) && count($value) >= 1){
foreach($value as $k => $v){
if(ereg("^[0-9]+$",$k)){
$type = "array";
} else {
$type = "struct";
}
break;
}
} elseif(is_int($value)){
$type = "int";
} elseif(is_float($value) || $value == "NaN" || $value == "INF"){
$type = "float";
} else {
$type = gettype($value);
}
}
// php type name mangle
if($type == "integer"){
$type = "int";
}
$this->soapTypes = $soapTypes;
$this->name = $name;
$this->value = "";
$this->type = $type;
$this->type_code = 0;
$this->type_prefix = false;
$this->array_type = "";
$this->debug_flag = true;
$this->debug_str = "";
$this->debug("Entering soapval - name: '$name' type: '$type' value: $value");
if($namespace){
$this->namespace = $namespace;
if(!isset($namespaces[$namespace])){
$namespaces[$namespace] = "ns".(count($namespaces)+1);
}
$this->prefix = $namespaces[$namespace];
}
// get type prefix
if(ereg(":",$type)){
$this->type = substr(strrchr($type,":"),1,strlen(strrchr($type,":")));
$this->type_prefix = substr($type,0,strpos($type,":"));
} elseif($type_namespace){
if(!isset($namespaces[$type_namespace])){
$namespaces[$type_namespace] = "ns".(count($namespaces)+1);
}
$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)){
// try to get type prefix from typeMap
if(!$ns = $this->verify_type($type)){
// else default to method namespace
$this->type_prefix = $namespaces[$methodNamespace];
} else {
$this->type_prefix = $namespaces[$ns];
}
}
// if scalar
if(in_array($this->type,$typemap[$XMLSchemaVersion])) {
$this->type_code = 1;
$this->addScalar($value,$this->type,$name);
// if array
} elseif(eregi("^(array|ur-type)$",$this->type)){
$this->type_code = 2;
$this->addArray($value);
// if struct
} elseif(eregi("struct",$this->type)){
$this->type_code = 3;
$this->addStruct($value);
} elseif(is_array($value)) {
$this->type_code = 3;
$this->addStruct($value);
} else {
$this->type_code = 1;
$this->addScalar($value,"string",$name);
}
}
function addScalar($value, $type, $name=""){
$this->debug("adding scalar '$name' of type '$type'");
$this->value = $value;
return true;
}
function addArray($vals){
$this->debug("adding array '$this->name' with ".count($vals)." vals");
$this->value = array();
if(is_array($vals) && count($vals) >= 1){
foreach($vals as $k => $v){
$this->debug("checking value $k : $v");
// if soapval, add..
if(get_class($v) == "soapval"){
$this->value[] = $v;
$this->debug($v->debug_str);
// else make obj and serialize
} else {
if(is_array($v)){
if(ereg("[a-zA-Z\-]*",key($v))){
$type = "struct";
} else {
$type = "array";
}
} elseif(!ereg("^[0-9]+$",$k) && $this->verify_type($k)){
$type = $k;
} elseif(is_int($v)){
$type = "int";
} elseif(is_float($v) || $v == "NaN" || $v == "INF"){
$type = "float";
} else {
$type = gettype($v);
}
$new_val = new soapval("item",$type,$v);
$this->debug($new_val->debug_str);
$this->value[] = $new_val;
}
}
}
return true;
}
function addStruct($vals){
$this->debug("adding struct '$this->name' with ".count($vals)." vals");
if(is_array($vals) && count($vals) >= 1){
foreach($vals as $k => $v){
// if serialize, if soapval
if(get_class($v) == "soapval"){
$this->value[] = $v;
$this->debug($v->debug_str);
// else make obj and serialize
} else {
if(is_array($v)){
foreach($v as $a => $b){
if($a == "0"){
$type = "array";
} else {
$type = "struct";
}
break;
}
} elseif($this->verify_type($k)){
$this->debug("got type '$type' for value '$v' from typemap!");
$type = $k;
} elseif(is_int($v)){
$type = "int";
} elseif(0&&(is_float($v) || $v == "NaN" || $v == "INF")){//MODIFIED: Mike Agar, to work with Google
$type = "float";
} else {
$type = gettype($v);
if($type=="boolean"){//MODIFIED: Mike Agar, to work with Google
switch($v){
case 0:
case false:
case "":
$v="false";
break;
default:
$v="true";
break;
}
}
$this->debug("got type '$type' for value '$v' from php gettype()!");
}
$new_val = new soapval($k,$type,$v);
$this->debug($new_val->debug_str);
$this->value[] = $new_val;
}
}
} else {
$this->value = array();
}
return true;
}
// turn soapvals into xml, woohoo!
function serializeval($soapval=false) {
if(!$soapval){
$soapval = $this;
}
$this->debug("serializing '$soapval->name' of type '$soapval->type'");
if(is_int($soapval->name)){
$soapval->name = "item";
}
switch($soapval->type_code) {
case 3:
// struct
$this->debug("got a struct");
if($soapval->prefix && $soapval->type_prefix){
$xml .= "<$soapval->prefix:$soapval->name xsi:type=\"$soapval->type_prefix:$soapval->type\">\n";
} elseif($soapval->type_prefix){
$xml .= "<$soapval->name xsi:type=\"$soapval->type_prefix:$soapval->type\">\n";
} elseif($soapval->prefix){
$xml .= "<$soapval->prefix:$soapval->name>\n";
} else {
$xml .= "<$soapval->name>\n";
}
if(is_array($soapval->value)){
foreach($soapval->value as $k => $v){
$xml .= $this->serializeval($v);
}
}
if($soapval->prefix){
$xml .= "$soapval->prefix:$soapval->name>\n";
} else {
$xml .= "$soapval->name>\n";
}
break;
case 2:
// array
foreach($soapval->value as $array_val){
$array_types[$array_val->type] = 1;
$xml .= $this->serializeval($array_val);
}
if(count($array_types) > 1){
$array_type = "xsd:ur-type";
} elseif(count($array_types) >= 1){
if($array_val->type_prefix != ""){
$array_type = $array_val->type_prefix.":".$array_val->type;
} else {
$array_type = $array_val->type;
}
}
$xml = "<$soapval->name xsi:type=\"SOAP-ENC:Array\" SOAP-ENC:arrayType=\"".$array_type."[".sizeof($soapval->value)."]\">\n".$xml."$soapval->name>\n";
break;
case 1:
$xml .= "<$soapval->name xsi:type=\"$soapval->type_prefix:$soapval->type\">$soapval->value$soapval->name>\n";
break;
default:
break;
}
return $xml;
}
// serialize
function serialize() {
return $this->serializeval($this);
}
function decode($soapval=false){
if(!$soapval){
$soapval = $this;
}
$this->debug("inside soapval->decode for $soapval->name of type $soapval->type and value: $soapval->value");
// scalar decode
if($soapval->type_code == 1){
return $soapval->value;
// array decode
} elseif($soapval->type_code == 2){
if(is_array($soapval->value)){
foreach($soapval->value as $item){
$return[] = $this->decode($item);
}
return $return;
} else {
return array();
}
// struct decode
} elseif($soapval->type_code == 3){
if(is_array($soapval->value)){
foreach($soapval->value as $item){
$return[$item->name] = $this->decode($item);
}
return $return;
} else {
return array();
}
}
}
// pass it a type, and it attempts to return a namespace uri
function verify_type($type){
global $typemap,$namespaces,$XMLSchemaVersion;
/*foreach($typemap as $namespace => $types){
if(is_array($types) && in_array($type,$types)){
return $namespace;
}
}*/
foreach($namespaces as $uri => $prefix){
if(is_array($typemap[$uri]) && in_array($type,$typemap[$uri])){
return $uri;
}
}
return false;
}
// alias for verify_type() - pass it a type, and it returns it's prefix
function get_prefix($type){
if($prefix = $this->verify_type($type)){
return $prefix;
}
return false;
}
function debug($string){
if($this->debug_flag){
$this->debug_str .= "soapval: $string\n";
}
}
}
//----------------------------------------------------------------------------
class soap_parser {
//----------------------------------------------------------------------------
function soap_parser($xml,$encoding="UTF-8"){
//global $soapTypes;
//$this->soapTypes = $soapTypes;
$this->xml = $xml;
$this->xml_encoding = $encoding;
$this->root_struct = "";
// determines where in the message we are (envelope,header,body,method)
$this->status = "";
$this->position = 0;
$this->pos_stat = 0;
$this->depth = 0;
$this->default_namespace = "";
$this->namespaces = array();
$this->message = array();
$this->fault = false;
$this->fault_code = "";
$this->fault_str = "";
$this->fault_detail = "";
$this->depth_array = array();
$this->debug_flag = true;
$this->debug_str = "";
$this->previous_element = "";
$this->soapresponse = NULL;
$this->entities = array ( "&" => "&", "<" => "<", ">" => ">",
"'" => "'", '"' => """ );
// Check whether content has been read.
if(!empty($xml)){
$this->debug("Entering soap_parser()");
//$this->debug("DATA DUMP:\n\n$xml");
// Create an XML parser.
$this->parser = xml_parser_create($this->xml_encoding);
// Set the options for parsing the XML data.
//xml_parser_set_option($parser, XML_OPTION_SKIP_WHITE, 1);
xml_parser_set_option($this->parser, XML_OPTION_CASE_FOLDING, 0);
// Set the object for the parser.
xml_set_object($this->parser, $this);
// Set the element handlers for the parser.
xml_set_element_handler($this->parser, "start_element","end_element");
xml_set_character_data_handler($this->parser,"character_data");
xml_set_default_handler($this->parser, "default_handler");
// Parse the XML file.
if(!xml_parse($this->parser,$xml,true)){
// Display an error message.
$this->debug(sprintf("XML error on line %d: %s",
xml_get_current_line_number($this->parser),
xml_error_string(xml_get_error_code($this->parser))));
$this->fault = true;
} else {
// get final value
$this->soapresponse = $this->build_response($this->root_struct);
}
xml_parser_free($this->parser);
} else {
$this->debug("xml was empty, didn't parse!");
}
}
// loop through msg, building response structures
function build_response($pos) {
$response = NULL;
if($this->message[$pos]["children"] != ""){
$this->debug("children string = ".$this->message[$pos]["children"]);
$children = explode("|",$this->message[$pos]["children"]);
$this->debug("it has ".count($children)." children");
foreach($children as $c => $child_pos){
//$this->debug("child pos $child_pos: ".$this->message[$child_pos]["name"]);
if ($this->message[$child_pos]["type"] != NULL) {
$this->debug("entering build_response() for ".$this->message[$child_pos]["name"].", array pos $c, pos: $child_pos");
$response[] = $this->build_response($child_pos);
}
}
}
// add current node's value
if ($response) {
$response = new soapval($this->message[$pos]["name"], $this->message[$pos]["type"] , $response);
} else {
$this->debug("inside buildresponse: creating soapval ".$this->message[$pos]["name"]." of type ".$this->message[$pos]["type"]." and value: ".$this->message[$pos]["cdata"]);
$response = new soapval($this->message[$pos]["name"], $this->message[$pos]["type"] , $this->message[$pos]["cdata"]);
}
return $response;
}
// start-element handler
function start_element($parser, $name, $attrs) {
// position in a total number of elements, starting from 0
// update class level pos
$pos = $this->position++;
// and set mine
$this->message[$pos]["pos"] = $pos;
// parent/child/depth determinations
// depth = how many levels removed from root?
// set mine as current global depth and increment global depth value
$this->message[$pos]["depth"] = $this->depth++;
// else add self as child to whoever the current parent is
if($pos != 0){
$this->message[$this->parent]["children"] .= "|$pos";
}
// set my parent
$this->message[$pos]["parent"] = $this->parent;
// set self as current value for this depth
$this->depth_array[$this->depth] = $pos;
// set self as current parent
$this->parent = $pos;
// set status
if(ereg(":Envelope$",$name)){
$this->status = "envelope";
} elseif(ereg(":Header$",$name)){
$this->status = "header";
} elseif(ereg(":Body$",$name)){
$this->status = "body";
// set method
} elseif($this->status == "body"){
$this->status = "method";
if(ereg(":",$name)){
$this->root_struct_name = substr(strrchr($name,":"),1);
} else {
$this->root_struct_name = $name;
}
$this->root_struct = $pos;
$this->message[$pos]["type"] = "struct";
}
// set my status
$this->message[$pos]["status"] = $this->status;
// set name
$this->message[$pos]["name"] = htmlspecialchars($name);
// set attrs
$this->message[$pos]["attrs"] = $attrs;
// get namespace
if(ereg(":",$name)){
$namespace = substr($name,0,strpos($name,":"));
$this->message[$pos]["namespace"] = $namespace;
$this->default_namespace = $namespace;
} else {
$this->message[$pos]["namespace"] = $this->default_namespace;
}
// loop through atts, logging ns and type declarations
foreach($attrs as $key => $value){
// if ns declarations, add to class level array of valid namespaces
if(ereg("xmlns:",$key)){
$prefix = substr(strrchr($key,":"),1);
if($prefix == "xsd"){
global $XMLSchemaVersion,$namespaces;
$XMLSchemaVersion = $value;
$tmpNS = array_flip($namespaces);
$tmpNS["xsd"] = $XMLSchemaVersion;
$tmpNS["xsi"] = $XMLSchemaVersion."-instance";
$namespaces = array_flip($tmpNS);
}
$this->namespaces[substr(strrchr($key,":"),1)] = $value;
// set method namespace
if($name == $this->root_struct_name){
$this->methodNamespace = $value;
}
// if it's a type declaration, set type
} elseif($key == "xsi:type"){
$this->message[$pos]["type"] = substr(strrchr($value,":"),1);
// should do something here with the namespace of specified type?
} elseif($key == "SOAP-ENC:arrayType"){
$this->message[$pos]['type'] = 'array';
}
}
}
// end-element handler
function end_element($parser, $name) {
// position of current element is equal to the last value left in depth_array for my depth
$pos = $this->depth_array[$this->depth];
// bring depth down a notch
$this->depth--;
// get type if not explicitly declared in an xsi:type attribute
// man is this fucked up. can't do wsdl like dis!
if($this->message[$pos]["type"] == ""){
if($this->message[$pos]["children"] != ""){
$this->message[$pos]["type"] = "SOAPStruct";
} else {
$this->message[$pos]["type"] = "string";
}
}
// set eval str start if it has a valid type and is inside the method
if($pos >= $this->root_struct){
$this->message[$pos]["inval"] = "true";
}
// if in the process of making a soap_val, close the parentheses and move on...
if($this->message[$pos]["inval"] == "true"){
$this->message[$pos]["inval"] == "false";
}
// if tag we are currently closing is the method wrapper
if($pos == $this->root_struct){
$this->status = "body";
} elseif(ereg(":Body",$name)){
$this->status = "header";
} elseif(ereg(":Header",$name)){
$this->status = "envelope";
}
// set parent back to my parent
$this->parent = $this->message[$pos]["parent"];
$this->debug("parsed $name end, type '".$this->message[$pos]["type"]."' children = ".$this->message[$pos]["children"]);
}
// element content handler
function character_data($parser, $data){
$pos = $this->depth_array[$this->depth];
$this->message[$pos]["cdata"] .= $data;
}
// default handler
function default_handler($parser, $data){
//$this->debug("DEFAULT HANDLER: $data");
}
// function to check fault status
function fault(){
if($this->fault){
return true;
} else {
return false;
}
}
// have this return a soap_val object
function get_response(){
if ($this->soapresponse) {
return $this->soapresponse;
} else {
$this->debug("ERROR: did not successfully eval the msg");
$this->fault = true;
return new soapval("Fault","struct",array(new soapval("faultcode","string","SOAP-ENV:Server"),new soapval("faultstring","string","couldn't build response")));
}
}
function debug($string){
if($this->debug_flag){
$this->debug_str .= "soap_parser: $string\n";
}
}
function decode_entities($text){
foreach($this->entities as $entity => $encoded){
$text = str_replace($encoded,$entity,$text);
}
return $text;
}
} // end class soap_parser
/* soapx4 high level class
usage:
// instantiate client with server info
$soapclient = new soapclient( string path [ ,boolean wsdl] );
// call method, get results
echo $soapclient->call( string methodname [ ,array parameters] );
// bye bye client
unset($soapclient);
*/
//----------------------------------------------------------------------------
class soapclient {
//----------------------------------------------------------------------------
var $fault, $faultcode, $faultstring, $faultdetail;
function soapclient($endpoint,$wsdl=false,$portName=false){
$this->debug_flag = false;
$this->endpoint = $endpoint;
$this->portName = false;
// make values
if($wsdl){
$this->endpointType = "wsdl";
$this->wsdlFile = $this->endpoint;
// instantiate wsdl class
$this->wsdl = new wsdl($this->endpoint);
if($portName){
$this->portName = $portName;
}
}
}
function call($method,$params=array(),$namespace=false,$soapAction=false){
if($this->endpointType == "wsdl"){
// get portName
if(!$this->portName){
$this->portName = $this->wsdl->getPortName($method);
}
// get endpoint
if(!$this->endpoint = $this->wsdl->getEndpoint($this->portName)){
die("no port of name '$this->portName' in the wsdl at that location!");
}
$this->debug("endpoint: $this->endpoint");
$this->debug("portName: $this->portName");
// get operation data
if($opData = $this->wsdl->getOperationData($this->portName,$method)){
$soapAction = $opData["soapAction"];
// set input params
$i = count($opData["input"]["parts"])-1;
foreach($opData["input"]["parts"] as $name => $type){
if(isset($params[$name])){
$nparams[$name] = $params[$name];
} else {
$nparams[$name] = $params[$i];
}
}
$params = $nparams;
} else {
die("could not get operation info from wsdl for operation: $method
");
}
}
$this->debug("soapAction: $soapAction");
// get namespace
if(!$namespace){
if($this->endpointType != "wsdl"){
//die("method call requires namespace if wsdl is not available!");
} elseif(!$namespace = $this->wsdl->getNamespace($this->portName,$method)){
//die("no namespace found in wsdl for operation: $method!");
}
}
$this->debug("namespace: $namespace");
// make message
$soapmsg = new soapmsg($method,$params,$namespace);
$this->debug( ereg_replace("\n","","
".$soapmsg->serialize().""));
// instantiate client
$dbg = "calling server at '$this->endpoint'...";
if($soap_client = new soap_client($this->endpoint)){
if($this->debug_flag){
$soap_client->debug_flag = true;
}
$this->debug($dbg."instantiated client successfully");
$this->debug("server: $soap_client->server
path: $soap_client->path
port: $soap_client->port");
// send
$dbg = "sending msg w/ soapaction '$soapAction'...";
if($return = $soap_client->send($soapmsg,$soapAction)){
$this->debug($soap_client->debug_str);
$this->request = $soap_client->outgoing_payload;
$this->response = $soap_client->incoming_payload;
$this->debug($dbg."sent message successfully and got a(n) ".gettype($return)." back");
// check for valid response
if(get_class($return) == "soapval"){
// fault?
if(eregi("fault",$return->name)){
$this->debug("got fault");
$this->fault = true;
$faultArray = $return->decode();
foreach($faultArray as $k => $v){
//print "$k = $v
";
if ($k == "faultcode") $this->faultcode = $v;
if ($k == "faultstring") $this->faultstring = $v;
if ($k == "faultdetail") $this->faultdetail = $v;
$this->debug("$k = $v
");
}
return false;
} else {
// decode to native php datatype
$returnArray = $return->decode();
// return array of return values
if(is_array($returnArray)){
return array_shift($returnArray);
// why is decode only returning an array, instead of the actual return vals?
} else {
$this->debug("didn't get array back from decode() for $return->name");
return false;
}
}
} else {
$this->debug("didn't get soapval object back from client");
return false;
}
} else {
$this->debug("client send/recieve error");
return false;
}
} else {
$this->debug("unable to instantiate client object");
return false;
}
}
function debug($string){
if($this->debug_flag){
$this->debug_data .= "soapclient: $string\n";
}
}
} // end class soapclient
/*
this is a class that loads a wsdl file and makes it's data available to an application
it should provide methods that allow both client and server usage of it
also should have methods for creating a wsdl file from scratch and
serializing wsdl into valid markup
*/
//----------------------------------------------------------------------------
class wsdl
{
//----------------------------------------------------------------------------
// constructor
function wsdl($wsdl=false){
// define internal arrays of bindings, ports, operations, messages, etc.
$this->complexTypes = array();
$this->messages = array();
$this->currentMessage;
$this->currentOperation;
$this->portTypes = array();
$this->currentPortType;
$this->bindings = array();
$this->currentBinding;
$this->ports = array();
$this->currentPort;
// debug switch
$this->debug_flag = false;
// parser vars
$this->parser;
$this->position;
$this->depth;
$this->depth_array = array();
// Check whether content has been read.
if($wsdl){
$wsdl_string = join("",file($wsdl));
// Create an XML parser.
$this->parser = xml_parser_create();
// Set the options for parsing the XML data.
//xml_parser_set_option($parser, XML_OPTION_SKIP_WHITE, 1);
xml_parser_set_option($this->parser, XML_OPTION_CASE_FOLDING, 0);
// Set the object for the parser.
xml_set_object($this->parser, $this);
// Set the element handlers for the parser.
xml_set_element_handler($this->parser, "start_element","end_element");
xml_set_character_data_handler($this->parser,"character_data");
//xml_set_default_handler($this->parser, "default_handler");
// Parse the XML file.
if(!xml_parse($this->parser,$wsdl_string,true)){
// Display an error message.
$this->debug(sprintf("XML error on line %d: %s",
xml_get_current_line_number($this->parser),
xml_error_string(xml_get_error_code($this->parser))));
$this->fault = true;
}
xml_parser_free($this->parser);
}
} // end function wsdl
// start-element handler
function start_element($parser, $name, $attrs) {
// position in the total number of elements, starting from 0
$pos = $this->position++;
$depth = $this->depth++;
// set self as current value for this depth
$this->depth_array[$depth] = $pos;
// find status, register data
switch($this->status){
case "types":
switch($name){
case "schema":
$this->schema = true;
break;
case "complexType":
$this->currentElement = $attrs["name"];
$this->schemaStatus = "complexType";
break;
case "element":
$this->complexTypes[$this->currentElement]["elements"][$attrs["name"]] = $attrs;
break;
case "complexContent":
break;
case "restriction":
$this->complexTypes[$this->currentElement]["restrictionBase"] = $attrs["base"];
break;
case "sequence":
$this->complexTypes[$this->currentElement]["order"] = "sequence";
break;
case "all":
$this->complexTypes[$this->currentElement]["order"] = "all";
break;
case "attribute":
if($attrs["ref"]){
$this->complexTypes[$this->currentElement]["attrs"][$attrs["ref"]] = $attrs;
} elseif($attrs["name"]){
$this->complexTypes[$this->currentElement]["attrs"][$attrs["name"]] = $attrs;
}
break;
}
break;
case "message":
if($name == "part"){
$this->messages[$this->currentMessage][$attrs["name"]] = $attrs["type"];
}
break;
case "portType":
switch($name){
case "operation":
$this->currentOperation = $attrs["name"];
$this->portTypes[$this->currentPortType][$attrs["name"]]["parameterOrder"] = $attrs["parameterOrder"];
break;
default:
$this->portTypes[$this->currentPortType][$this->currentOperation][$name]= $attrs;
break;
}
break;
case "binding":
switch($name){
case "soap:binding":
$this->bindings[$this->currentBinding] = array_merge($this->bindings[$this->currentBinding],$attrs);
break;
case "operation":
$this->currentOperation = $attrs["name"];
$this->bindings[$this->currentBinding]["operations"][$attrs["name"]] = array();
break;
case "soap:operation":
$this->bindings[$this->currentBinding]["operations"][$this->currentOperation]["soapAction"] = $attrs["soapAction"];
break;
case "input":
$this->opStatus = "input";
case "soap:body":
$this->bindings[$this->currentBinding]["operations"][$this->currentOperation][$this->opStatus] = $attrs;
break;
case "output":
$this->opStatus = "output";
break;
}
break;
case "service":
switch($name){
case "port":
$this->currentPort = $attrs["name"];
$this->ports[$attrs["name"]] = $attrs;
break;
case "soap:address":
$this->ports[$this->currentPort]["location"] = $attrs["location"];
break;
}
break;
} // end switch
// set status
switch($name){
case "types":
$this->status = "types";
break;
case "message":
$this->status = "message";
$this->messages[$attrs["name"]] = array();
$this->currentMessage = $attrs["name"];
break;
case "portType":
$this->status = "portType";
$this->portTypes[$attrs["name"]] = array();
$this->currentPortType = $attrs["name"];
break;
case "binding":
$this->status = "binding";
$this->currentBinding = $attrs["name"];
$this->bindings[$attrs["name"]]["type"] = $attrs["type"];
break;
case "service":
$this->serviceName = $attrs["name"];
$this->status = "service";
break;
case "definitions":
foreach ($attrs as $name=>$value) {
$this->wsdl_info[$name]=$value;
}
break;
}
// get element prefix
if(ereg(":",$name)){
$prefix = substr($name,0,strpos($name,":"));
}
} // end function start_element
function getEndpoint($portName){
if($endpoint = $this->ports[$portName]["location"]){
return $endpoint;
}
return false;
}
// find the name of the first port that contains an operation of name $operation
function getPortName($operation){
foreach($this->ports as $port => $portAttrs){
$binding = substr($portAttrs["binding"],4);
if($this->bindings[$binding]["operations"][$operation] != ""){
return $port;
}
}
}
function getOperationData($portName,$operation){
if($binding = substr($this->ports[$portName]["binding"],4)){
// get operation data from binding
if(is_array($this->bindings[$binding]["operations"][$operation])){
$opData = $this->bindings[$binding]["operations"][$operation];
}
// get operation data from porttype
$portType = substr(strstr($this->bindings[$binding]["type"],":"),1);
if(is_array($this->portTypes[$portType][$operation])){
$opData["parameterOrder"] = $this->portTypes[$portType][$operation]["parameterOrder"];
$opData["input"] = array_merge($opData["input"],$this->portTypes[$portType][$operation]["input"]);
$opData["output"] = array_merge($opData["output"],$this->portTypes[$portType][$operation]["output"]);
}
// message data from messages
$inputMsg = substr(strstr($opData["input"]["message"],":"),1);
$opData["input"]["parts"] = $this->messages[$inputMsg];
$outputMsg = substr(strstr($opData["output"]["message"],":"),1);
$opData["output"]["parts"] = $this->messages[$outputMsg];
}
return $opData;
}
function getSoapAction($portName,$operation){
if($binding = substr($this->ports[$portName]["binding"],4)){
if($soapAction = $this->bindings[$binding]["operations"][$operation]["soapAction"]){
return $soapAction;
}
return false;
}
return false;
}
function getNamespace($portName,$operation){
if($binding = substr($this->ports[$portName]["binding"],4)){
//$this->debug("looking for namespace using binding '$binding', port '$portName', operation '$operation'");
if($namespace = $this->bindings[$binding]["operations"][$operation]["input"]["namespace"]){
return $namespace;
}
return false;
}
return false;
}
// end-element handler
function end_element($parser, $name) {
// position of current element is equal to the last value left in depth_array for my depth
$pos = $this->depth_array[$this->depth];
// bring depth down a notch
$this->depth--;
}
// element content handler
function character_data($parser, $data){
$pos = $this->depth_array[$this->depth];
$this->message[$pos]["cdata"] .= $data;
}
function debug($string){
if($this->debug_flag){
$this->debug_str .= "wsdl: $string\n";
}
}
// }
// xsd:dateTime helpers
function timestamp_to_iso8601($timestamp){
$datestr = date("Y-m-d\TH:i:sO",$timestamp);
return $datestr;
}
function iso8601_to_timestamp($datestr)
{
$eregStr =
"([0-9]{4})-". // centuries & years CCYY-
"([0-9]{2})-". // months MM-
"([0-9]{2})". // days DD
"T". // separator T
"([0-9]{2}):". // hours hh:
"([0-9]{2}):". // minutes mm:
"([0-9]{2})(\.[0-9]*)?". // seconds ss.ss...
"(Z|[+\-][0-9]{4})"; // Z to indicate UTC, -/+HH:MM:SS.SS... for local tz's
if(ereg($eregStr,$datestr,$regs)){
if($regs[8] != "Z"){
$op = substr($regs[8],0,1);
$h = substr($regs[8],1,2);
$m = substr($regs[8],3,2);
if($op == "-"){
$regs[4] = $regs[4] - $h;
$regs[5] = $regs[5] - $m;
} elseif($op == "+"){
$regs[4] = $regs[4] + $h;
$regs[5] = $regs[5] + $m;
}
}
return strtotime("$regs[1]-$regs[2]-$regs[3] $regs[4]:$regs[5]:$regs[6]Z");
}
else
{
return false;
}
}
} // end class
//----------------------------------------------------------------------------
// classe Google API Search
//----------------------------------------------------------------------------
class GoogleApiSearch
{
function doGoogleSearch($google_registration_key, $search, $start)
{
$soapDebug = false;
$maxResults = (int)10;
if ($soapDebug) {
echo "Begin SOAP:
";
}
$query = array();
$query["key"] = $google_registration_key;
if ($soapDebug) {
echo "Google Registration Key: ".$query["key"]."
";
}
$query["q"] = $search;
$query["start"] = (int)$start;
$query["maxResults"] = $maxResults;
$query["filter"] = (boolean)true;
$query["restrict"]="";
$query["safeSearch"]=(boolean)false;
$query["lr"]="";
$query["ie"]="UTF-8";
$query["oe"]="UTF-8";
$soapclient = new soapclient("http://api.google.com/search/beta2");
if ($soapDebug) {
$soapclient->debug_flag = true;
}
$google_results = $soapclient->call("doGoogleSearch",$query,"urn:GoogleSearch","doGoogleSearch");
if ($soapDebug){
echo nl2br($soapclient->debug_data);
echo "
Result:
";
$this->renderArray($google_results,"google_results");
echo "
";
echo "End SOAP
";
}
//
// Begin Generating the Google Results
//
if (is_array($google_results))
{
// The return value
$outArray = array();
$outArray = $google_results;
}
else
{
$outArray = false;
}
/////////////////////////////////////////////////////////////////////
return $outArray;
} // fn doGoogleSearch
}
}
?>