PHP Script for XML-RPC calls from outside Drupal

Events happening in the community are now at Drupal community events on www.drupal.org.
thompcha's picture

Here is a set of PHP functions I put together for calling Drupal's core XML-RPC methods without using the Services API:

<?php
function assemble_request($method, $args = array(), $dump_request = FALSE){
       
$request = xmlrpc_encode_request($method,$args);
       
$context = stream_context_create(array('http' => array(
               
'method' => "POST",
               
'header' => "Content-Type: text/xml",
               
'content' => $request
       
)));
        if(
$dump_request){
                echo
'<pre>';
                echo
htmlentities($request);
                echo
'</pre>';
        }
        return
$context;
}

function
dump_response($response){
       echo
'<pre>';
                if (
xmlrpc_is_fault($response)) {
                       
trigger_error("xmlrpc: $response[faultString] ($response[faultCode])");
                } else {
                       
print_r($response);
                }
       echo
'</pre>';
}

function
make_args_array($method, $session, $args = array(), $dump_args = FALSE){
       
$domain = 'localhost';
       
$timestamp = (string) time();
       
$nonce = user_password();
       
$key = '4a13889853ed635941670fe6054a9759';
       
$hash = hash_hmac('sha256', $timestamp .';'.$domain .';'. $nonce .';'.$method, $key);
       
$arrHash = array();
       
array_push($arrHash, $hash, $domain, $timestamp, $nonce, $session);
        if(
$dump_args){
                echo
'<pre>';
               
var_dump(array_merge($arrHash,$args));
                echo
'</pre>';
        }
        return
array_merge($arrHash,$args);
}

function
user_password($length = 10) {
       
$allowable_characters = 'abcdefghijkmnopqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ23456789';
       
$len = strlen($allowable_characters) - 1;
       
$pass = '';
        for (
$i = 0; $i < $length; $i++) {
               
$pass .= $allowable_characters[mt_rand(0, $len)];
        }
        return
$pass;
}
?>

Here is an example use that logs in a user and returns a node:

<?php
$ctxtSysConnect
= assemble_request("system.connect", NULL);
$file = file_get_contents("http://localhost/drupal/xmlrpc.php", false, $ctxtSysConnect);
$response = xmlrpc_decode($file);
$session = $response[sessid];

$arrArgs = make_args_array('user.login',$session,array("username","password"));
$ctxtSysConnect = assemble_request('user.login', $arrArgs);
$file = file_get_contents("http://localhost/drupal/xmlrpc.php", false, $ctxtSysConnect);
$response = xmlrpc_decode($file);
$session = $response[sessid];

$arrArgs = make_args_array('node.view',$session,array(11,array("field_date")),TRUE);
$ctxtSysConnect = assemble_request('node.view', $arrArgs);
$file = file_get_contents("http://localhost/drupal/xmlrpc.php", false, $ctxtSysConnect);
$response = xmlrpc_decode($file);
dump_response($response);
?>

If you're interested in working on making CCK date fields work with Drupal's "node.save" function, get in touch with me through my Drupal Groups user page.

Comments

I am using Fedora 10, PHP

nhchau's picture

