Index: plupload.module
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/plupload/plupload.module,v
retrieving revision 1.1.2.10
diff -u -p -r1.1.2.10 plupload.module
--- plupload.module	15 Dec 2010 14:54:42 -0000	1.1.2.10
+++ plupload.module	22 Dec 2010 16:08:25 -0000
@@ -139,77 +139,101 @@ __RSD__;
 }
 
 function plupload_pernode() {
-  $temp_directory = file_directory_temp();
-
   // Chunk it?
   $chunk = isset($_REQUEST["chunk"]) ? $_REQUEST["chunk"] : 0;
   $chunks = isset($_REQUEST["chunks"]) ? $_REQUEST["chunks"] : 0;
-  
-  // Get and clean the filename.
-  $file_name = isset($_REQUEST["name"]) ? $_REQUEST["name"] : '';
 
-  // Clean the fileName for security reasons
-  $file_name = preg_replace('/[^\w\._]+/', '', $file_name);
-  
-  
   // Look for the content type header
-  if (isset($_SERVER["HTTP_CONTENT_TYPE"])) {
-    $content_type = $_SERVER["HTTP_CONTENT_TYPE"];
-  }
+  $content_type = '';
   if (isset($_SERVER["CONTENT_TYPE"])) {
     $content_type = $_SERVER["CONTENT_TYPE"];
   }
+  elseif (isset($_SERVER["HTTP_CONTENT_TYPE"])) {
+    $content_type = $_SERVER["HTTP_CONTENT_TYPE"];
+  }
 
-  // Is this a multipart upload?
-  if (strpos($content_type, "multipart") !== false) {
-    if (isset($_FILES['file']['tmp_name']) && is_uploaded_file($_FILES['file']['tmp_name'])) {
-      // Open temp file
-      $out = fopen($temp_directory . DIRECTORY_SEPARATOR . $file_name, $chunk == 0 ? "wb" : "ab");
-      if ($out) {
-        // Read binary input stream and append it to temp file
-        $in = fopen($_FILES['file']['tmp_name'], "rb");
-
-        if ($in) {
-          while ($buff = fread($in, 4096))
-            fwrite($out, $buff);
-        } else
-          die('{"jsonrpc" : "2.0", "error" : {"code": 101, "message": "Failed to open input stream."}, "id" : "id"}');
-
-        fclose($in);
-        fclose($out);
-        unlink($_FILES['file']['tmp_name']);
-      } else
-        die('{"jsonrpc" : "2.0", "error" : {"code": 102, "message": "Failed to open output stream."}, "id" : "id"}');
-    } else
+  if (strpos($content_type, "multipart") !== FALSE) {
+    // usual multipart file upload. Get filename from PHP files array.
+    if (empty($_FILES['file']['tmp_name']) || !is_uploaded_file($_FILES['file']['tmp_name'])) {
       die('{"jsonrpc" : "2.0", "error" : {"code": 103, "message": "Failed to move uploaded file."}, "id" : "id"}');
+    }
+    // check upload errors
+    $message = FALSE;
+    switch ($_FILES['file']['error']) {
+      // @see http://php.net/manual/en/features.file-upload.errors.php
+      case UPLOAD_ERR_OK:
+        break;
+
+      case UPLOAD_ERR_INI_SIZE:
+      case UPLOAD_ERR_FORM_SIZE:
+        $message = t('The file %file could not be saved, because it exceeds %maxsize, the maximum allowed size for uploads.', array('%file' => $source, '%maxsize' => format_size(file_upload_max_size())));
+        break;
+
+      case UPLOAD_ERR_PARTIAL:
+      case UPLOAD_ERR_NO_FILE:
+        $message = t('The file %file could not be saved, because the upload did not complete.', array('%file' => $source));
+        break;
+
+      // Unknown error
+      default:
+        $message = t('The file %file could not be saved. An unknown error has occurred.', array('%file' => $source));
+    }
+    if ($message) {
+      die('{"jsonrpc" : "2.0", "error" : {"code": 102, "message": "' . $message . '"}, "id" : "id"}');
+    }
+    $input_file = $_FILES['file']['tmp_name'];
+    $filename = $_FILES['file']['name'];
   }
   else {
-    // Open temp file
-    $out = fopen($temp_directory . DIRECTORY_SEPARATOR . $file_name, $chunk == 0 ? "wb" : "ab");
-    if ($out) {
-      // Read binary input stream and append it to temp file
-      $in = fopen("php://input", "rb");
-
-      if ($in) {
-        while ($buff = fread($in, 4096))
-          fwrite($out, $buff);
-      } else
-        die('{"jsonrpc" : "2.0", "error" : {"code": 101, "message": "Failed to open input stream."}, "id" : "id"}');
-
-      fclose($in); 
-      fclose($out);
-    } else
-      die('{"jsonrpc" : "2.0", "error" : {"code": 102, "message": "Failed to open output stream."}, "id" : "id"}');
+    // the file must be read from the raw post request data,
+    // in this case the filename is passed through the query string.
+    $input_file = 'php://input';
+    if (empty($_REQUEST["name"])) {
+      die('{"jsonrpc" : "2.0", "error" : {"code": 102, "message": "No filename passed."}, "id" : "id"}');
+    }
+    $filename = preg_replace('/[^\w\._-]+/', '', $_REQUEST["name"]);
   }
-  
+  $filename = trim(basename($filename), '.');
+  $extensions = '';
+  global $user;
+  foreach ($user->roles as $rid => $name) {
+    $extensions .= ' '. variable_get("upload_extensions_$rid",
+    variable_get('upload_extensions_default', 'jpg jpeg gif png txt html doc xls pdf ppt pps odt ods odp'));
+  }
+  $filename = file_munge_filename($filename, $extensions);
+  if (preg_match('/\.(php|pl|py|cgi|asp|js)$/i', $filename) && (substr($filename, -4) != '.txt')) {
+    $filename .= '.txt';
+    // As the file may be named example.php.txt, we need to munge again to
+    // convert to example.php_.txt, then create the correct destination.
+    $filename = file_munge_filename($filename, $extensions);
+  }
+
+  // create a temporary file with the same name and append the input.
+  $temp_filepath = file_create_filename($filename, file_directory_temp());
+  $out = fopen($temp_filepath, $chunk == 0 ? "wb" : "ab");
+  if ($out === FALSE) {
+    die('{"jsonrpc" : "2.0", "error" : {"code": 102, "message": "Failed to create temporary file."}, "id" : "id"}');
+  }
+  $in = fopen($input_file, "rb");
+  if ($in === FALSE) {
+    die('{"jsonrpc" : "2.0", "error" : {"code": 101, "message": "Failed to open input stream."}, "id" : "id"}');
+  }
+  while ($buff = fread($in, 4096)) {
+    fwrite($out, $buff);
+  }
+  fclose($in);
+  fclose($out);
+
+  // if it was a multipart upload delete the temporary file that PHP created.
+  if (strpos($content_type, "multipart") !== FALSE) {
+    unlink($input_file);
+  }
+
+  // stop here if its a chunked upload and more chunks are coming.
   if ($chunks > 1 && $chunk < $chunks - 1) {
-    // Don't move the file and add the node yet, we have more chunks coming
     die('{"jsonrpc" : "2.0", "result" : null, "id" : "id"}');
   }
 
-  // Move it to it's final home.
-  $path = file_directory_path();
-  
   // Pull off all the options from the query string for later attachment to the node.
   $options = array();
   foreach (array_keys($_GET) as $k) {
@@ -218,11 +242,9 @@ function plupload_pernode() {
       $options[substr($k, strlen(PLUPLOAD_URL_PARAM_PREFIX))] = $_GET[$k];
     }
   }
-
-  $image_node = plupload_imagefield_create_node_from($temp_directory . DIRECTORY_SEPARATOR . $file_name, $file_name, $options);
-
+  $image_node = plupload_imagefield_create_node_from($temp_filepath, $filename, $options);
   // @todo check the $image_node and do some error handling.
-  
+
   // Return JSON-RPC response
   die('{"jsonrpc" : "2.0", "result" : null, "id" : "id"}');
 }
@@ -238,7 +260,7 @@ function plupload_pernode() {
  * @return $node
  *   a node object.
  */
-function plupload_imagefield_create_node_from($temp_filepath, $file_name, $options) {
+function plupload_imagefield_create_node_from($temp_filepath, $filename, $options) {
   // Only get files from Drupal's tmp directory.
   $directory = file_directory_temp();
   if (file_check_location($temp_filepath, $directory)) {
@@ -266,7 +288,7 @@ function plupload_imagefield_create_node
   
       // Create some defaults that imagefield expects.
       $form_state_values = array(
-        'title' => $file_name,
+        'title' => $filename,
         'body' => '',
         'field_photo' => array(0 => array(
             'fid' => 0,
@@ -289,7 +311,7 @@ function plupload_imagefield_create_node
         'node_status' => NULL,
         )
       );
-      // Save the file and create a node.
+      // Actually save the file and create a node.
       if ($file = field_file_save_file($temp_filepath, $validators, $directory)) {
         $file['original_path'] = $temp_filepath;
         $node = _plupload_imagefield_import_create_node($field, $form_state_values, $file, $options);
