A while ago I posted on my website how I was using php and curl to do automatic image uploading to Drupal and geolocating images. Some people requested the script, others arrive there from Google by searching about the same thing, so here is a small tutorial on how to do it.

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.

    $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.

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

Now it's time to log in.

    $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

    $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?

            "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

    $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 here. The tutorial can also be found at my website, at http://www.voidberg.org/blog/using_php_and_curl_to_automate_drupal_tasks...

Comments

sepeck’s picture

Could you add this into the handbook please? If you can't any place appropriate toss it into the site-recipes section and we'll make a place for it later.

-Steven Peck
---------
Test site, always start with a test site.
Drupal Best Practices Guide -|- Black Mountain

-Steven Peck
---------
Test site, always start with a test site.
Drupal Best Practices Guide

dman’s picture

Funny the hoops we make ourselves jump through :)
It looks like this way of just hammering in the form fields is easier than thying to set up an RPC system or anything. ... I guess error handling may be a problem however!

Anyway, great howto!

.dan.
How to troubleshoot Drupal | http://www.coders.co.nz/

TheWhippinpost’s picture

Yeah nice one, thanks.

I had a very similar plan to implement such a utility so this has given me a head-start, cheers

Mike

pwolanin’s picture

As part of a reorganization of the page snippet section, I created a new section for this sort of cURL snippet: http://drupal.org/node/87711

---
Work: BioRAFT

voidberg’s picture

dman, you're right, error handling is pretty hard (if not impossible) to do. I'm mostly using it to bulk upload images, so if an image doesn't get in the sistem, no problem. :)
I added it to the section pwolanin suggested: http://drupal.org/node/89710