I am using Fedora 10, PHP 5.2.6. However my PHP does not understand xmlrpc_encode_request(). It said: "PHP Fatal error: Call to undefined function xmlrpc_encode_request() in /home/chau/public_html/tmp/rpc.php on line 5".
On the other side, php.net says xmlrpc_encode_request() is still in experimental stage (http://vn.php.net/xmlrpc_encode_request). Any other way to call XML-RPC from outside Drupal to Drupal? Thanks.

C.

xmlrpc extension enabled?

thompcha's picture

Make sure you remove the semicolon in front of "extension=php_xmlrpc.dll" in php.ini

System.connect is only provided by the Services Module

craigmc's picture

So these calls are still dependent on the Services Module being enabled, right?

Can you explain a little bit more about how the user authentication works in the Services module model? Would greatly appreciate it.

Los Angeles, CA

Doc page

pieterdc's picture

Maybe this Services module documentation page will clarify some things for you.

CCK date field on "node.save" function

un11imig's picture

Hi,

I want to develop a client using C Sharp that allows the creation of new nodes. The problem is with date_field. What is the structure must follow the node?.

Thanks in advance.

I have the same problem too

sullix's picture

I have the same problem too (using PHP). It works for CCK text fields but not for date ones.

I used this format unsuccessfully:
$node->field_date[0] = array(
'value' => date('Y-m-dT00:00:00', strtotime('+2 months')),
'timezone' => 'Europe/Paris',
'timezone_db' => 'UTC',
'date_type' => 'date'
);

edited the post .. since it

karthick62's picture

edited the post .. since it was posted twice by mistake

which params need to pass for user.save method.

purabdk's picture

I tried the use the user.save method using above code but I failed. I always got following message
Missing required arguments.

Software Development

I need to have this for Druapl 7 + zend Framwark.

rajab natshah's picture

We had this code working.

<?php
require_once 'Zend/XmlRpc/Client.php';
$client = new Zend_XmlRpc_Client('http://mywebsitedomain.com/drupal/myendpoint');
$data $client->call('system.listMethods');
print_r($data);
?>

But we need to have full secure authenticated connect+login+get Node data.

<?php
function user_password($length = 10) {
       
$allowable_characters = 'abcdefghijkmnopqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ23456789';
       
$len = strlen($allowable_characters) - 1;
       
$pass = '';
        for (
$i = 0; $i < $length; $i++) {
               
$pass .= $allowable_characters[mt_rand(0, $len)];
        }
        return
$pass;
}

require_once
'Zend/XmlRpc/Client.php';

$client = new Zend_XmlRpc_Client('http://mydomian.com/drupal/myendpoint');

// system.listMethods .
echo "\nCall for system.listMethods\n";
$data $client->call('system.listMethods');
print_r($data);


// system.connect.
echo "\nCall for the system.connect\n";
$connect_data $client->call('system.connect');
print_r($connect_data);

$session_id = $connect_data['sessid'];
       if (
$session_id)
           echo
"\n got anonymous session id fine\n";
       else
           echo
"\nfailed to get anonymous session id!\n";

// user.login
echo "\nCall user.login\n";

$userName = 'myusername';
$userPassword = 'mypassword';

       
$domain = 'localhost';
       
$nonce = user_password();
       
$timestamp = (string) time();
       
$key = '4a13889853ed635941670fe6054a9759';
       
$hash = hash_hmac('sha256', $timestamp .';'.$domain .';'. $nonce .';user.login', $key);

       
$arrUser = array ($userName, $userPassword);
       
$arrHash = array();

       
array_push($arrHash, $hash, $domain, $timestamp, $nonce, $session_id);

       
$arrParm array_merge($arrHash,$arrUser);
$userlogin = $client->call('user.login',array($userName,$userPassword) );
print_r($userlogin);
?>

For this It's getting the $session_id .. But for login.
Do we have to create our key and change it .. How to do this for Drupal 7 and services 3.0
$key = '4a13889853ed635941670fe6054a9759';

Please , I need help on this..

Rajab Natshah
rajab.natshah.com

Seems this Class is very good

rajab natshah's picture

From this link
http://wonderlandlabs.com/wll_drupal/drupal/services.html

But the API Key still not working

Rajab Natshah
rajab.natshah.com

Is this right.. Services 3.x

rajab natshah's picture

Is this right..
Services 3.x no longer uses API keys. Sessions are handled via regular session authentication.
It's from this link http://drupal.stackexchange.com/questions/6042/how-to-get-an-api-key-in-...

Rajab Natshah
rajab.natshah.com

Services

Group organizers

Group categories

Group notifications

This group offers an RSS feed. Or subscribe to these personalized, sitewide feeds:

Hot content this week