drupal using node.save with XMLRPC call to another site. "Access Denied" message
I have a piece of code on 1 drupal site to create a node another drupal site in a multi-site setup. It looks like I'm getting the sessionid and logging in just fine, but when trying to create a "page" node, I get "Access denied". Under Services -> Settings I have "Key Authentication", "Use keys" is unchecked, and "Use sessid" is checked. I agev permissions for the logged in user: "create page content", "administer services", etc... Below is my code:
<p>Test Page 1</p>
<? $ur开发者_运维知识库l = 'http://drupal2.dev/xmlrpc.php'; ?>
<?
$conn = xmlrpc($url, 'system.connect');
print_r($conn);
?>
<p>--</p>
<?
$login = xmlrpc($url, 'user.login', $conn['sessid'], 'superuser_name', 'superuser_password');
print_r($login);
?>
<p>--</p>
<?
$data=array('type'=>'page', 'title'=>'Test', 'body'=>'test');
$data_s=serialize($data);
$result = xmlrpc($url, 'node.save', $login['sessid'], $data_s);
echo $result;
//echo $data_s;
?>
<?
if($error = xmlrpc_error()){
if($error->code > 0){
$error->message = t('Outgoing HTTP request failed because the socket could not be opened.');
}
drupal_set_message(t('Operation failed because the remote site gave an error: %message (@code).',
array(
'%message' => $error->message,
'@code' => $error->code
)
)
);
}
?>
The ouput of this script is:
Array ( [sessid] => 9eebdde9bf0bfd9610cc2f03af131a9c [user] => Array ( [uid] => 0 [hostname] => ::1 [roles] => Array ( [1] => anonymous user ) [session] => [cache] => 0 ) )
--
Array ( [sessid] => c0ca4c599e41e97e7a7ceb43ee43249e [user] => Array ( [uid] => 1 [name] => eric [pass] => 13583b155536098b98df41bb69fcc53 [mail] => email@gmail.com [mode] => 0 [sort] => 0 [threshold] => 0 [theme] => [signature] => [signature_format] => 0 [created] => 1271813934 [access] => 1275867734 [login] => 1275868794 [status] => 1 [timezone] => [language] => [picture] => [init] => email@gmail.com [data] => a:0:{} [roles] => Array ( [2] => authenticated user ) ) )
--
Access denied
I discovered recently that PHP session ids are more complex than I had thought.
For them to work, your XMLRPC transport needs to fully support cookies, which are used for Drupal's authentication.
Without cookies, each request is treated as a new anonymous request and is given a new session ID. So the fact that you've logged in means nothing to the next xmlrpc call you make.
I'm doing some work in python, and made a custom transport object to support cookies, and now it all works for me. I found out how to do this in python here:
http://osdir.com/ml/python.cherrypy/2005-12/msg00142.html
(edit-add) I might also add that the services module is pretty bad with its error reporting. For example, if you send an argument as a string when it's expecting an array (with the string in the array) you can often get access denied errors which don't really reflect the fact that there is a parameter error.
Check that the service is working as you expect by testing it out under Admin > Site Building > Services > Browse and click the service you want to use.
site 1 code:
function exmple2_cron() {
homes_sync_get_node_list();
}
function homes_sync_get_node_list() {
$methods = xmlrpc('http://example.com/map/xmlrpc.php', array('system.listMethods' => array()));
$node_ids = xmlrpc('http://example.com/map/xmlrpc.php', array('node.getAllHomes'=>array()));
if (xmlrpc_error()) {
$error = xmlrpc_error();
watchdog('homes_sync', 'Error getting node list from parent server. Error: @error.', array('@error' => $error);
}
else {
foreach ($node_ids as $nid) {
$nodes[] = $nid;
}
variable_set('parent_home_nodes', $nodes);
watchdog('homes_sync', 'Successfully retrieved node list from parent server.', array(), WATCHDOG_NOTICE);
}
homes_sync_perform_update();
}
function homes_sync_perform_update() {
$node_ids = variable_get('parent_home_nodes', 0);
foreach ($node_ids as $nid) {
$data = xmlrpc('http://example.com/map/xmlrpc.php', array('node.get' => array($nid)));print_r($data);exit;
$result = db_fetch_array(db_query('SELECT n.nid, n.title, n.type FROM {node} n WHERE n.title = "%s" AND n.type = "%s"', $data['title'], 'page'));
if (xmlrpc_error()) {
$error = xmlrpc_error();
watchdog('homes_sync', 'Could not perform XMLRPC request. Error: @error.', array('@error' => $error), WATCHDOG_CRITICAL);
} else {
if (is_array($data)) {
$node = "";
if ($result && $result['nid']) {
$node->nid = $result['nid'];
}
$node->type = $data['type'];
$node->uid = 1;
$node->status = $data['status'];
$node->created = $data['created'];
$node->changed = $data['changed'];
$node->comment = $data['comment'];
$node->promote = $data['promote'];
$node->moderate = $data['moderate'];
$node->sticky = $data['sticky'];
$node->tnid = $data['tnid'];
$node->translate = $data['translate'];
$node->title = $data['title'];
$node->body = $data['body'];
$node->teaser = $data['teaser'];
$node->format = $data['format'];
$node->name = $data['name'];
$node->data = $data['data'];
$node->path = $data['path'];
node_save($node);
unset($node);
}
}
}
}
remote site code:
function example_xmlrpc() {
$methods = array();
$methods[] = array(
'node.getAllHomes',
'homes_service_node_get_all_homes',
array('int'),
);
return $methods;
}
function homes_service_node_get_all_homes() {
$query = db_query('SELECT n.* FROM {node} n');
foreach ($query as $record){
$nid[] = $record;
}
return $nid;
}
精彩评论