Index: includes/file.inc
===================================================================
RCS file: /cvs/drupal/drupal/includes/file.inc,v
retrieving revision 1.121.2.5
diff -u -p -r1.121.2.5 file.inc
--- includes/file.inc	20 Oct 2008 09:42:31 -0000	1.121.2.5
+++ includes/file.inc	6 Apr 2009 21:40:40 -0000
@@ -526,7 +526,6 @@ function file_save_upload($source, $vali
     // Begin building file object.
     $file = new stdClass();
     $file->filename = file_munge_filename(trim(basename($_FILES['files']['name'][$source]), '.'), $extensions);
-    $file->filepath = $_FILES['files']['tmp_name'][$source];
     $file->filemime = file_get_mimetype($file->filename);
 
     // Rename potentially executable files, to help prevent exploits.
@@ -546,6 +545,17 @@ function file_save_upload($source, $vali
     $file->destination = file_destination(file_create_path($dest .'/'. $file->filename), $replace);
     $file->filesize = $_FILES['files']['size'][$source];
 
+    // Move uploaded files from PHP's upload_tmp_dir to Drupal's temporary directory.
+    // This overcomes open_basedir restrictions for future file operations.
+    // This move must occur before validation as some validation tests will fail
+    // due to open_basedir restrictions.
+    $file->filepath = file_directory_temp() . '/' . trim(basename($_FILES['files']['name'][$source]));
+    if (!move_uploaded_file($_FILES['files']['tmp_name'][$source], $file->filepath)) {
+      form_set_error($source, t('File upload error. Could not move uploaded file.'));
+      watchdog('file', 'Upload error. Could not move uploaded file %file to destination %destination.', array('%file' => $file->filename, '%destination' => $temp_filepath));
+      return 0;
+    }
+
     // Call the validation functions.
     $errors = array();
     foreach ($validators as $function => $args) {
@@ -566,14 +576,13 @@ function file_save_upload($source, $vali
       return 0;
     }
 
-    // Move uploaded files from PHP's upload_tmp_dir to Drupal's temporary directory.
-    // This overcomes open_basedir restrictions for future file operations.
-    $file->filepath = $file->destination;
-    if (!move_uploaded_file($_FILES['files']['tmp_name'][$source], $file->filepath)) {
-      form_set_error($source, t('File upload error. Could not move uploaded file.'));
-      watchdog('file', 'Upload error. Could not move uploaded file %file to destination %destination.', array('%file' => $file->filename, '%destination' => $file->filepath));
+    // Move uploaded files from Drupal's temporary directory to their final destination.
+    if (!rename($file->filepath, $file->destination)) {
+      form_set_error($source, t('File moving error. Could not move uploaded file.'));
+      watchdog('file', 'Upload error. Could not move file %file to destination %destination.', array('%file' => $file->filename, '%destination' => $file->destination));
       return 0;
     }
+    $file->filepath = $file->destination;
 
     // If we made it this far it's safe to record this file in the database.
     $file->uid = $user->uid;
