From c7b0594b1be921d16d665a36bd0a0f979fb74beb Mon Sep 17 00:00:00 2001
From: Kyle Browning <kylebrowning@me.com>
Date: Thu, 26 May 2011 17:35:30 -0700
Subject: [PATCH] Files Test

---
 resources/file_resource.inc                     |   74 +++++++----------------
 servers/rest_server/includes/RESTServer.inc     |    2 +-
 tests/functional/ServicesResourceFileTests.test |    2 +-
 tests/services.test                             |   29 +++++++++-
 4 files changed, 52 insertions(+), 55 deletions(-)

diff --git a/resources/file_resource.inc b/resources/file_resource.inc
index 1a5bf43..070cba8 100644
--- a/resources/file_resource.inc
+++ b/resources/file_resource.inc
@@ -21,13 +21,6 @@ function _file_resource_definition() {
         'access arguments' => array('create'),
         'access arguments append' => TRUE,
         'args' => array(
-          array(
-            'name' => 'file',
-            'type' => 'array',
-            'description'    => t('An array representing a file.'),
-            'source' => 'data',
-            'optional' => FALSE,
-          ),
         ),
       ),
       'retrieve' => array(
@@ -115,53 +108,28 @@ function _file_resource_definition() {
  * @return
  *   Unique identifier for the file (fid) or errors if there was a problem.
  */
-function _file_resource_create($file) {
-  global $user;
-  $file = (object) $file;
-
-  // If the file data is empty then bail
-  if (!isset($file->file)) {
-    return FALSE;
-  }
-
-  // Make sure we create new file.
-  $file->fid = NULL;
-
-  // Get the directory name for the location of the file:
-  if (isset($file->filename) && !isset($file->filepath)) {
-    $file->filepath = file_default_scheme() . '://' . $file->filename;
-  }
-  $dir = file_default_scheme() . '://';
-  // Build the destination folder tree if it doesn't already exists.
-  if (!file_prepare_directory($dir, FILE_CREATE_DIRECTORY)) {
-    return services_error(t("Could not create destination directory for file."), 500);
-  }
-
-  $file->filemime = file_get_mimetype($file->filename);
-
-  // Rename potentially executable files, to help prevent exploits.
-  if (preg_match('/\.(php|pl|py|cgi|asp|js)$/i', $file->filename) && (drupal_substr($file->filename, -4) != '.txt')) {
-    $file->filemime = 'text/plain';
-    $file->filepath .= '.txt';
-    $file->filename .= '.txt';
-  }
-
-  // Update the timestamp to the current time, otherwise the file could
-  // get deleted on the next cron run if its status is set to 0.
-  $file->timestamp = time();
-  
-  // Write the file
-  if (!$file = file_save_data(base64_decode($file->file), $file->filepath)) {
-    return services_error(t("Could not write file to destination"), 500);
+function _file_resource_create() {
+  $validators = array(
+    'file_validate_extensions' => array(),
+    'file_validate_size' => array(),
+  );
+  $files = array();
+  foreach ($_FILES['files']['name'] as $field_name => $file_name) {
+    $file = file_save_upload($field_name, $validators, file_default_scheme() . "://");
+    // Required to be able to reference this file.
+    if ($file->fid) {
+      file_usage_add($file, 'services', 'files', $file->fid);
+      $files[] = array(
+        'fid' => $file->fid,
+        'uri' => services_resource_uri(array('file', $file->fid)),
+      ); 
+    } 
+    else {
+      return services_error(t('An unknown error occured', 500));
+    }
   }
 
-  // Required to be able to reference this file.
-  file_usage_add($file, 'services', 'files', $file->fid);
-
-  return array(
-    'fid' => $file->fid,
-    'uri' => services_resource_uri(array('file', $file->fid)),
-  );
+  return $files;
 }
 
 /**
@@ -177,6 +145,7 @@ function _file_resource_create($file) {
 function _file_resource_retrieve($fid, $include_file_contents = TRUE) {
   if ($file = file_load($fid)) {
     $filepath = $file->uri;
+    $file->url = file_create_url($file->uri);
     if ($include_file_contents) {
       $file->file = base64_encode(file_get_contents($filepath));
     }
@@ -257,6 +226,7 @@ function _file_resource_access($op = 'view', $args = array()) {
       return $file->uid == $user->uid && user_access('get own binary files');
       break;
     case 'create':
+      return user_access('save file information');
     case 'delete':
       return $file->uid == $user->uid && user_access('save file information');
       break;
diff --git a/servers/rest_server/includes/RESTServer.inc b/servers/rest_server/includes/RESTServer.inc
index ed3adcb..6049678 100755
--- a/servers/rest_server/includes/RESTServer.inc
+++ b/servers/rest_server/includes/RESTServer.inc
@@ -254,7 +254,7 @@ class RESTServer {
     }
     switch ($method) {
       case 'POST':
-        if (isset($type['value']) && $type['value'] == 'application/x-www-form-urlencoded') {
+        if (isset($type['value']) && ($type['value'] == 'application/x-www-form-urlencoded' || $type['value'] == "multipart/form-data")) {
           return $_POST;
         }
       case 'PUT':
diff --git a/tests/functional/ServicesResourceFileTests.test b/tests/functional/ServicesResourceFileTests.test
index 6dc3545..be0233f 100644
--- a/tests/functional/ServicesResourceFileTests.test
+++ b/tests/functional/ServicesResourceFileTests.test
@@ -104,7 +104,7 @@ class ServicesResourceFileTests extends ServicesWebTestCase {
     );
 
     // Create file with call.
-    $result = $this->servicesPost($this->endpoint->path . '/file', array('file' => $file));
+    $result = $this->servicesPostFile($this->endpoint->path . '/file', $this->testfile->uri);
     $this->assertEqual($result['code'], 200, t('File created.'), 'FileResource: Create');
 
     // Load file and assert that it exists.
diff --git a/tests/services.test b/tests/services.test
index 46da1fe..a573fe3 100644
--- a/tests/services.test
+++ b/tests/services.test
@@ -40,6 +40,34 @@ class ServicesWebTestCase extends DrupalWebTestCase {
     return array('header' => $header, 'status' => $status, 'code' => $code, 'body' => $body);
   }
 
+  protected function servicesPostFile($url, $filepath, $headers = array()) {
+    $options = array();
+    // Add .php to get serialized response.
+    $url = $this->getAbsoluteUrl($url) . '.php';
+
+    // Otherwise Services will reject arguments.
+    $headers = array("Content-type: multipart/form-data");
+    // Prepare arguments.
+    $post = array('file_contents'=>'@'.$filepath); 
+
+    $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 />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 servicesPost($url, $data = array(), $headers = array()) {
     $options = array();
     // Add .php to get serialized response.
@@ -69,7 +97,6 @@ class ServicesWebTestCase extends DrupalWebTestCase {
                    '<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';
-- 
1.7.3.4

