/** * Returns a SOAP XML message that can be sent as a server response. * * @return string */ function message($encoding = SOAP_DEFAULT_ENCODING) { $msg = new SOAP_Base(); $params = array(); $params[] = new SOAP_Value('faultcode', 'QName', SOAP_BASE::SOAPENVPrefix() . ':' . $this->code); $params[] = new SOAP_Value('faultstring', 'string', $this->message); $params[] = new SOAP_Value('faultactor', 'anyURI', $this->error_message_prefix); if (PEAR::getStaticProperty('SOAP_Fault', 'backtrace') && isset($this->backtrace)) { $params[] = new SOAP_Value('detail', 'string', $this->backtrace); } else { $params[] = new SOAP_Value('detail', 'string', $this->userinfo); } $methodValue = new SOAP_Value('{' . SOAP_ENVELOP . '}Fault', 'Struct', $params); $headers = null; return $msg->makeEnvelope($methodValue, $headers, $encoding); }
/** * Constructor * * @param string $name Name of the SOAP value {namespace}name. * @param mixed $type SOAP value {namespace}type. Determined * automatically if not set. * @param mixed $value Value to set * @param integer $mustunderstand Zero or one. * @param mixed $attributes Attributes. */ function SOAP_Header($name = '', $type, $value, $mustunderstand = 0, $attributes = array()) { if (!is_array($attributes)) { $actor = $attributes; $attributes = array(); } parent::SOAP_Value($name, $type, $value, $attributes); if (isset($actor)) { $this->attributes[SOAP_BASE::SOAPENVPrefix() . ':actor'] = $actor; } elseif (!isset($this->attributes[SOAP_BASE::SOAPENVPrefix() . ':actor'])) { $this->attributes[SOAP_BASE::SOAPENVPrefix() . ':actor'] = 'http://schemas.xmlsoap.org/soap/actor/next'; } $this->attributes[SOAP_BASE::SOAPENVPrefix() . ':mustUnderstand'] = (int) $mustunderstand; }
/** * Creates the SOAP envelope with the SOAP envelop data. * * @param SOAP_Value $method SOAP_Value instance with the method name as * the name, and the method arguments as the * value. * @param array $headers A list of additional SOAP_Header objects. * @param string $encoding The charset of the SOAP message. * @param array $options A list of encoding/serialization options. * * @return string The complete SOAP message. */ function makeEnvelope($method, $headers, $encoding = SOAP_DEFAULT_ENCODING, $options = array()) { $smsg = $header_xml = $ns_string = ''; if ($headers) { for ($i = 0, $c = count($headers); $i < $c; $i++) { $header_xml .= $headers[$i]->serialize($this); } $header_xml = sprintf("<%s:Header>\r\n%s\r\n</%s:Header>\r\n", SOAP_BASE::SOAPENVPrefix(), $header_xml, SOAP_BASE::SOAPENVPrefix()); } if (!isset($options['input']) || $options['input'] == 'parse') { if (is_array($method)) { for ($i = 0, $c = count($method); $i < $c; $i++) { $smsg .= $method[$i]->serialize($this); } } else { $smsg = $method->serialize($this); } } else { $smsg = $method; } $body = sprintf("<%s:Body>%s\r\n</%s:Body>\r\n", SOAP_BASE::SOAPENVPrefix(), $smsg, SOAP_BASE::SOAPENVPrefix()); foreach ($this->_namespaces as $k => $v) { $ns_string .= "\r\n " . sprintf('xmlns:%s="%s"', $v, $k); } if ($this->_namespace) { $ns_string .= "\r\n " . sprintf('xmlns="%s"', $this->_namespace); } /* If 'use' == 'literal', do not put in the encodingStyle. This is * denoted by $this->_section5 being false. 'use' can be defined at a * more granular level than we are dealing with here, so this does not * work for all services. */ $xml = sprintf('<?xml version="1.0" encoding="%s"?>%s<%s:Envelope%s', $encoding, "\r\n", SOAP_BASE::SOAPENVPrefix(), $ns_string); if ($this->_section5) { $xml .= "\r\n " . sprintf('%s:encodingStyle="%s"', SOAP_BASE::SOAPENVPrefix(), SOAP_SCHEMA_ENCODING); } $xml .= sprintf('>%s%s%s</%s:Envelope>' . "\r\n", "\r\n", $header_xml, $body, SOAP_BASE::SOAPENVPrefix()); return $xml; }
/** * Sends and receives SOAP data. * * @access public * * @param string Outgoing SOAP data. * @param array Options. * * @return string|SOAP_Fault */ function send($msg, $options = array()) { $this->fault = null; $this->incoming_payload = ''; $this->outgoing_payload = $msg; if (!$this->_validateUrl()) { return $this->fault; } if (!$options || !isset($options['from'])) { return $this->_raiseSoapFault('No From: address to send message with'); } if (isset($options['host'])) { $this->host = $options['host']; } if (isset($options['port'])) { $this->port = $options['port']; } if (isset($options['auth'])) { $this->auth = $options['auth']; } if (isset($options['username'])) { $this->username = $options['username']; } if (isset($options['password'])) { $this->password = $options['password']; } $headers = array(); $headers['From'] = $options['from']; $headers['X-Mailer'] = $this->_userAgent; $headers['MIME-Version'] = '1.0'; $headers['Message-ID'] = md5(time()) . '.soap@' . $this->host; $headers['To'] = $this->urlparts['path']; if (isset($options['soapaction'])) { $headers['Soapaction'] = "\"{$options['soapaction']}\""; } if (isset($options['headers'])) { $headers = array_merge($headers, $options['headers']); } // If the content type is already set, we assume that MIME encoding is // already done. if (isset($headers['Content-Type'])) { $out = $msg; } else { // Do a simple inline MIME encoding. $headers['Content-Disposition'] = 'inline'; $headers['Content-Type'] = "text/xml; charset=\"{$this->encoding}\""; if (isset($options['transfer-encoding'])) { if (strcasecmp($options['transfer-encoding'], 'quoted-printable') == 0) { $headers['Content-Transfer-Encoding'] = $options['transfer-encoding']; $out = $msg; } elseif (strcasecmp($options['transfer-encoding'], 'base64') == 0) { $headers['Content-Transfer-Encoding'] = 'base64'; $out = chunk_split(base64_encode($msg), 76, "\n"); } else { return $this->_raiseSoapFault("Invalid Transfer Encoding: {$options['transfer-encoding']}"); } } else { // Default to base64. $headers['Content-Transfer-Encoding'] = 'base64'; $out = chunk_split(base64_encode($msg)); } } $headers['Subject'] = isset($options['subject']) ? $options['subject'] : 'SOAP Message'; foreach ($headers as $key => $value) { $header_text .= "{$key}: {$value}\n"; } $this->outgoing_payload = $header_text . "\r\n" . $this->outgoing_payload; $mailer_params = array('host' => $this->host, 'port' => $this->port, 'username' => $this->username, 'password' => $this->password, 'auth' => $this->auth); $mailer = new Mail_smtp($mailer_params); $result = $mailer->send($this->urlparts['path'], $headers, $out); if (!PEAR::isError($result)) { $val = new SOAP_Value('Message-ID', 'string', $headers['Message-ID']); } else { $sval[] = new SOAP_Value('faultcode', 'QName', SOAP_BASE::SOAPENVPrefix() . ':Client'); $sval[] = new SOAP_Value('faultstring', 'string', "couldn't send SMTP message to {$this->urlparts['path']}"); $val = new SOAP_Value('Fault', 'Struct', $sval); } $methodValue = new SOAP_Value('Response', 'Struct', array($val)); $this->incoming_payload = $this->makeEnvelope($methodValue, $this->headers, $this->encoding); return $this->incoming_payload; }
function &__decodeRequest($request, $shift = false) { if (!$request) { $decoded = null; return $decoded; } /* Check for valid response. */ if (PEAR::isError($request)) { $fault =& $this->_raiseSoapFault($request); return $fault; } else { if (!is_a($request, 'SOAP_Value')) { $fault =& $this->_raiseSoapFault('Invalid data in server::__decodeRequest'); return $fault; } } /* Decode to native php datatype. */ $requestArray = $this->_decode($request); /* Fault? */ if (PEAR::isError($requestArray)) { $fault =& $this->_raiseSoapFault($requestArray); return $fault; } if (is_object($requestArray) && get_class($requestArray) == 'stdClass') { $requestArray = get_object_vars($requestArray); } elseif ($this->_options['style'] == 'document') { $requestArray = array($requestArray); } if (is_array($requestArray)) { if (isset($requestArray['faultcode']) || isset($requestArray[SOAP_BASE::SOAPENVPrefix() . ':faultcode'])) { $faultcode = $faultstring = $faultdetail = $faultactor = ''; foreach ($requestArray as $k => $v) { if (stristr($k, 'faultcode')) { $faultcode = $v; } if (stristr($k, 'faultstring')) { $faultstring = $v; } if (stristr($k, 'detail')) { $faultdetail = $v; } if (stristr($k, 'faultactor')) { $faultactor = $v; } } $fault =& $this->_raiseSoapFault($faultstring, $faultdetail, $faultactor, $faultcode); return $fault; } /* Return array of return values. */ if ($shift && count($requestArray) == 1) { $decoded = array_shift($requestArray); return $decoded; } return $requestArray; } return $requestArray; }
function addSchemaFromMap(&$map) { if (!$map) { return; } foreach ($map as $_type_name => $_type_def) { list($typens, $type) = $this->_getTypeNs($_type_name); if ($typens == 'xsd') { // cannot add to xsd, lets use method_namespace $typens = 'tns'; } $schema =& $this->_getSchema(array_search($typens, $this->namespaces)); if (!$this->_ifComplexTypeExists($schema['complexType'], $type)) { $ctype =& $schema['complexType'][]; $ctype['attr']['name'] = $type; foreach ($_type_def as $_varname => $_vartype) { if (!is_int($_varname)) { list($_vartypens, $_vartype) = $this->_getTypeNs($_vartype); $ctype['all']['attr'] = ''; $el =& $ctype['all']['element'][]; $el['attr']['name'] = $_varname; $el['attr']['type'] = $_vartypens . ':' . $_vartype; } else { $ctype['complexContent']['attr'] = ''; $ctype['complexContent']['restriction']['attr']['base'] = SOAP_BASE::SOAPENCPrefix() . ':Array'; foreach ($_vartype as $array_type) { list($_vartypens, $_vartype) = $this->_getTypeNs($array_type); $ctype['complexContent']['restriction']['attribute']['attr']['ref'] = SOAP_BASE::SOAPENCPrefix() . ':arrayType'; $ctype['complexContent']['restriction']['attribute']['attr']['wsdl:arrayType'] = $_vartypens . ':' . $_vartype . '[]'; } } } } } }
/** * Converts a complex SOAP_Value into a PHP Array * * @param SOAP_Value $response Value object. * @param boolean $shift * * @return array */ function _decodeResponse($response, $shift = true) { if (!$response) { $decoded = null; return $decoded; } // Check for valid response. if (PEAR::isError($response)) { $fault = $this->_raiseSoapFault($response); return $fault; } elseif (!is_a($response, 'soap_value')) { $fault = $this->_raiseSoapFault("Didn't get SOAP_Value object back from client"); return $fault; } // Decode to native php datatype. $returnArray = $this->_decode($response); // Fault? if (PEAR::isError($returnArray)) { $fault = $this->_raiseSoapFault($returnArray); return $fault; } if (is_object($returnArray) && strcasecmp(get_class($returnArray), 'stdClass') == 0) { $returnArray = get_object_vars($returnArray); } if (is_array($returnArray)) { if (isset($returnArray['faultcode']) || isset($returnArray[SOAP_BASE::SOAPENVPrefix() . ':faultcode'])) { $faultcode = $faultstring = $faultdetail = $faultactor = ''; foreach ($returnArray as $k => $v) { if (stristr($k, 'faultcode')) { $faultcode = $v; } if (stristr($k, 'faultstring')) { $faultstring = $v; } if (stristr($k, 'detail')) { $faultdetail = $v; } if (stristr($k, 'faultactor')) { $faultactor = $v; } } $fault = $this->_raiseSoapFault($faultstring, $faultdetail, $faultactor, $faultcode); return $fault; } // Return array of return values. if ($shift && count($returnArray) == 1) { $decoded = array_shift($returnArray); return $decoded; } return $returnArray; } return $returnArray; }
/** * Initialise the SOAP_WSDL tree (destructive). * * If the object has already been initialised, the only effect * will be to change the tns namespace to the new service name. * * @param $service_name Name of the WSDL <service> * @access private */ function _initialise($service_name) { // Set up the basic namespaces that all WSDL definitions use. $this->wsdl->namespaces['wsdl'] = SCHEMA_WSDL; // WSDL language $this->wsdl->namespaces['soap'] = SCHEMA_SOAP; // WSDL SOAP bindings $this->wsdl->namespaces[$this->tnsPrefix] = 'urn:' . $service_name; // Target namespace $this->wsdl->namespaces['xsd'] = array_search('xsd', $this->_namespaces); // XML Schema $this->wsdl->namespaces[SOAP_BASE::SOAPENCPrefix()] = array_search(SOAP_BASE::SOAPENCPrefix(), $this->_namespaces); // SOAP types // XXX Refactor $namespace/$ns for Shane :-) unset($this->wsdl->ns['urn:' . $service_name]); $this->wsdl->ns += array_flip($this->wsdl->namespaces); // Imports are not implemented in WSDL generation from classes. // *** <wsdl:import> *** }