236 lines
7.0 KiB
PHP
236 lines
7.0 KiB
PHP
<?php
|
|
namespace IXR\Client;
|
|
|
|
use IXR\Exception\ClientException;
|
|
use IXR\Message\Message;
|
|
use IXR\Request\Request;
|
|
|
|
/**
|
|
* Client for communicating with a XML-RPC Server over HTTPS.
|
|
*
|
|
* @author Jason Stirk <jstirk@gmm.com.au> (@link http://blog.griffin.homelinux.org/projects/xmlrpc/)
|
|
* @version 0.2.0 26May2005 08:34 +0800
|
|
* @copyright (c) 2004-2005 Jason Stirk
|
|
* @package IXR
|
|
*/
|
|
class ClientSSL extends Client
|
|
{
|
|
/**
|
|
* Filename of the SSL Client Certificate
|
|
* @access private
|
|
* @since 0.1.0
|
|
* @var string
|
|
*/
|
|
private $_certFile;
|
|
|
|
/**
|
|
* Filename of the SSL CA Certificate
|
|
* @access private
|
|
* @since 0.1.0
|
|
* @var string
|
|
*/
|
|
private $_caFile;
|
|
|
|
/**
|
|
* Filename of the SSL Client Private Key
|
|
* @access private
|
|
* @since 0.1.0
|
|
* @var string
|
|
*/
|
|
private $_keyFile;
|
|
|
|
/**
|
|
* Passphrase to unlock the private key
|
|
* @access private
|
|
* @since 0.1.0
|
|
* @var string
|
|
*/
|
|
private $_passphrase;
|
|
|
|
/**
|
|
* Constructor
|
|
* @param string $server URL of the Server to connect to
|
|
* @since 0.1.0
|
|
*/
|
|
public function __construct($server, $path = false, $port = 443, $timeout = false, $timeout_io = null)
|
|
{
|
|
parent::__construct($server, $path, $port, $timeout, $timeout_io);
|
|
$this->useragent = 'The Incutio XML-RPC PHP Library for SSL';
|
|
|
|
// Set class fields
|
|
$this->_certFile = false;
|
|
$this->_caFile = false;
|
|
$this->_keyFile = false;
|
|
$this->_passphrase = '';
|
|
}
|
|
|
|
/**
|
|
* Set the client side certificates to communicate with the server.
|
|
*
|
|
* @since 0.1.0
|
|
* @param string $certificateFile Filename of the client side certificate to use
|
|
* @param string $keyFile Filename of the client side certificate's private key
|
|
* @param string $keyPhrase Passphrase to unlock the private key
|
|
* @throws ClientException
|
|
*/
|
|
public function setCertificate($certificateFile, $keyFile, $keyPhrase = '')
|
|
{
|
|
// Check the files all exist
|
|
if (is_file($certificateFile)) {
|
|
$this->_certFile = $certificateFile;
|
|
} else {
|
|
throw new ClientException('Could not open certificate: ' . $certificateFile);
|
|
}
|
|
|
|
if (is_file($keyFile)) {
|
|
$this->_keyFile = $keyFile;
|
|
} else {
|
|
throw new ClientException('Could not open private key: ' . $keyFile);
|
|
}
|
|
|
|
$this->_passphrase = (string)$keyPhrase;
|
|
}
|
|
|
|
public function setCACertificate($caFile)
|
|
{
|
|
if (is_file($caFile)) {
|
|
$this->_caFile = $caFile;
|
|
} else {
|
|
throw new ClientException('Could not open CA certificate: ' . $caFile);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Sets the connection timeout (in seconds)
|
|
* @param int $newTimeOut Timeout in seconds
|
|
* @returns void
|
|
* @since 0.1.2
|
|
*/
|
|
public function setTimeOut($newTimeOut)
|
|
{
|
|
$this->timeout = (int)$newTimeOut;
|
|
}
|
|
|
|
/**
|
|
* Returns the connection timeout (in seconds)
|
|
* @returns int
|
|
* @since 0.1.2
|
|
*/
|
|
public function getTimeOut()
|
|
{
|
|
return $this->timeout;
|
|
}
|
|
|
|
/**
|
|
* Set the query to send to the XML-RPC Server
|
|
* @since 0.1.0
|
|
*/
|
|
public function query()
|
|
{
|
|
$args = func_get_args();
|
|
$method = array_shift($args);
|
|
$request = new Request($method, $args);
|
|
$length = $request->getLength();
|
|
$xml = $request->getXml();
|
|
|
|
$this->debugOutput('<pre>' . htmlspecialchars($xml) . PHP_EOL . '</pre>');
|
|
|
|
//This is where we deviate from the normal query()
|
|
//Rather than open a normal sock, we will actually use the cURL
|
|
//extensions to make the calls, and handle the SSL stuff.
|
|
|
|
$curl = curl_init('https://' . $this->server . $this->path);
|
|
|
|
curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
|
|
|
|
//Since 23Jun2004 (0.1.2) - Made timeout a class field
|
|
curl_setopt($curl, CURLOPT_CONNECTTIMEOUT, $this->timeout);
|
|
if (null !== $this->timeout_io) {
|
|
curl_setopt($curl, CURLOPT_TIMEOUT, $this->timeout_io);
|
|
}
|
|
|
|
if ($this->debug) {
|
|
curl_setopt($curl, CURLOPT_VERBOSE, 1);
|
|
}
|
|
|
|
curl_setopt($curl, CURLOPT_HEADER, 1);
|
|
curl_setopt($curl, CURLOPT_POST, 1);
|
|
curl_setopt($curl, CURLOPT_POSTFIELDS, $xml);
|
|
if($this->port !== 443) {
|
|
curl_setopt($curl, CURLOPT_PORT, $this->port);
|
|
}
|
|
curl_setopt($curl, CURLOPT_HTTPHEADER, [
|
|
"Content-Type: text/xml",
|
|
"Content-length: {$length}"
|
|
]);
|
|
|
|
// Process the SSL certificates, etc. to use
|
|
if (!($this->_certFile === false)) {
|
|
// We have a certificate file set, so add these to the cURL handler
|
|
curl_setopt($curl, CURLOPT_SSLCERT, $this->_certFile);
|
|
curl_setopt($curl, CURLOPT_SSLKEY, $this->_keyFile);
|
|
|
|
if ($this->debug) {
|
|
$this->debugOutput('SSL Cert at : ' . $this->_certFile);
|
|
$this->debugOutput('SSL Key at : ' . $this->_keyFile);
|
|
}
|
|
|
|
// See if we need to give a passphrase
|
|
if (!($this->_passphrase === '')) {
|
|
curl_setopt($curl, CURLOPT_SSLCERTPASSWD, $this->_passphrase);
|
|
}
|
|
|
|
if ($this->_caFile === false) {
|
|
// Don't verify their certificate, as we don't have a CA to verify against
|
|
curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, 0);
|
|
} else {
|
|
// Verify against a CA
|
|
curl_setopt($curl, CURLOPT_CAINFO, $this->_caFile);
|
|
}
|
|
}
|
|
|
|
// Call cURL to do it's stuff and return us the content
|
|
$contents = curl_exec($curl);
|
|
curl_close($curl);
|
|
|
|
// Check for 200 Code in $contents
|
|
if (!strstr($contents, '200 OK')) {
|
|
//There was no "200 OK" returned - we failed
|
|
return $this->handleError(-32300, 'transport error - HTTP status code was not 200');
|
|
}
|
|
|
|
if ($this->debug) {
|
|
$this->debugOutput('<pre>' . htmlspecialchars($contents) . PHP_EOL . '</pre>');
|
|
}
|
|
// Now parse what we've got back
|
|
// Since 20Jun2004 (0.1.1) - We need to remove the headers first
|
|
// Why I have only just found this, I will never know...
|
|
// So, remove everything before the first <
|
|
$contents = substr($contents, strpos($contents, '<'));
|
|
|
|
$this->message = new Message($contents);
|
|
if (!$this->message->parse()) {
|
|
// XML error
|
|
return $this->handleError(-32700, 'parse error. not well formed');
|
|
}
|
|
// Is the message a fault?
|
|
if ($this->message->messageType == 'fault') {
|
|
return $this->handleError($this->message->faultCode, $this->message->faultString);
|
|
}
|
|
|
|
// Message must be OK
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* Debug output, if debug is enabled
|
|
* @param $message
|
|
*/
|
|
private function debugOutput($message)
|
|
{
|
|
if ($this->debug) {
|
|
echo $message . PHP_EOL;
|
|
}
|
|
}
|
|
}
|