? 1017036.patch
? 1030220.patch
? services-test.patch.txt
Index: services.info
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/services/services.info,v
retrieving revision 1.12
diff -u -p -r1.12 services.info
--- services.info	27 Jan 2011 03:16:00 -0000	1.12
+++ services.info	1 Feb 2011 12:52:41 -0000
@@ -18,4 +18,6 @@ files[] = tests/functional/ServicesResou
 files[] = tests/functional/ServicesResourceUserTests.test
 files[] = tests/functional/ServicesEndpointTests.test
 files[] = tests/unit/TestServicesModule.test
+files[] = tests/services.test
+
 dependencies[] = ctools
\ No newline at end of file
Index: tests/services.test
===================================================================
RCS file: tests/services.test
diff -N tests/services.test
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ tests/services.test	1 Feb 2011 12:52:42 -0000
@@ -0,0 +1,437 @@
+<?php
+// $Id: ServicesWebTestCase.php,v 1.4 2011/01/30 16:21:04 heyrocker Exp $
+
+class ServicesWebTestCase extends DrupalWebTestCase {
+
+  public function setUp() {
+    $args = func_get_args();
+  
+    $modules = array();
+    if (isset($args[0]) && is_array($args[0])) {
+      $modules = $args[0];
+    }
+  
+    // Add the required module dependencies.
+    array_unshift($modules, 'ctools', 'services', 'rest_server');
+  
+    parent::setUp($modules);
+  }
+  
+
+  protected function servicesGet($url, $data = NULL, $headers = array()) {
+    $options = array('query' => $data);
+    $url = url($this->getAbsoluteUrl($url) . '.php', $options);
+    $headers = array();
+    $content = $this->curlExec(array(
+      CURLOPT_HTTPGET => TRUE,
+      CURLOPT_URL => $url,
+      CURLOPT_NOBODY => FALSE,
+      CURLOPT_RETURNTRANSFER => TRUE,
+      CURLOPT_HEADER => TRUE,
+      CURLOPT_HTTPHEADER => $headers
+    ));
+
+    // Parse response.
+    list($info, $header, $status, $code, $body) = $this->parseHeader($content);
+
+    $this->verbose('GET request to: ' . $url .
+                   '<hr />Arguments: ' . highlight_string('<?php ' . var_export($data, TRUE), TRUE) .
+                   '<hr />Response: ' . highlight_string('<?php ' . var_export($body, TRUE), TRUE) .
+                   '<hr />Raw response: ' . $content);
+    return array('header' => $header, 'status' => $status, 'code' => $code, 'body' => $body);
+  }
+
+  protected function servicesPost($url, $data = array(), $headers = array()) {
+    $options = array();
+    // Add .php to get serialized response.
+    $url = $this->getAbsoluteUrl($url) . '.php';
+
+    // Otherwise Services will reject arguments.
+    $headers = array("Content-type: application/x-www-form-urlencoded");
+    // Prepare arguments.
+    $post = http_build_query($data, '', '&');
+
+    $content = $this->curlExec(array(
+      CURLOPT_URL => $url,
+      CURLOPT_POST => TRUE,
+      CURLOPT_POSTFIELDS => $post,
+      CURLOPT_HTTPHEADER => $headers,
+      CURLOPT_HEADER => TRUE,
+      CURLOPT_RETURNTRANSFER => TRUE
+    ));
+
+    // Parse response.
+    list($info, $header, $status, $code, $body) = $this->parseHeader($content);
+
+    $this->verbose('POST request to: ' . $url .
+                   '<hr />Arguments: ' . highlight_string('<?php ' . var_export($data, TRUE), TRUE) .
+                   '<hr />Response: ' . highlight_string('<?php ' . var_export($body, TRUE), TRUE) .
+                   '<hr />Curl info: ' . highlight_string('<?php ' . var_export($info, TRUE), TRUE) .
+                   '<hr />Raw response: ' . $content);
+    return array('header' => $header, 'status' => $status, 'code' => $code, 'body' => $body);
+  }
+
+  protected function servicesPut($url, $data = NULL, $headers = array()) {
+    $options = array();
+    $url = $this->getAbsoluteUrl($url) . '.php';
+
+    $serialize_args = serialize($data);
+
+    // Set up headers so arguments will be unserialized.
+    $headers = array("Content-type: application/vnd.php.serialized; charset=iso-8859-1");
+
+    // Emulate file.
+    $putData = fopen('php://memory', 'rw+');
+    fwrite($putData, $serialize_args);
+    fseek($putData, 0);
+
+    $content = $this->curlExec(array(
+      CURLOPT_URL => $url,
+      CURLOPT_RETURNTRANSFER => TRUE,
+      CURLOPT_PUT => TRUE,
+      CURLOPT_HEADER => TRUE,
+      CURLOPT_HTTPHEADER => $headers,
+      CURLOPT_INFILE => $putData,
+      CURLOPT_INFILESIZE => strlen($serialize_args)
+    ));
+    fclose($putData);
+
+    // Parse response.
+    list($info, $header, $status, $code, $body) = $this->parseHeader($content);
+
+    $this->verbose('PUT request to: ' . $url .
+                   '<hr />Arguments: ' . highlight_string('<?php ' . var_export($data, TRUE), TRUE) .
+                   '<hr />Response: ' . highlight_string('<?php ' . var_export($body, TRUE), TRUE) .
+                   '<hr />Curl info: ' . highlight_string('<?php ' . var_export($info, TRUE), TRUE) .
+                   '<hr />Raw response: ' . $content);
+    return array('header' => $header, 'status' => $status, 'code' => $code, 'body' => $body);
+  }
+
+  protected function servicesDelete($url, $data = NULL, $headers = array()) {
+    $options = array('query' => $data);
+    $url = url($this->getAbsoluteUrl($url) . '.php', $options);
+
+    $content = $this->curlExec(array(
+      CURLOPT_URL => $url,
+      CURLOPT_CUSTOMREQUEST => "DELETE",
+      CURLOPT_HTTPHEADER => $headers,
+      CURLOPT_RETURNTRANSFER => TRUE
+    ));
+
+    // Parse response.
+    list($info, $header, $status, $code, $body) = $this->parseHeader($content);
+
+    $this->verbose('DELETE request to: ' . $url .
+                   '<hr />Arguments: ' . highlight_string('<?php ' . var_export($data, TRUE), TRUE) .
+                   '<hr />Response: ' . highlight_string('<?php ' . var_export($body, TRUE), TRUE) .
+                   '<hr />Curl info: ' . highlight_string('<?php ' . var_export($info, TRUE), TRUE) .
+                   '<hr />Raw response: ' . $content);
+    return array('header' => $header, 'status' => $status, 'code' => $code, 'body' => $body);
+  }
+
+  /*
+  ------------------------------------
+  HELPER METHODS
+  ------------------------------------
+  */
+
+  /**
+   * Parse header.
+   *
+   * @param type $content
+   * @return type
+   */
+  function parseHeader($content) {
+    $info = curl_getinfo($this->curlHandle);
+    $header = substr($content, 0, $info['header_size']);
+    $header = str_replace("HTTP/1.1 100 Continue\r\n\r\n", '', $header);
+    $status = strtok($header, "\r\n");
+    $code = $info['http_code'];
+    $body = unserialize(substr($content, $info['header_size'], strlen($content) - $info['header_size']));
+    return array($info, $header, $status, $code, $body);
+  }
+
+  /**
+   * Creates a data array for populating an endpoint creation form.
+   *
+   * @return
+   * An array of fields for fully populating an endpoint creation form.
+   */
+  public function populateEndpointFAPI() {
+    return array(
+      'name'   => 'machinename',
+      'title'  => $this->randomName(20),
+      'path'   => $this->randomName(10),
+      'server' => 'rest_server',
+    );
+  }
+
+  public function saveNewEndpoint() {
+    $edit = $this->populateEndpointFAPI() ;
+    $endpoint = new stdClass;
+    $endpoint->disabled = FALSE; /* Edit this to true to make a default endpoint disabled initially */
+    $endpoint->api_version = 3;
+    $endpoint->name = $edit['name'];
+    $endpoint->title = $edit['title'];
+    $endpoint->server = $edit['server'];
+    $endpoint->path = $edit['path'];
+    $endpoint->authentication = array();
+    $endpoint->resources = array(
+      'node' => array(
+        'alias' => '',
+        'operations' => array(
+          'create' => array(
+            'enabled' => 1,
+          ),
+          'retrieve' => array(
+            'enabled' => 1,
+          ),
+          'update' => array(
+            'enabled' => 1,
+          ),
+          'delete' => array(
+            'enabled' => 1,
+          ),
+          'index' => array(
+            'enabled' => 1,
+          ),
+        ),
+      ),
+      'system' => array(
+        'alias' => '',
+        'actions' => array(
+          'connect' => array(
+            'enabled' => 1,
+          ),
+          'get_variable' => array(
+            'enabled' => 1,
+          ),
+          'set_variable' => array(
+            'enabled' => 1,
+          ),
+        ),
+      ),
+      'taxonomy_term' => array(
+        'alias' => '',
+        'operations' => array(
+          'create' => array(
+            'enabled' => 1,
+          ),
+          'retrieve' => array(
+            'enabled' => 1,
+          ),
+          'update' => array(
+            'enabled' => 1,
+          ),
+          'delete' => array(
+            'enabled' => 1,
+          ),
+        ),
+        'actions' => array(
+          'selectNodes' => array(
+            'enabled' => 1,
+          ),
+        ),
+      ),
+      'taxonomy_vocabulary' => array(
+        'alias' => '',
+        'operations' => array(
+          'create' => array(
+            'enabled' => 1,
+          ),
+          'retrieve' => array(
+            'enabled' => 1,
+          ),
+          'update' => array(
+            'enabled' => 1,
+          ),
+          'delete' => array(
+            'enabled' => 1,
+          ),
+        ),
+        'actions' => array(
+          'getTree' => array(
+            'enabled' => 1,
+          ),
+        ),
+      ),
+      'user' => array(
+        'alias' => '',
+        'operations' => array(
+          'create' => array(
+            'enabled' => 1,
+          ),
+          'retrieve' => array(
+            'enabled' => 1,
+          ),
+          'update' => array(
+            'enabled' => 1,
+          ),
+          'delete' => array(
+            'enabled' => 1,
+          ),
+          'index' => array(
+            'enabled' => 1,
+          ),
+        ),
+        'actions' => array(
+          'login' => array(
+            'enabled' => 1,
+          ),
+          'logout' => array(
+            'enabled' => 1,
+          ),
+        ),
+      ),
+      'comment' => array(
+        'alias' => '',
+        'operations' => array(
+          'create' => array(
+            'enabled' => 1,
+          ),
+          'retrieve' => array(
+            'enabled' => 1,
+          ),
+          'update' => array(
+            'enabled' => 1,
+          ),
+          'delete' => array(
+            'enabled' => 1,
+          ),
+        ),
+        'actions' => array(
+          'loadNodeComments' => array(
+            'enabled' => 1,
+          ),
+          'countAll' => array(
+            'enabled' => 1,
+          ),
+          'countNew' => array(
+            'enabled' => 1,
+          ),
+        ),
+      ),
+      'file' => array(
+        'alias' => '',
+        'operations' => array(
+          'create' => array(
+            'enabled' => 1,
+          ),
+          'retrieve' => array(
+            'enabled' => 1,
+          ),
+          'delete' => array(
+            'enabled' => 1,
+          ),
+        ),
+        'actions' => array(
+          'nodeFiles' => array(
+            'enabled' => 1,
+          ),
+        ),
+      ),
+      'echo' => array(
+        'alias' => '',
+        'operations' => array(
+          'index' => array(
+            'enabled' => 1,
+          ),
+        ),
+      ),
+    );
+    $endpoint->debug = 1;
+    $endpoint->status = 1;
+    services_endpoint_save($endpoint);
+    $endpoint = services_endpoint_load($endpoint->name);
+    $this->assertTrue($endpoint->name == $edit['name'], t('Endpoint successfully created'));
+    return $endpoint;
+  }
+
+  /**
+   * Performs a cURL exec with the specified options after calling curlConnect().
+   *
+   * @param $curl_options
+   *   Custom cURL options.
+   * @return
+   *   Content returned from the exec.
+   */
+  protected function curlExec($curl_options, $redirect = FALSE) {
+    $this->curlInitialize();
+
+    // cURL incorrectly handles URLs with a fragment by including the
+    // fragment in the request to the server, causing some web servers
+    // to reject the request citing "400 - Bad Request". To prevent
+    // this, we strip the fragment from the request.
+    // TODO: Remove this for Drupal 8, since fixed in curl 7.20.0.
+    if (!empty($curl_options[CURLOPT_URL]) && strpos($curl_options[CURLOPT_URL], '#')) {
+      $original_url = $curl_options[CURLOPT_URL];
+      $curl_options[CURLOPT_URL] = strtok($curl_options[CURLOPT_URL], '#');
+    }
+
+    $url = empty($curl_options[CURLOPT_URL]) ? curl_getinfo($this->curlHandle, CURLINFO_EFFECTIVE_URL) : $curl_options[CURLOPT_URL];
+
+    if (!empty($curl_options[CURLOPT_POST])) {
+      // This is a fix for the Curl library to prevent Expect: 100-continue
+      // headers in POST requests, that may cause unexpected HTTP response
+      // codes from some webservers (like lighttpd that returns a 417 error
+      // code). It is done by setting an empty "Expect" header field that is
+      // not overwritten by Curl.
+      $curl_options[CURLOPT_HTTPHEADER][] = 'Expect:';
+    }
+    curl_setopt_array($this->curlHandle, $this->additionalCurlOptions + $curl_options);
+
+    if (!$redirect) {
+      // Reset headers, the session ID and the redirect counter.
+      $this->session_id = NULL;
+      $this->headers = array();
+      $this->redirect_count = 0;
+    }
+
+    $content = curl_exec($this->curlHandle);
+    $status = curl_getinfo($this->curlHandle, CURLINFO_HTTP_CODE);
+
+    // cURL incorrectly handles URLs with fragments, so instead of
+    // letting cURL handle redirects we take of them ourselves to
+    // to prevent fragments being sent to the web server as part
+    // of the request.
+    // TODO: Remove this for Drupal 8, since fixed in curl 7.20.0.
+    if (in_array($status, array(300, 301, 302, 303, 305, 307)) && $this->redirect_count < variable_get('simpletest_maximum_redirects', 5)) {
+      if ($this->drupalGetHeader('location')) {
+        $this->redirect_count++;
+        $curl_options = array();
+        $curl_options[CURLOPT_URL] = $this->drupalGetHeader('location');
+        $curl_options[CURLOPT_HTTPGET] = TRUE;
+        return $this->curlExec($curl_options, TRUE);
+      }
+    }
+
+    $this->drupalSetContent($content, isset($original_url) ? $original_url : curl_getinfo($this->curlHandle, CURLINFO_EFFECTIVE_URL));
+
+    // Analyze the method for log message.
+    $method = '';
+    if (!empty($curl_options[CURLOPT_NOBODY])) {
+      $method = 'HEAD';
+    }
+
+    if (empty($method) && !empty($curl_options[CURLOPT_PUT])) {
+      $method = 'PUT';
+    }
+
+    if (empty($method) && !empty($curl_options[CURLOPT_CUSTOMREQUEST])) {
+      $method = $curl_options[CURLOPT_CUSTOMREQUEST];
+    }
+
+    if (empty($method)) {
+      $method = empty($curl_options[CURLOPT_POSTFIELDS]) ? 'GET' : 'POST';
+    }
+    $message_vars = array(
+      '!method' => $method,
+      '@url' => isset($original_url) ? $original_url : $url,
+      '@status' => $status,
+      '!length' => format_size(strlen($this->drupalGetContent()))
+    );
+    $message = t('!method @url returned @status (!length).', $message_vars);
+    $this->assertTrue($this->drupalGetContent() !== FALSE, $message, t('Browser'));
+    return $this->drupalGetContent();
+  }
+}
Index: tests/functional/NoAuthEndpointTestRunner.test
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/services/tests/functional/NoAuthEndpointTestRunner.test,v
retrieving revision 1.4
diff -u -p -r1.4 NoAuthEndpointTestRunner.test
--- tests/functional/NoAuthEndpointTestRunner.test	24 Dec 2010 17:25:13 -0000	1.4
+++ tests/functional/NoAuthEndpointTestRunner.test	1 Feb 2011 12:52:42 -0000
@@ -9,9 +9,6 @@
  *
  */
 
