Last updated November 17, 2008. Created by Amitaibu on October 17, 2006.
Edited by voidberg. Log in to edit this page.
First of all you'll need the libcurl extension to php installed. The code snippets I'll present here might work if you'll convert them to Snoopy, but libcurl is faster.
What we'll do: we are going to login into Drupal and we are going to perform different operations.
1. Logging in
The first step is to log in. We're going to send the credentials using POST to the /user/login page of our Drupal website. The trick here is to capture the cookie sent by the server to use it later.
Let's init curl and set some options: the site we're going to use along with the login page and a file on our server which will store the cookie. Be careful, the user that the webserver runs as needs to have write access there. CURLOPT_POST tells curl we're going to use POST to send form data.
<?php
$crl = curl_init();
$url = "http://www.example.com/user/login";
curl_setopt($crl, CURLOPT_URL, $url);
curl_setopt($crl, CURLOPT_COOKIEFILE, "/tmp/cookie.txt");
curl_setopt($crl, CURLOPT_COOKIEJAR, "/tmp/cookie.txt");
curl_setopt($crl, CURLOPT_FOLLOWLOCATION, 1);
curl_setopt($crl, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($crl, CURLOPT_POST, 1);
?>Next, we need to set the username and the password of the user we're going to login and send the data to the login script. To do this, we need to inspect the standard drupal login form and see the fields names: they're edit[name], edit[pass], edit[form_id] and op.
Warning: Be careful to init all elements of the form because missing some will make the script unusable. Particularly, edit[form_id] is essential.
<?php
// This array will hold the field names and values.
$postdata=array(
"edit[name]"=>"admin",
"edit[pass]"=>"password",
"edit[form_id]"=>"user_login",
"op"=>"Log in"
);
// Tell curl we're going to send $postdata as the POST data
curl_setopt ($crl, CURLOPT_POSTFIELDS, $postdata);
?>Note that since Drupal 6 the correct syntax should be:
// The key of the postdata is the “name” of the form field.
$postdata=array(
"name" => "admin",
"pass" => "password",
"form_id" => "user_login",
"op" => "Log in",
);Note that trying to login again with the same cookie name will fail.
Now it's time to log in.
<?php
$result=curl_exec($crl);
$headers = curl_getinfo($crl);
if ($headers['url'] == $url) {
die("Cannot login.");
}
?>What we're doing here is sending the form data to the Drupal login page. We then get the headers of the response and check if the returned url is the login one. If it is, then it means we couldn't log in. This happens because, after a succesful login, Drupal redirects to http://www.example.com/user/2, 2 being the id of the logged in user. In case of failing, it returns to the login page displaying an error.
If everything went ok, we're logged in. Now you can do more serious stuff. :) Let's continue with some examples:
2. Example: Adding an image
<?php
$file = "test.jpg";
$url = "http://www.example.com/node/add/image";
curl_setopt($crl, CURLOPT_URL, $url);
$postdata = array("edit[title]"=>$file,
"edit[image]"=>"@$file.jpg",
"edit[body]"=>"This is an image posted with cURL.",
"op"=>"Submit",
"edit[format]"=>"1",
"edit[comment]"=>"2",
"edit[name]"=>"admin",
"edit[date]"=>"",
"edit[status]"=>"1",
"edit[moderate]"=>"0",
"edit[promote]"=>"1",
"edit[sticky]"=>"0",
"edit[revision]"=>"0",
"edit[images][_original]"=>"",
"edit[images][thumbnail]"=>"",
"edit[images][preview]"=>"",
"edit[form_id]"=>"image_node_form"
);
curl_setopt ($crl, CURLOPT_POSTFIELDS, $postdata);
$result=curl_exec($crl);
$headers = curl_getinfo($crl);
if ($headers['url'] == $url) {
die("Cannot add the image.");
}
?>I looked over the image add form generated by Drupal, noting the fields' names and their default values. Then, we fill this with our info and send the data. Because we're using the same resource, $crl, we're still logged. In the end we check if the resulting url is still "node/add/image". If it is, then some data wasn't filled right and Drupal returned us to the node add page.
What's with that @ in the code?
<?php
"edit[image]"=>"@$file.jpg",
?>edit[image] is an input of type file. By using @, we tell cURL to fetch the contents of that file and send them to the add script.
3. Example: Adding an user
<?php
$url = "http://www.example.com/admin/user/create";
curl_setopt($crl, CURLOPT_URL, $url);
$postdata = array(
"edit[name]"=>"newuser",
"edit[mail]"=>"newuser@example.com",
"edit[password]"=>"password",
"edit[notify]"=>1,
"op"=>"Submit",
"edit[form_id]"=>"user_register"
);
curl_setopt ($crl, CURLOPT_POSTFIELDS, $postdata);
$result=curl_exec($crl);
$headers = curl_getinfo($crl);
if ($headers['url'] == $url) {
die("Cannot add the image.");
}
?>And that's basically it. Post any questions or suggestions to the forums or here.
Comments
$postdata for Drupal 5.x
I'm running this code with Drupal 5.x and first tried as you suggest:
$postdata=array("edit[name]"=>"admin",
"edit[pass]"=>"password",
"edit[form_id]"=>"user_login",
"op"=>"Log in"
);
even if I could tell from the form's HTML that the field names were not like the keys in the array above. It didn't work. Then I just used the "Drupal 6" version and it worked:
$postdata=array("name" => "admin",
"pass" => "password",
"form_id" => "user_login",
"op" => "Log in",
);
In conclusion, you use the same format for Drupal 5 and 6 and the names of the form elements correspond to the name attributes of each form element in your HTML source.
Thanks for your help :)
Alexis Bellido
Ventanazul: web development and Internet business consulting shouldn't be boring
Alexis Bellido
Need help with your next Drupal project?
Logging in using cURL
On Drupal 6 the following sequence works.
<?php
$site = 'http://www.nowhere-special.com';
$export_path = '/some/export/';
$targets = array('target1', 'target2', 'target3');
// get login form
$crl = curl_init();
$url = $site."/user/login";
curl_setopt($crl, CURLOPT_URL, $url);
curl_setopt($crl, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($crl, CURLOPT_COOKIEJAR, "/tmp/cookie.txt");
$result=curl_exec($crl);
$info = curl_getinfo($crl);
if ($info['http_code'] != 200) {
die("expected http code 200. got ".$info['http_code']);
}
// login
$crl = curl_init();
$url = $site."/user/login";
curl_setopt($crl, CURLOPT_URL, $url);
curl_setopt($crl, CURLOPT_COOKIEFILE, "/tmp/cookie.txt");
curl_setopt($crl, CURLOPT_COOKIEJAR, "/tmp/cookie.txt");
curl_setopt($crl, CURLOPT_FOLLOWLOCATION, 1);
curl_setopt($crl, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($crl, CURLOPT_POST, 1);
$postdata=array(
"name" => 'august',
"pass" => "sausage",
"form_id" => "user_login",
"op" => "Log in",
);
curl_setopt ($crl, CURLOPT_POSTFIELDS, $postdata);
$result=curl_exec($crl);
$headers = curl_getinfo($crl);
if ($headers['url'] == $url) {
var_dump($headers);
die("Cannot login.");
}
// access paths to do export
foreach ($targets as $target) {
$uri = $site.$export_path.$target;
$crl=curl_init();
curl_setopt($crl,CURLOPT_URL, $uri);
curl_setopt($crl, CURLOPT_FOLLOWLOCATION, 1);
curl_setopt($crl, CURLOPT_COOKIEFILE, "/tmp/cookie.txt");
curl_exec($crl);
curl_close($crl);
}
?>
Lots of the time this wont
Lots of the time this wont work because you need to get the security token and post it as well as form_id. See this: http://drupal.org/node/80548
Simplistech Solutions - Simplifying technology for small businesses and entrepreneurs.
Imagecache+ubercart+curl
Hello. I am having trouble with an image upload. In the ubercart form it is a JS(imagecache) controlled image field, which I don't know how to fill from outside drupal using CURL...
The idea is to bulk add products with images from my local(not drupal) database of products to the remote drupal site.
The node adds, with all the custom fields I've created, but there is no image uploading. It is just no image. As I think it is handled by filefield/imagecache.
But how to put the image in it?
I have tried files[field_image_cache_0] and field_image_cache[0][fid] but nothing happens. Node adds with no image in it.
I think it works like this:
JS uses filefield to upload an image and then uses imagecache to put it in the form, so by the time of submitting the form the image is already uploaded and a reference is added to Drupal database.
<?php
$thefilename = 'Z:\home\www\tst\file.jpg';
$thesize = filesize($thefilename);
$thepostfields="name=admin&body=thebody&title=thetitle&path=thepath&files[field_image_cache_0]=file.jpg&sell_price=4400.00&weight=3.0&field_pwr[0][value]=1.1&field_h[0][value]=3.0&field_flow[0][value]=3.0&model=11111111&status=1&revision=1&op=Submit&form_id=product_node_form&form_token=xxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
// ***********************************************
// ********* post form, using token
// ***********************************************
echo "Posting form<br>\n\r";
$ch = curl_init();
curl_setopt($ch, CURLOPT_HEADER, 1);
curl_setopt($ch, CURLOPT_RETURNTRANSFER,1);
curl_setopt($ch, CURLOPT_COOKIEFILE, "cookie.txt");
curl_setopt($ch, CURLOPT_URL,"http://192.168.0.248/?q=node/add/product");
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $thepostfields);
curl_setopt($ch,CURLOPT_INFILESIZE,$thesize);
curl_setopt($ch,CURLOPT_INFILE,$thefile);
$buf2 = curl_exec ($ch);
//echo $buf2;
fclose($thefile);
curl_close ($ch);
echo "<br>\n\r Page has been posted \n\r";
?>
What do I do?
Please help.
Otherwise I will need to add like 6000 images manually, which will kill me at work.
http://digger3d.com