Index: plupload.module
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/plupload/plupload.module,v
retrieving revision 1.1.2.11
diff -u -r1.1.2.11 plupload.module
--- plupload.module	11 Jan 2011 15:52:57 -0000	1.1.2.11
+++ plupload.module	11 Jan 2011 16:57:46 -0000
@@ -139,82 +139,108 @@
 }
 
 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"];
+  }
+  dpm($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
+    // It's the typical multipart file upload -- get the 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 for 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'];
+  dpm($filename);
   }
   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"}');
+    // The file must be read from the raw post request data.
+    // If we get here, 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"}');
+    }
+    // This replaces all non-word chars (excluding dots and dashes) in the filename with empty string.
+    $filename = preg_replace('/[^\w\._-]+/', '', $_REQUEST["name"]);
+  dpm($filename);
+  }
+  $filename = trim(basename($filename), '.');
+  dpm($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);
+  }
+  dpm($filename);
+
+  // 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);
 
-      fclose($in);
-      fclose($out);
-    }
-    else
-      die('{"jsonrpc" : "2.0", "error" : {"code": 102, "message": "Failed to open output stream."}, "id" : "id"}');
+  // If it's a multipart upload, delete the temporary file that was created.
+  if (strpos($content_type, "multipart") !== FALSE) {
+    unlink($input_file);
   }
 
+  // Stop processing now if we have 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) {
@@ -223,10 +249,11 @@
       $options[drupal_substr($k, drupal_strlen(PLUPLOAD_URL_PARAM_PREFIX))] = $_GET[$k];
     }
   }
-
-  $image_node = plupload_imagefield_create_node_from($temp_directory . DIRECTORY_SEPARATOR . $file_name, $file_name, $options);
-
-  // @todo check the $image_node and do some error handling.
+  dpm($temp_filepath);
+  dpm($filename);
+  dpm($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"}');
@@ -243,7 +270,7 @@
  * @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)) {
@@ -271,7 +298,7 @@
 
       // Create some defaults that imagefield expects.
       $form_state_values = array(
-        'title' => $file_name,
+        'title' => $filename,
         'body' => '',
         'field_photo' => array(0 => array(
             'fid' => 0,
