[ Index ]

PHP Cross Reference of DokuWiki

title

Body

[close]

/vendor/kissifrot/php-ixr/src/Client/ -> ClientSSL.php (source)

   1  <?php
   2  namespace IXR\Client;
   3  
   4  use IXR\Exception\ClientException;
   5  use IXR\Message\Message;
   6  use IXR\Request\Request;
   7  
   8  /**
   9   * Client for communicating with a XML-RPC Server over HTTPS.
  10   *
  11   * @author Jason Stirk <jstirk@gmm.com.au> (@link http://blog.griffin.homelinux.org/projects/xmlrpc/)
  12   * @version 0.2.0 26May2005 08:34 +0800
  13   * @copyright (c) 2004-2005 Jason Stirk
  14   * @package IXR
  15   */
  16  class ClientSSL extends Client
  17  {
  18      /**
  19       * Filename of the SSL Client Certificate
  20       * @access private
  21       * @since 0.1.0
  22       * @var string
  23       */
  24      private $_certFile;
  25  
  26      /**
  27       * Filename of the SSL CA Certificate
  28       * @access private
  29       * @since 0.1.0
  30       * @var string
  31       */
  32      private $_caFile;
  33  
  34      /**
  35       * Filename of the SSL Client Private Key
  36       * @access private
  37       * @since 0.1.0
  38       * @var string
  39       */
  40      private $_keyFile;
  41  
  42      /**
  43       * Passphrase to unlock the private key
  44       * @access private
  45       * @since 0.1.0
  46       * @var string
  47       */
  48      private $_passphrase;
  49  
  50      /**
  51       * Constructor
  52       * @param string $server URL of the Server to connect to
  53       * @since 0.1.0
  54       */
  55      public function __construct($server, $path = false, $port = 443, $timeout = false, $timeout_io = null)
  56      {
  57          parent::__construct($server, $path, $port, $timeout, $timeout_io);
  58          $this->useragent = 'The Incutio XML-RPC PHP Library for SSL';
  59  
  60          // Set class fields
  61          $this->_certFile = false;
  62          $this->_caFile = false;
  63          $this->_keyFile = false;
  64          $this->_passphrase = '';
  65      }
  66  
  67      /**
  68       * Set the client side certificates to communicate with the server.
  69       *
  70       * @since 0.1.0
  71       * @param string $certificateFile Filename of the client side certificate to use
  72       * @param string $keyFile         Filename of the client side certificate's private key
  73       * @param string $keyPhrase       Passphrase to unlock the private key
  74       * @throws ClientException
  75       */
  76      public function setCertificate($certificateFile, $keyFile, $keyPhrase = '')
  77      {
  78          // Check the files all exist
  79          if (is_file($certificateFile)) {
  80              $this->_certFile = $certificateFile;
  81          } else {
  82              throw new ClientException('Could not open certificate: ' . $certificateFile);
  83          }
  84  
  85          if (is_file($keyFile)) {
  86              $this->_keyFile = $keyFile;
  87          } else {
  88              throw new ClientException('Could not open private key: ' . $keyFile);
  89          }
  90  
  91          $this->_passphrase = (string)$keyPhrase;
  92      }
  93  
  94      public function setCACertificate($caFile)
  95      {
  96          if (is_file($caFile)) {
  97              $this->_caFile = $caFile;
  98          } else {
  99              throw new ClientException('Could not open CA certificate: ' . $caFile);
 100          }
 101      }
 102  
 103      /**
 104       * Sets the connection timeout (in seconds)
 105       * @param int $newTimeOut Timeout in seconds
 106       * @returns void
 107       * @since 0.1.2
 108       */
 109      public function setTimeOut($newTimeOut)
 110      {
 111          $this->timeout = (int)$newTimeOut;
 112      }
 113  
 114      /**
 115       * Returns the connection timeout (in seconds)
 116       * @returns int
 117       * @since 0.1.2
 118       */
 119      public function getTimeOut()
 120      {
 121          return $this->timeout;
 122      }
 123  
 124      /**
 125       * Set the query to send to the XML-RPC Server
 126       * @since 0.1.0
 127       */
 128      public function query()
 129      {
 130          $args = func_get_args();
 131          $method = array_shift($args);
 132          $request = new Request($method, $args);
 133          $length = $request->getLength();
 134          $xml = $request->getXml();
 135  
 136          $this->debugOutput('<pre>' . htmlspecialchars($xml) . PHP_EOL . '</pre>');
 137  
 138          //This is where we deviate from the normal query()
 139          //Rather than open a normal sock, we will actually use the cURL
 140          //extensions to make the calls, and handle the SSL stuff.
 141  
 142          $curl = curl_init('https://' . $this->server . $this->path);
 143  
 144          curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
 145  
 146          //Since 23Jun2004 (0.1.2) - Made timeout a class field
 147          curl_setopt($curl, CURLOPT_CONNECTTIMEOUT, $this->timeout);
 148          if (null !== $this->timeout_io) {
 149              curl_setopt($curl, CURLOPT_TIMEOUT, $this->timeout_io);
 150          }
 151  
 152          if ($this->debug) {
 153              curl_setopt($curl, CURLOPT_VERBOSE, 1);
 154          }
 155  
 156          curl_setopt($curl, CURLOPT_HEADER, 1);
 157          curl_setopt($curl, CURLOPT_POST, 1);
 158          curl_setopt($curl, CURLOPT_POSTFIELDS, $xml);
 159          if($this->port !== 443) {
 160              curl_setopt($curl, CURLOPT_PORT, $this->port);
 161          }
 162          curl_setopt($curl, CURLOPT_HTTPHEADER, [
 163              "Content-Type: text/xml",
 164              "Content-length: {$length}"
 165          ]);
 166  
 167          // Process the SSL certificates, etc. to use
 168          if (!($this->_certFile === false)) {
 169              // We have a certificate file set, so add these to the cURL handler
 170              curl_setopt($curl, CURLOPT_SSLCERT, $this->_certFile);
 171              curl_setopt($curl, CURLOPT_SSLKEY, $this->_keyFile);
 172  
 173              if ($this->debug) {
 174                  $this->debugOutput('SSL Cert at : ' . $this->_certFile);
 175                  $this->debugOutput('SSL Key at : ' . $this->_keyFile);
 176              }
 177  
 178              // See if we need to give a passphrase
 179              if (!($this->_passphrase === '')) {
 180                  curl_setopt($curl, CURLOPT_SSLCERTPASSWD, $this->_passphrase);
 181              }
 182  
 183              if ($this->_caFile === false) {
 184                  // Don't verify their certificate, as we don't have a CA to verify against
 185                  curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, 0);
 186              } else {
 187                  // Verify against a CA
 188                  curl_setopt($curl, CURLOPT_CAINFO, $this->_caFile);
 189              }
 190          }
 191  
 192          // Call cURL to do it's stuff and return us the content
 193          $contents = curl_exec($curl);
 194          curl_close($curl);
 195  
 196          // Check for 200 Code in $contents
 197          if (!strstr($contents, '200 OK')) {
 198              //There was no "200 OK" returned - we failed
 199              return $this->handleError(-32300, 'transport error - HTTP status code was not 200');
 200          }
 201  
 202          if ($this->debug) {
 203              $this->debugOutput('<pre>' . htmlspecialchars($contents) . PHP_EOL . '</pre>');
 204          }
 205          // Now parse what we've got back
 206          // Since 20Jun2004 (0.1.1) - We need to remove the headers first
 207          // Why I have only just found this, I will never know...
 208          // So, remove everything before the first <
 209          $contents = substr($contents, strpos($contents, '<'));
 210  
 211          $this->message = new Message($contents);
 212          if (!$this->message->parse()) {
 213              // XML error
 214              return $this->handleError(-32700, 'parse error. not well formed');
 215          }
 216          // Is the message a fault?
 217          if ($this->message->messageType == 'fault') {
 218              return $this->handleError($this->message->faultCode, $this->message->faultString);
 219          }
 220  
 221          // Message must be OK
 222          return true;
 223      }
 224  
 225      /**
 226       * Debug output, if debug is enabled
 227       * @param $message
 228       */
 229      private function debugOutput($message)
 230      {
 231          if ($this->debug) {
 232              echo $message . PHP_EOL;
 233          }
 234      }
 235  }