Welcome Guest, Not a member yet? Register   Sign In
connect to xmlrpc behind http auth
#1

[eluser]nigelb[/eluser]
Is there a way that I can connect via CI xmlrpc client to a CI xmlrpc server which is behind http auth?
#2

[eluser]pistolPete[/eluser]
You probably have to subclass the core class XML_RPC_Client and modify the function sendPayload():
Code:
function sendPayload($msg)
    {    
        $fp = @fsockopen($this->server, $this->port,$this->errno, $this->errstr, $this->timeout);
        
        if ( ! is_resource($fp))
        {
            error_log($this->xmlrpcstr['http_error']);
            $r = new XML_RPC_Response(0, $this->xmlrpcerr['http_error'],$this->xmlrpcstr['http_error']);
            return $r;
        }
        
        if(empty($msg->payload))
        {
            // $msg = XML_RPC_Messages
            $msg->createPayload();
        }
        
        $r = "\r\n";
        $op  = "POST {$this->path} HTTP/1.0$r";
        $op .= "Host: {$this->server}$r";
        $op .= "Content-Type: text/xml$r";
        $op .= "User-Agent: {$this->xmlrpcName}$r";
        
        //Added "basic access authentication":
        $op .= "Authorization: Basic ".base64_encode("$username:$password").$r;
        
        $op .= "Content-Length: ".strlen($msg->payload). "$r$r";
        $op .= $msg->payload;
        

        if ( ! fputs($fp, $op, strlen($op)))
        {
            error_log($this->xmlrpcstr['http_error']);
            $r = new XML_RPC_Response(0, $this->xmlrpcerr['http_error'], $this->xmlrpcstr['http_error']);
            return $r;
        }
        $resp = $msg->parseResponse($fp);
        fclose($fp);
        return $resp;
    }

You'd then have to extend the parent class in order to hand on $username and $password.
#3

[eluser]Rob Pomeroy[/eluser]
Just to expand on pistolPete's excellent suggestion, here's how I implemented the entire extended class (save as application/libraries/MY_Xmlrpc.php):
Code:
<?php (defined('BASEPATH')) OR exit('No direct script access allowed');

/**
* XMLRPC client extension
*
* Adapted from the CodeIgniter Core Classes
* @link    http://codeigniter.com
*
* Description:
* This library extends the CodeIgniter XMLRPC class.
*
* Install this file as application/libraries/MY_Xmlrpc.php
*
**/


/**
* XML-RPC Client class extended to include HTTP authentication capability
* @link        http://ellislab.com/forums/viewthread/111201/
*/
class MY_Xmlrpc extends CI_Xmlrpc {
    function server($url, $port=80)
    {
        if (substr($url, 0, 4) != "http")
        {
            $url = "http://".$url;
        }

        $parts = parse_url($url);

        $path = ( ! isset($parts['path'])) ? '/' : $parts['path'];

        if (isset($parts['query']) && $parts['query'] != '')
        {
            $path .= '?'.$parts['query'];
        }

        $this->client = new MY_XML_RPC_Client($path, $parts['host'], $port); // Use extended XML client class instead of core
    }

  // Pass through HTTP authentication credentials to extended XML client
  function setCredentials($username, $password) {
    $this->client->setCredentials($username, $password);
  }

  
} // END MY_XML_RPC Class

class MY_XML_RPC_Client extends XML_RPC_Client
{
    // Extra variables for authentication
  var $username = '';
    var $password = '';

  function setCredentials($username, $password) {
    $this->username = $username;
    $this->password = $password;
  }
  
  function sendPayload($msg)
    {
        $fp = @fsockopen($this->server, $this->port,$this->errno, $this->errstr, $this->timeout);

        if ( ! is_resource($fp))
        {
            error_log($this->xmlrpcstr['http_error']);
            $r = new XML_RPC_Response(0, $this->xmlrpcerr['http_error'],$this->xmlrpcstr['http_error']);
            return $r;
        }

        if(empty($msg->payload))
        {
            // $msg = XML_RPC_Messages
            $msg->createPayload();
        }

        $r = "\r\n";
        $op  = "POST {$this->path} HTTP/1.0$r";
        $op .= "Host: {$this->server}$r";
        $op .= "Content-Type: text/xml$r";
        $op .= "User-Agent: {$this->xmlrpcName}$r";
    // This is where we're extending the base class, to include HTTP auth (basic)
    if ($this->username != '' && $this->password != '') {
      $op .= "Authorization: Basic ".base64_encode($this->username.':'.$this->password).$r;
    }
        $op .= "Content-Length: ".strlen($msg->payload). "$r$r";
        $op .= $msg->payload;


        if ( ! fputs($fp, $op, strlen($op)))
        {
            error_log($this->xmlrpcstr['http_error']);
            $r = new XML_RPC_Response(0, $this->xmlrpcerr['http_error'], $this->xmlrpcstr['http_error']);
            return $r;
        }
        $resp = $msg->parseResponse($fp);
        fclose($fp);
        return $resp;
    }

} // end class MY_XML_RPC_Client

/* End of file MY_Xmlrpc.php */
/* Location: ./system/applications/libraries/MY_Xmlrpc.php */

You can then call it like this:

Code:
function testRPC() {
    $this->load->library('xmlrpc'); // This auto-loads the custom extension MY_Xmlrpc too.
    $this->xmlrpc->server("http://some.url.or.other/rpc/", 80);
    $this->xmlrpc->setCredentials('my_username', 'my_password');
    $this->xmlrpc->method('my_method');
    $request = array('my_parameter');
    $this->xmlrpc->request($request);
    if ( ! $this->xmlrpc->send_request()) {
      echo $this->xmlrpc->display_error();
    } else {
      // Do neat stuff
    }
  }
#4

[eluser]Neerav[/eluser]
Thank you very much Rob and Pete.

You guys saved my lots of hours. ;-)

Cheers,
Neerav Dobaria
#5

[eluser]Rob Pomeroy[/eluser]
Good to hear. Neerav. :-)




Theme © iAndrew 2016 - Forum software by © MyBB