Skip to content
World Wide Web Server edited this page Jul 4, 2012 · 3 revisions

I needed to use xml-rpc with SSL, so I had to extend some classes that are all inside Xmlrpc.php.

[code] <?php

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);
}

function send_request()
{
    $this->message = new MY_XML_RPC_Message($this->method,$this->data);
    $this->message->debug = $this->debug;

    if ( ! $this->result = $this->client->send($this->message))
    {
        $this->error = $this->result->errstr;
        return FALSE;
    }
    elseif( ! is_object($this->result->val))
    {
        $this->error = $this->result->errstr;
        return FALSE;
    }

    $this->response = $this->result->decode();

    return TRUE;
}

}

class MY_XML_RPC_Client extends XML_RPC_Client {

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

    $ch = curl_init();

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

    $header = array(
        'POST ' . $this->path,
        'Host: ' . $this->server,
        'Content-Type: text/xml',
        'User-Agent: ' . $this->xmlrpcName,
        'Content-Length: ' . strlen($msg->payload)
    );

    if( $this->port == '443' )
    {
        $pre = 'https://';
        curl_setopt( $ch, CURLOPT_SSL_VERIFYPEER, FALSE );
    }
    else
    {
        $pre = 'http://';
    }

    curl_setopt( $ch, CURLOPT_URL, $pre . $this->server . $this->path );
    curl_setopt( $ch, CURLOPT_HEADER, 1 );
    curl_setopt( $ch, CURLOPT_RETURNTRANSFER, 1 );
    curl_setopt( $ch, CURLOPT_POSTFIELDS, $msg->payload ); 
    curl_setopt( $ch, CURLOPT_HTTPHEADER, $header );

    if( $resp = curl_exec&#40; $ch &#41; )
    {
        return $msg->parseResponse( $resp );
    }
    else
    {
        error_log($this->xmlrpcstr['http_error']);
        $r = new XML_RPC_Response(0, $this->xmlrpcerr['http_error'], $this->xmlrpcstr['http_error']);
        return $r;
    }

    curl_close($ch);
}

}

class MY_XML_RPC_Message extends XML_RPC_Message {

function parseResponse($data)
{
    /*$data = '';

    while($datum = fread($fp, 4096))
    {
        $data .= $datum;
    }*/

    //-------------------------------------
    //  DISPLAY HTTP CONTENT for DEBUGGING
    //-------------------------------------

    if ($this->debug === TRUE)
    {
        echo "<pre>";
        echo "---DATA---\n" . htmlspecialchars($data) . "\n---END DATA---\n\n";
        echo "</pre>";
    }

    //-------------------------------------
    //  Check for data
    //-------------------------------------

    if($data == "")
    {
        error_log($this->xmlrpcstr['no_data']);
        $r = new XML_RPC_Response(0, $this->xmlrpcerr['no_data'], $this->xmlrpcstr['no_data']);
        return $r;
    }


    //-------------------------------------
    //  Check for HTTP 200 Response
    //-------------------------------------

    if (strncmp($data, 'HTTP', 4) == 0 && ! preg_match('/^HTTP\/[0-9\.]+ 200 /', $data))
    {
        $errstr= substr($data, 0, strpos($data, "\n")-1);
        $r = new XML_RPC_Response(0, $this->xmlrpcerr['http_error'], $this->xmlrpcstr['http_error']. ' (' . $errstr . ')');
        return $r;
    }

    //-------------------------------------
    //  Create and Set Up XML Parser
    //-------------------------------------

    $parser = xml_parser_create($this->xmlrpc_defencoding);

    $this->xh[$parser]                    = array();
    $this->xh[$parser]['isf']            = 0;
    $this->xh[$parser]['ac']            = '';
    $this->xh[$parser]['headers']        = array();
    $this->xh[$parser]['stack']            = array();
    $this->xh[$parser]['valuestack']    = array();
    $this->xh[$parser]['isf_reason']    = 0;

    xml_set_object($parser, $this);
    xml_parser_set_option($parser, XML_OPTION_CASE_FOLDING, true);
    xml_set_element_handler($parser, 'open_tag', 'closing_tag');
    xml_set_character_data_handler($parser, 'character_data');
    //xml_set_default_handler($parser, 'default_handler');


    //-------------------------------------
    //  GET HEADERS
    //-------------------------------------

    $lines = explode("\r\n", $data);
    while (($line = array_shift($lines)))
    {
        if (strlen($line) < 1)
        {
            break;
        }
        $this->xh[$parser]['headers'][] = $line;
    }
    $data = implode("\r\n", $lines);


    //-------------------------------------
    //  PARSE XML DATA
    //-------------------------------------

    if ( ! xml_parse($parser, $data, count($data)))
    {
        $errstr = sprintf('XML error: %s at line %d',
                xml_error_string(xml_get_error_code($parser)),
                xml_get_current_line_number($parser));
        //error_log($errstr);
        $r = new XML_RPC_Response(0, $this->xmlrpcerr['invalid_return'], $this->xmlrpcstr['invalid_return']);
        xml_parser_free($parser);
        return $r;
    }
    xml_parser_free($parser);

    // ---------------------------------------
    //  Got Ourselves Some Badness, It Seems
    // ---------------------------------------

    if ($this->xh[$parser]['isf'] > 1)
    {
        if ($this->debug === TRUE)
        {
            echo "---Invalid Return---\n";
            echo $this->xh[$parser]['isf_reason'];
            echo "---Invalid Return---\n\n";
        }

        $r = new XML_RPC_Response(0, $this->xmlrpcerr['invalid_return'],$this->xmlrpcstr['invalid_return'].' '.$this->xh[$parser]['isf_reason']);
        return $r;
    }
    elseif ( ! is_object($this->xh[$parser]['value']))
    {
        $r = new XML_RPC_Response(0, $this->xmlrpcerr['invalid_return'],$this->xmlrpcstr['invalid_return'].' '.$this->xh[$parser]['isf_reason']);
        return $r;
    }

    //-------------------------------------
    //  DISPLAY XML CONTENT for DEBUGGING
    //-------------------------------------

    if ($this->debug === TRUE)
    {
        echo "<pre>";

        if (count($this->xh[$parser]['headers'] > 0))
        {
            echo "---HEADERS---\n";
            foreach ($this->xh[$parser]['headers'] as $header)
            {
                echo "$header\n";
            }
            echo "---END HEADERS---\n\n";
        }

        echo "---DATA---\n" . htmlspecialchars($data) . "\n---END DATA---\n\n";

        echo "---PARSED---\n" ;
        var_dump($this->xh[$parser]['value']);
        echo "\n---END PARSED---</pre>";
    }

    //-------------------------------------
    //  SEND RESPONSE
    //-------------------------------------

    $v = $this->xh[$parser]['value'];

    if ($this->xh[$parser]['isf'])
    {
        $errno_v = $v->me['struct']['faultCode'];
        $errstr_v = $v->me['struct']['faultString'];
        $errno = $errno_v->scalarval();

        if ($errno == 0)
        {
            // FAULT returned, errno needs to reflect that
            $errno = -1;
        }

        $r = new XML_RPC_Response($v, $errno, $errstr_v->scalarval());
    }
    else
    {
        $r = new XML_RPC_Response($v);
    }

    $r->headers = $this->xh[$parser]['headers'];
    return $r;
}

} [/code]

Clone this wiki locally