-// Parent class holds the actual tests
-require_once('ServicesEndpointTests.test') ;
-
 /**
  * Sets conditions for a no-authentication set of endpoint test runs.
  */
@@ -21,13 +18,6 @@ require_once('ServicesEndpointTests.test
   protected $privilegedUser = NULL ;
 
    /**
-    * Implementation of setUp().
-    */
-   public function setUp() {
-     parent::setUp();
-   }
-
-   /**
     * Implementation of getInfo().
     */
    public static function getInfo() {
Index: tests/functional/ServicesEndpointTests.test
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/services/tests/functional/ServicesEndpointTests.test,v
retrieving revision 1.6
diff -u -p -r1.6 ServicesEndpointTests.test
--- tests/functional/ServicesEndpointTests.test	31 Jan 2011 11:49:32 -0000	1.6
+++ tests/functional/ServicesEndpointTests.test	1 Feb 2011 12:52:42 -0000
@@ -7,7 +7,6 @@
  * Call the endpoint tests when no authentication is being used.
  *
  */
-require_once('ServicesWebTestCase.php') ;
 
 /**
  * Run test cases for the endpoint with no authentication turned on.
@@ -15,16 +14,6 @@ require_once('ServicesWebTestCase.php') 
  */
  class ServicesEndpointTests extends ServicesWebTestCase {
 
-	/**
-    * Implementation of setUp().
-    */
-   public function setUp() {
-     parent::setUp(
-     	'ctools',
-     	'services',
-      'rest_server'
-     );
-   }
 /**
     * Test adding an endpoint succeeds.
     */
Index: tests/functional/ServicesResourceNodeTests.test
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/services/tests/functional/ServicesResourceNodeTests.test,v
retrieving revision 1.2
diff -u -p -r1.2 ServicesResourceNodeTests.test
--- tests/functional/ServicesResourceNodeTests.test	27 Jan 2011 03:16:00 -0000	1.2
+++ tests/functional/ServicesResourceNodeTests.test	1 Feb 2011 12:52:42 -0000
@@ -7,8 +7,6 @@
  *
  */
 
-require_once('ServicesWebTestCase.php') ;
-
 /**
  * Run test cases for the endpoint with no authentication turned on.
  *
Index: tests/functional/ServicesWebTestCase.php
===================================================================
RCS file: tests/functional/ServicesWebTestCase.php
diff -N tests/functional/ServicesWebTestCase.php
--- tests/functional/ServicesWebTestCase.php	30 Jan 2011 16:21:04 -0000	1.4
+++ /dev/null	1 Jan 1970 00:00:00 -0000
@@ -1,422 +0,0 @@
-<?php
-// $Id: ServicesWebTestCase.php,v 1.4 2011/01/30 16:21:04 heyrocker Exp $
-
-class ServicesWebTestCase extends DrupalWebTestCase {
-
-  protected function servicesGet($url, $data = NULL, $headers = array()) {
-    $options = array('query' => $data);
-    $url = url($this->getAbsoluteUrl($url) . '.php', $options);
-    $headers = array();
-    $content = $this->curlExec(array(
-      CURLOPT_HTTPGET => TRUE,
-      CURLOPT_URL => $url,
-      CURLOPT_NOBODY => FALSE,
-      CURLOPT_RETURNTRANSFER => TRUE,
-      CURLOPT_HEADER => TRUE,
-      CURLOPT_HTTPHEADER => $headers
-    ));
-
-    // Parse response.
-    list($info, $header, $status, $code, $body) = $this->parseHeader($content);
-
-    $this->verbose('GET request to: ' . $url .
-                   '<hr />Arguments: ' . highlight_string('<?php ' . var_export($data, TRUE), TRUE) .
-                   '<hr />Response: ' . highlight_string('<?php ' . var_export($body, TRUE), TRUE) .
-                   '<hr />Raw response: ' . $content);
-    return array('header' => $header, 'status' => $status, 'code' => $code, 'body' => $body);
-  }
-
-  protected function servicesPost($url, $data = array(), $headers = array()) {
-    $options = array();
-    // Add .php to get serialized response.
-    $url = $this->getAbsoluteUrl($url) . '.php';
-
-    // Otherwise Services will reject arguments.
-    $headers = array("Content-type: application/x-www-form-urlencoded");
-    // Prepare arguments.
-    $post = http_build_query($data, '', '&');
-
-    $content = $this->curlExec(array(
-      CURLOPT_URL => $url,
-      CURLOPT_POST => TRUE,
-      CURLOPT_POSTFIELDS => $post,
-      CURLOPT_HTTPHEADER => $headers,
-      CURLOPT_HEADER => TRUE,
-      CURLOPT_RETURNTRANSFER => TRUE
-    ));
-
-    // Parse response.
-    list($info, $header, $status, $code, $body) = $this->parseHeader($content);
-
-    $this->verbose('POST request to: ' . $url .
-                   '<hr />Arguments: ' . highlight_string('<?php ' . var_export($data, TRUE), TRUE) .
-                   '<hr />Response: ' . highlight_string('<?php ' . var_export($body, TRUE), TRUE) .
-                   '<hr />Curl info: ' . highlight_string('<?php ' . var_export($info, TRUE), TRUE) .
-                   '<hr />Raw response: ' . $content);
-    return array('header' => $header, 'status' => $status, 'code' => $code, 'body' => $body);
-  }
-
-  protected function servicesPut($url, $data = NULL, $headers = array()) {
-    $options = array();
-    $url = $this->getAbsoluteUrl($url) . '.php';
-
-    $serialize_args = serialize($data);
-
-    // Set up headers so arguments will be unserialized.
-    $headers = array("Content-type: application/vnd.php.serialized; charset=iso-8859-1");
-
-    // Emulate file.
-    $putData = fopen('php://memory', 'rw+');
-    fwrite($putData, $serialize_args);
-    fseek($putData, 0);
-
-    $content = $this->curlExec(array(
-      CURLOPT_URL => $url,
-      CURLOPT_RETURNTRANSFER => TRUE,
-      CURLOPT_PUT => TRUE,
-      CURLOPT_HEADER => TRUE,
-      CURLOPT_HTTPHEADER => $headers,
-      CURLOPT_INFILE => $putData,
-      CURLOPT_INFILESIZE => strlen($serialize_args)
-    ));
-    fclose($putData);
-
-    // Parse response.
-    list($info, $header, $status, $code, $body) = $this->parseHeader($content);
-
-    $this->verbose('PUT request to: ' . $url .
-                   '<hr />Arguments: ' . highlight_string('<?php ' . var_export($data, TRUE), TRUE) .
-                   '<hr />Response: ' . highlight_string('<?php ' . var_export($body, TRUE), TRUE) .
-                   '<hr />Curl info: ' . highlight_string('<?php ' . var_export($info, TRUE), TRUE) .
-                   '<hr />Raw response: ' . $content);
-    return array('header' => $header, 'status' => $status, 'code' => $code, 'body' => $body);
-  }
-
-  protected function servicesDelete($url, $data = NULL, $headers = array()) {
-    $options = array('query' => $data);
-    $url = url($this->getAbsoluteUrl($url) . '.php', $options);
-
-    $content = $this->curlExec(array(
-      CURLOPT_URL => $url,
-      CURLOPT_CUSTOMREQUEST => "DELETE",
-      CURLOPT_HTTPHEADER => $headers,
-      CURLOPT_RETURNTRANSFER => TRUE
-    ));
-
-    // Parse response.
-    list($info, $header, $status, $code, $body) = $this->parseHeader($content);
-
-    $this->verbose('DELETE request to: ' . $url .
-                   '<hr />Arguments: ' . highlight_string('<?php ' . var_export($data, TRUE), TRUE) .
-                   '<hr />Response: ' . highlight_string('<?php ' . var_export($body, TRUE), TRUE) .
-                   '<hr />Curl info: ' . highlight_string('<?php ' . var_export($info, TRUE), TRUE) .
-                   '<hr />Raw response: ' . $content);
-    return array('header' => $header, 'status' => $status, 'code' => $code, 'body' => $body);
-  }
-
-  /*
-  ------------------------------------
-  HELPER METHODS
-  ------------------------------------
-  */
-
-  /**
-   * Parse header.
-   *
-   * @param type $content
-   * @return type
-   */
-  function parseHeader($content) {
-    $info = curl_getinfo($this->curlHandle);
-    $header = substr($content, 0, $info['header_size']);
-    $header = str_replace("HTTP/1.1 100 Continue\r\n\r\n", '', $header);
-    $status = strtok($header, "\r\n");
-    $code = $info['http_code'];
-    $body = unserialize(substr($content, $info['header_size'], strlen($content) - $info['header_size']));
-    return array($info, $header, $status, $code, $body);
-  }
-
-  /**
-   * Creates a data array for populating an endpoint creation form.
-   *
-   * @return
-   * An array of fields for fully populating an endpoint creation form.
-   */
-  public function populateEndpointFAPI() {
-    return array(
-      'name'   => 'machinename',
-      'title'  => $this->randomName(20),
-      'path'   => $this->randomName(10),
-      'server' => 'rest_server',
-    );
-  }
-
-  public function saveNewEndpoint() {
-    $edit = $this->populateEndpointFAPI() ;
-    $endpoint = new stdClass;
-    $endpoint->disabled = FALSE; /* Edit this to true to make a default endpoint disabled initially */
-    $endpoint->api_version = 3;
-    $endpoint->name = $edit['name'];
-    $endpoint->title = $edit['title'];
-    $endpoint->server = $edit['server'];
-    $endpoint->path = $edit['path'];
-    $endpoint->authentication = array();
-    $endpoint->resources = array(
-      'node' => array(
-        'alias' => '',
-        'operations' => array(
-          'create' => array(
-            'enabled' => 1,
-          ),
-          'retrieve' => array(
-            'enabled' => 1,
-          ),
-          'update' => array(
-            'enabled' => 1,
-          ),
-          'delete' => array(
-            'enabled' => 1,
-          ),
-          'index' => array(
-            'enabled' => 1,
-          ),
-        ),
-      ),
-      'system' => array(
-        'alias' => '',
-        'actions' => array(
-          'connect' => array(
-            'enabled' => 1,
-          ),
-          'get_variable' => array(
-            'enabled' => 1,
-          ),
-          'set_variable' => array(
-            'enabled' => 1,
-          ),
-        ),
-      ),
-      'taxonomy_term' => array(
-        'alias' => '',
-        'operations' => array(
-          'create' => array(
-            'enabled' => 1,
-          ),
-          'retrieve' => array(
-            'enabled' => 1,
-          ),
-          'update' => array(
-            'enabled' => 1,
-          ),
-          'delete' => array(
-            'enabled' => 1,
-          ),
-        ),
-        'actions' => array(
-          'selectNodes' => array(
-            'enabled' => 1,
-          ),
-        ),
-      ),
-      'taxonomy_vocabulary' => array(
-        'alias' => '',
-        'operations' => array(
-          'create' => array(
-            'enabled' => 1,
-          ),
-          'retrieve' => array(
-            'enabled' => 1,
-          ),
-          'update' => array(
-            'enabled' => 1,
-          ),
-          'delete' => array(
-            'enabled' => 1,
-          ),
-        ),
-        'actions' => array(
-          'getTree' => array(
-            'enabled' => 1,
-          ),
-        ),
-      ),
-      'user' => array(
-        'alias' => '',
-        'operations' => array(
-          'create' => array(
-            'enabled' => 1,
-          ),
-          'retrieve' => array(
-            'enabled' => 1,
-          ),
-          'update' => array(
-            'enabled' => 1,
-          ),
-          'delete' => array(
-            'enabled' => 1,
-          ),
-          'index' => array(
-            'enabled' => 1,
-          ),
-        ),
-        'actions' => array(
-          'login' => array(
-            'enabled' => 1,
-          ),
-          'logout' => array(
-            'enabled' => 1,
-          ),
-        ),
-      ),
-      'comment' => array(
-        'alias' => '',
-        'operations' => array(
-          'create' => array(
-            'enabled' => 1,
-          ),
-          'retrieve' => array(
-            'enabled' => 1,
-          ),
-          'update' => array(
-            'enabled' => 1,
-          ),
-          'delete' => array(
-            'enabled' => 1,
-          ),
-        ),
-        'actions' => array(
-          'loadNodeComments' => array(
-            'enabled' => 1,
-          ),
-          'countAll' => array(
-            'enabled' => 1,
-          ),
-          'countNew' => array(
-            'enabled' => 1,
-          ),
-        ),
-      ),
-      'file' => array(
-        'alias' => '',
-        'operations' => array(
-          'create' => array(
-            'enabled' => 1,
-          ),
-          'retrieve' => array(
-            'enabled' => 1,
-          ),
-          'delete' => array(
-            'enabled' => 1,
-          ),
-        ),
-        'actions' => array(
-          'nodeFiles' => array(
-            'enabled' => 1,
-          ),
-        ),
-      ),
-      'echo' => array(
-        'alias' => '',
-        'operations' => array(
-          'index' => array(
-            'enabled' => 1,
-          ),
-        ),
-      ),
-    );
-    $endpoint->debug = 1;
-    $endpoint->status = 1;
-    services_endpoint_save($endpoint);
-    $endpoint = services_endpoint_load($endpoint->name);
-    $this->assertTrue($endpoint->name == $edit['name'], t('Endpoint successfully created'));
-    return $endpoint;
-  }
-
-  /**
-   * Performs a cURL exec with the specified options after calling curlConnect().
-   *
-   * @param $curl_options
-   *   Custom cURL options.
-   * @return
-   *   Content returned from the exec.
-   */
-  protected function curlExec($curl_options, $redirect = FALSE) {
-    $this->curlInitialize();
-
-    // cURL incorrectly handles URLs with a fragment by including the
-    // fragment in the request to the server, causing some web servers
-    // to reject the request citing "400 - Bad Request". To prevent
-    // this, we strip the fragment from the request.
-    // TODO: Remove this for Drupal 8, since fixed in curl 7.20.0.
-    if (!empty($curl_options[CURLOPT_URL]) && strpos($curl_options[CURLOPT_URL], '#')) {
-      $original_url = $curl_options[CURLOPT_URL];
-      $curl_options[CURLOPT_URL] = strtok($curl_options[CURLOPT_URL], '#');
-    }
-
-    $url = empty($curl_options[CURLOPT_URL]) ? curl_getinfo($this->curlHandle, CURLINFO_EFFECTIVE_URL) : $curl_options[CURLOPT_URL];
-
-    if (!empty($curl_options[CURLOPT_POST])) {
-      // This is a fix for the Curl library to prevent Expect: 100-continue
-      // headers in POST requests, that may cause unexpected HTTP response
-      // codes from some webservers (like lighttpd that returns a 417 error
-      // code). It is done by setting an empty "Expect" header field that is
-      // not overwritten by Curl.
-      $curl_options[CURLOPT_HTTPHEADER][] = 'Expect:';
-    }
-    curl_setopt_array($this->curlHandle, $this->additionalCurlOptions + $curl_options);
-
-    if (!$redirect) {
-      // Reset headers, the session ID and the redirect counter.
-      $this->session_id = NULL;
-      $this->headers = array();
-      $this->redirect_count = 0;
-    }
-
-    $content = curl_exec($this->curlHandle);
-    $status = curl_getinfo($this->curlHandle, CURLINFO_HTTP_CODE);
-
-    // cURL incorrectly handles URLs with fragments, so instead of
-    // letting cURL handle redirects we take of them ourselves to
-    // to prevent fragments being sent to the web server as part
-    // of the request.
-    // TODO: Remove this for Drupal 8, since fixed in curl 7.20.0.
-    if (in_array($status, array(300, 301, 302, 303, 305, 307)) && $this->redirect_count < variable_get('simpletest_maximum_redirects', 5)) {
-      if ($this->drupalGetHeader('location')) {
-        $this->redirect_count++;
-        $curl_options = array();
-        $curl_options[CURLOPT_URL] = $this->drupalGetHeader('location');
-        $curl_options[CURLOPT_HTTPGET] = TRUE;
-        return $this->curlExec($curl_options, TRUE);
-      }
-    }
-
-    $this->drupalSetContent($content, isset($original_url) ? $original_url : curl_getinfo($this->curlHandle, CURLINFO_EFFECTIVE_URL));
-
-    // Analyze the method for log message.
-    $method = '';
-    if (!empty($curl_options[CURLOPT_NOBODY])) {
-      $method = 'HEAD';
-    }
-
-    if (empty($method) && !empty($curl_options[CURLOPT_PUT])) {
-      $method = 'PUT';
-    }
-
-    if (empty($method) && !empty($curl_options[CURLOPT_CUSTOMREQUEST])) {
-      $method = $curl_options[CURLOPT_CUSTOMREQUEST];
-    }
-
-    if (empty($method)) {
-      $method = empty($curl_options[CURLOPT_POSTFIELDS]) ? 'GET' : 'POST';
-    }
-    $message_vars = array(
-      '!method' => $method,
-      '@url' => isset($original_url) ? $original_url : $url,
-      '@status' => $status,
-      '!length' => format_size(strlen($this->drupalGetContent()))
-    );
-    $message = t('!method @url returned @status (!length).', $message_vars);
-    $this->assertTrue($this->drupalGetContent() !== FALSE, $message, t('Browser'));
-    return $this->drupalGetContent();
-  }
-}
