Good morning WAREBOT’rs

Today we’ll be sharing how we were able to crack Drupal’s modules :

  • Services
  • Rest Server
  • Views Service

in order to allow argument passing to your endpoint API.

We will adding simple modifications to the following files:

RESTServer.inc – located in {path to your modules}/services/servers/rest_server/includes/RESTServer.inc

services_views.resource.inc (OPTIONAL) – located in {path to your modules}/services/resources/services_views.resource.inc

RESTServer.inc

Approximately @ line 30 you will see the following

$path = explode('/', $canonical_path);

That’s pretty much splitting the path e.g “views/products/1″ into array(“views”,”products”,1)

The next two lines are pretty much where the magic begins:

 $leaf = array_pop($path);<br />$resource_name = array_shift($path);

To my computer science friends, $leaf is pretty much the leaf of the “tree”, outmost child, which in our case here is our argument : 1

$resource_name = array_shift($path);

is pretty much like “popping” but from the bottom of the stack as opposed to the top

Awesome! so far we have our argument. Moving on..

Lets add our argument to the arguments array:

Approximately @ line 156 you will see the following:

$arguments['args'][]=$leaf  //WAREBOT EDIT - add our leaf "argument" to the args array
try {
$result = services_controller_execute($controller, $arguments);
} catch (ServicesException $e) {
$errors = $this->handleException($e);
drupal_alter('rest_server_exectue_errors', $errors, $controller, $arguments);
$result = $errors;

In our case, we were only concerned with passing one argument, if you will be passing more e.g “views/products/1/2″ then you would probably want to change the logic above to fetch all of your arguments from the endpoint url instead of just grabbing the leaf

$arguments['args'][]=$leaf 

Approximately @ line 584 you will see the following:

($pc==1 && ($method=='GET' || $method=='PUT' || $method=='DELETE')) || ($pc==0 && $method='POST')) {
$action_mapping = array('GET' =>'retrieve','POST' =>'create','PUT' => 'update','DELETE' => 'delete',);

AHA! $pc == 1 is pretty much what is preventing us from sending our argument.
Simply change that to $pc <=2. In our case, we just needed to pass one argument to our view, so if you need to pass more, just change this logic.

Is this the cleanest way to do it, I would not be able to make that statement in a court of law, but it works dammit.

OK. One file down. Next up, services_views.resource.inc (OPTIONAL) – located in {path to your modules}/services/resources/services_views.resource.inc
In the

function services_views_retrieve($view_name, $display_id = 'default', $args = array(), $offset = 0, $limit = 10, $theme_result = FALSE)

we added

$display_id='page';

since we had more than one display set for that view.

Again, I’m sure there are other approaches out there to solve this issue, some better, some worse, but this worked for us…

-WAREBOT

 

Leave a Reply

Your email address will not be published. Required fields are marked *

*

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>