? .DS_Store ? .cache ? .git ? .project ? .settings ? empty ? hook_file_142995_18.patch ? logs ? modules/.DS_Store ? modules/simpletest/tests/file.test ? modules/simpletest/tests/file_test.info ? modules/simpletest/tests/file_test.module ? sites/all/modules ? sites/default/files ? sites/default/settings.php ? sites/default/test Index: includes/common.inc =================================================================== RCS file: /cvs/drupal/drupal/includes/common.inc,v retrieving revision 1.788 diff -u -p -r1.788 common.inc --- includes/common.inc 21 Aug 2008 19:36:36 -0000 1.788 +++ includes/common.inc 28 Aug 2008 14:31:36 -0000 @@ -1815,7 +1815,7 @@ function drupal_build_css_cache($types, $data = implode('', $matches[0]) . $data; // Create the CSS file. - file_save_data($data, $csspath . '/' . $filename, FILE_EXISTS_REPLACE); + file_save_data_plain($data, $csspath . '/' . $filename, FILE_EXISTS_REPLACE); } return $csspath . '/' . $filename; } @@ -1916,7 +1916,7 @@ function _drupal_load_stylesheet($matche * Delete all cached CSS files. */ function drupal_clear_css_cache() { - file_scan_directory(file_create_path('css'), '.*', array('.', '..', 'CVS'), 'file_delete', TRUE); + file_scan_directory(file_create_path('css'), '.*', array('.', '..', 'CVS'), 'file_delete_plain', TRUE); } /** @@ -2279,7 +2279,7 @@ function drupal_build_js_cache($files, $ } // Create the JS file. - file_save_data($contents, $jspath . '/' . $filename, FILE_EXISTS_REPLACE); + file_save_data_plain($contents, $jspath . '/' . $filename, FILE_EXISTS_REPLACE); } return $jspath . '/' . $filename; @@ -2290,6 +2290,7 @@ function drupal_build_js_cache($files, $ */ function drupal_clear_js_cache() { file_scan_directory(file_create_path('js'), '.*', array('.', '..', 'CVS'), 'file_delete', TRUE); + file_scan_directory(file_create_path('js'), '.*', array('.', '..', 'CVS'), 'file_delete_plain', TRUE); variable_set('javascript_parsed', array()); } Index: includes/file.inc =================================================================== RCS file: /cvs/drupal/drupal/includes/file.inc,v retrieving revision 1.128 diff -u -p -r1.128 file.inc --- includes/file.inc 14 Aug 2008 12:10:47 -0000 1.128 +++ includes/file.inc 28 Aug 2008 14:32:19 -0000 @@ -29,17 +29,18 @@ define('FILE_DOWNLOADS_PUBLIC', 1); define('FILE_DOWNLOADS_PRIVATE', 2); /** - * Flag used by file_create_directory() -- create directory if not present. + * Flag used by file_check_directory() -- create directory if not present. */ define('FILE_CREATE_DIRECTORY', 1); /** - * Flag used by file_create_directory() -- file permissions may be changed. + * Flag used by file_check_directory() -- file permissions may be changed. */ define('FILE_MODIFY_PERMISSIONS', 2); /** - * Flag for dealing with existing files: Append number until filename is unique. + * Flag for dealing with existing files: Append number until filename is + * unique. */ define('FILE_EXISTS_RENAME', 0); @@ -77,7 +78,8 @@ define('FILE_STATUS_PERMANENT', 1); * @return A string containing a URL that can be used to download the file. */ function file_create_url($path) { - // Strip file_directory_path from $path. We only include relative paths in urls. + // Strip file_directory_path from $path. We only include relative paths in + // URLs. if (strpos($path, file_directory_path() . '/') === 0) { $path = trim(substr($path, strlen(file_directory_path())), '\\/'); } @@ -93,28 +95,30 @@ function file_create_url($path) { * Make sure the destination is a complete path and resides in the file system * directory, if it is not prepend the file system directory. * - * @param $dest A string containing the path to verify. If this value is + * @param $destination A string containing the path to verify. If this value is * omitted, Drupal's 'files' directory will be used. * @return A string containing the path to file, with file system directory * appended if necessary, or FALSE if the path is invalid (i.e. outside the * configured 'files' or temp directories). */ -function file_create_path($dest = 0) { +function file_create_path($destination = NULL) { $file_path = file_directory_path(); - if (!$dest) { + if (!$destination) { return $file_path; } - // file_check_location() checks whether the destination is inside the Drupal files directory. - if (file_check_location($dest, $file_path)) { - return $dest; - } - // check if the destination is instead inside the Drupal temporary files directory. - else if (file_check_location($dest, file_directory_temp())) { - return $dest; + // file_check_location() checks whether the destination is inside the Drupal + // files directory. + if (file_check_location($destination, $file_path)) { + return $destination; + } + // Check if the destination is instead inside the Drupal temporary files + // directory. + else if (file_check_location($destination, file_directory_temp())) { + return $destination; } // Not found, try again with prefixed directory path. - else if (file_check_location($file_path . '/' . $dest, $file_path)) { - return $file_path . '/' . $dest; + else if (file_check_location($file_path . '/' . $destination, $file_path)) { + return $file_path . '/' . $destination; } // File not found. return FALSE; @@ -133,7 +137,7 @@ function file_create_path($dest = 0) { * work, a form error will be set preventing them from saving the settings. * @return FALSE when directory not found, or TRUE when directory exists. */ -function file_check_directory(&$directory, $mode = 0, $form_item = NULL) { +function file_check_directory(&$directory, $mode = FALSE, $form_item = NULL) { $directory = rtrim($directory, '/\\'); // Check if directory exists. @@ -152,9 +156,13 @@ function file_check_directory(&$director // Check to see if the directory is writable. if (!is_writable($directory)) { - if (($mode & FILE_MODIFY_PERMISSIONS) && !@chmod($directory, 0775)) { - form_set_error($form_item, t('The directory %directory is not writable', array('%directory' => $directory))); - watchdog('file system', 'The directory %directory is not writable, because it does not have the correct permissions set.', array('%directory' => $directory), WATCHDOG_ERROR); + // If not able to modify permissions, or if able to, but chmod + // fails, return false. + if (!$mode || (($mode & FILE_MODIFY_PERMISSIONS) && !@chmod($directory, 0775))) { + if ($form_item) { + form_set_error($form_item, t('The directory %directory is not writable', array('%directory' => $directory))); + watchdog('file system', 'The directory %directory is not writable, because it does not have the correct permissions set.', array('%directory' => $directory), WATCHDOG_ERROR); + } return FALSE; } } @@ -202,7 +210,8 @@ function file_check_path(&$path) { /** * Check if a file is really located inside $directory. Should be used to make * sure a file specified is really located within the directory to prevent - * exploits. + * exploits. Note that the file or path being checked does not actually need + * to exist yet. * * @code * // Returns FALSE: @@ -211,7 +220,8 @@ function file_check_path(&$path) { * * @param $source A string set to the file to check. * @param $directory A string where the file should be located. - * @return FALSE for invalid path or the real path of the source. + * @return FALSE if the path does not exist in the directory; + * otherwise, the real path of the source. */ function file_check_location($source, $directory = '') { $check = realpath($source); @@ -219,7 +229,7 @@ function file_check_location($source, $d $source = $check; } else { - // This file does not yet exist + // This file does not yet exist. $source = realpath(dirname($source)) . '/' . basename($source); } $directory = realpath($directory); @@ -230,88 +240,122 @@ function file_check_location($source, $d } /** - * Copies a file to a new location. This is a powerful function that in many ways + * Copy a file to a new location and adds a file record to the database. + * + * This function should be used when manipulating files that have records + * stored in the database. This is a powerful function that in many ways * performs like an advanced version of copy(). - * - Checks if $source and $dest are valid and readable/writable. - * - Performs a file copy if $source is not equal to $dest. - * - If file already exists in $dest either the call will error out, replace the - * file or rename the file based on the $replace parameter. - * - * @param $source A string specifying the file location of the original file. - * This parameter will contain the resulting destination filename in case of - * success. - * @param $dest A string containing the directory $source should be copied to. - * If this value is omitted, Drupal's 'files' directory will be used. - * @param $replace Replace behavior when the destination file already exists. - * - FILE_EXISTS_REPLACE - Replace the existing file - * - FILE_EXISTS_RENAME - Append _{incrementing number} until the filename is unique + * - Checks if $source and $destination are valid and readable/writable. + * - Checks that $source is not equal to $destination, if they are an error + * is reported. + * - If file already exists in $destination either the call will error out, + * replace the file or rename the file based on the $replace parameter. + * - Adds the new file to the files database. If the source file is a + * temporary file, the resulting file will also be a temporary file. + * @see file_save_upload about temporary files. + * + * @param $source + * A file object. + * @param $destination + * A string containing the directory $source should be copied to. If this + * value is omitted, Drupal's 'files' directory will be used. + * @param $replace + * Replace behavior when the destination file already exists: + * - FILE_EXISTS_REPLACE - Replace the existing file. + * - FILE_EXISTS_RENAME - Append _{incrementing number} until the filename is + * unique. * - FILE_EXISTS_ERROR - Do nothing and return FALSE. - * @return True for success, FALSE for failure. + * @return + * File object if the copy is successful, or FALSE in the event of an error. + * + * @see file_copy_plain() */ -function file_copy(&$source, $dest = 0, $replace = FILE_EXISTS_RENAME) { - $dest = file_create_path($dest); - - $directory = $dest; - $basename = file_check_path($directory); - - // Make sure we at least have a valid directory. - if ($basename === FALSE) { - $source = is_object($source) ? $source->filepath : $source; - drupal_set_message(t('The selected file %file could not be uploaded, because the destination %directory is not properly configured.', array('%file' => $source, '%directory' => $dest)), 'error'); - watchdog('file system', 'The selected file %file could not be uploaded, because the destination %directory could not be found, or because its permissions do not allow the file to be written.', array('%file' => $source, '%directory' => $dest), WATCHDOG_ERROR); - return FALSE; - } - - // Process a file upload object. - if (is_object($source)) { - $file = $source; - $source = $file->filepath; - if (!$basename) { - $basename = $file->filename; +function file_copy($source, $destination = NULL, $replace = FILE_EXISTS_RENAME) { + if ($result = file_copy_plain($source->filepath, $destination, $replace)) { + $file = clone $source; + $file->fid = NULL; + $file->filename = basename($result); + $file->filepath = $result; + if ($file = file_save($file)) { + module_invoke_all('file_copy', $file, $source); + return $file; } } + return FALSE; +} +/** + * Copy a file to a new location without saving a record in the database. + * + * This is a powerful function that in many ways performs like an advanced + * version of copy(). + * - Checks if $source and $destination are valid and readable/writable. + * - Checks that $source is not equal to $destination, if they are an error + * is reported. + * - If file already exists in $destination either the call will error out, + * replace the file or rename the file based on the $replace parameter. + * + * @param $source + * A string specifying the file location of the original file. + * @param $destination + * A string containing the directory $source should be copied to. If this + * value is omitted, Drupal's 'files' directory will be used. + * @param $replace + * Replace behavior when the destination file already exists: + * - FILE_EXISTS_REPLACE - Replace the existing file. + * - FILE_EXISTS_RENAME - Append _{incrementing number} until the filename is + * unique. + * - FILE_EXISTS_ERROR - Do nothing and return FALSE. + * @return + * The path to the new file, or FALSE in the event of an error. + * + * @see file_copy() + */ +function file_copy_plain($source, $destination = NULL, $replace = FILE_EXISTS_RENAME) { $source = realpath($source); if (!file_exists($source)) { - drupal_set_message(t('The selected file %file could not be copied, because no file by that name exists. Please check that you supplied the correct filename.', array('%file' => $source)), 'error'); + drupal_set_message(t('The specified file %file could not be copied, because no file by that name exists. Please check that you supplied the correct filename.', array('%file' => $source)), 'error'); return FALSE; } - // If the destination file is not specified then use the filename of the source file. - $basename = $basename ? $basename : basename($source); - $dest = $directory . '/' . $basename; + $destination = file_create_path($destination); + $directory = $destination; + $basename = file_check_path($directory); - // Make sure source and destination filenames are not the same, makes no sense - // to copy it if they are. In fact copying the file will most likely result in - // a 0 byte file. Which is bad. Real bad. - if ($source != realpath($dest)) { - if (!$dest = file_destination($dest, $replace)) { - drupal_set_message(t('The selected file %file could not be copied, because a file by that name already exists in the destination.', array('%file' => $source)), 'error'); - return FALSE; - } + // Make sure we at least have a valid directory. + if ($basename === FALSE) { + drupal_set_message(t('The specified file %file could not be copied, because the destination %directory is not properly configured.', array('%file' => $source, '%directory' => $destination)), 'error'); + return FALSE; + } - if (!@copy($source, $dest)) { - drupal_set_message(t('The selected file %file could not be copied.', array('%file' => $source)), 'error'); - return FALSE; - } + // If the destination file is not specified then use the filename of the + // source file. + $basename = $basename ? $basename : basename($source); + $destination = file_destination($directory . '/' . $basename, $replace); - // Give everyone read access so that FTP'd users or - // non-webserver users can see/read these files, - // and give group write permissions so group members - // can alter files uploaded by the webserver. - @chmod($dest, 0664); + if ($destination === FALSE) { + drupal_set_message(t('The specified file %file could not be copied because a file by that name already exists in the destination.', array('%file' => $source)), 'error'); + return FALSE; } - - if (isset($file) && is_object($file)) { - $file->filename = $basename; - $file->filepath = $dest; - $source = $file; + // Make sure source and destination filenames are not the same, makes no + // sense to copy it if they are. In fact copying the file will most likely + // result in a 0 byte file. Which is bad. Real bad. + if ($source == realpath($destination)) { + drupal_set_message(t('The specified file %file was not copied because it would overwrite itself.', array('%file' => $source)), 'error'); + return FALSE; } - else { - $source = $dest; + if (!@copy($source, $destination)) { + drupal_set_message(t('The specified file %file could not be copied.', array('%file' => $source)), 'error'); + return FALSE; } - return TRUE; // Everything went ok. + // Give everyone read access so that FTP'd users or + // non-webserver users can see/read these files, + // and give group write permissions so group members + // can alter files uploaded by the webserver. + @chmod($destination, 0664); + + return $destination; } /** @@ -320,9 +364,9 @@ function file_copy(&$source, $dest = 0, * * @param $destination A string specifying the desired path. * @param $replace Replace behavior when the destination file already exists. - * - FILE_EXISTS_REPLACE - Replace the existing file + * - FILE_EXISTS_REPLACE - Replace the existing file. * - FILE_EXISTS_RENAME - Append _{incrementing number} until the filename is - * unique + * unique. * - FILE_EXISTS_ERROR - Do nothing and return FALSE. * @return The destination file path or FALSE if the file already exists and * FILE_EXISTS_ERROR was specified. @@ -330,6 +374,10 @@ function file_copy(&$source, $dest = 0, function file_destination($destination, $replace) { if (file_exists($destination)) { switch ($replace) { + case FILE_EXISTS_REPLACE: + // Do nothing here, we want to overwrite the existing file. + break; + case FILE_EXISTS_RENAME: $basename = basename($destination); $directory = dirname($destination); @@ -337,7 +385,7 @@ function file_destination($destination, break; case FILE_EXISTS_ERROR: - drupal_set_message(t('The selected file %file could not be copied, because a file by that name already exists in the destination.', array('%file' => $destination)), 'error'); + drupal_set_message(t('The specified file %file could not be copied, because a file by that name already exists in the destination.', array('%file' => $destination)), 'error'); return FALSE; } } @@ -345,38 +393,75 @@ function file_destination($destination, } /** - * Moves a file to a new location. - * - Checks if $source and $dest are valid and readable/writable. - * - Performs a file move if $source is not equal to $dest. - * - If file already exists in $dest either the call will error out, replace the - * file or rename the file based on the $replace parameter. - * - * @param $source A string specifying the file location of the original file. - * This parameter will contain the resulting destination filename in case of - * success. - * @param $dest A string containing the directory $source should be copied to. - * If this value is omitted, Drupal's 'files' directory will be used. - * @param $replace Replace behavior when the destination file already exists. - * - FILE_EXISTS_REPLACE - Replace the existing file - * - FILE_EXISTS_RENAME - Append _{incrementing number} until the filename is unique + * Move a file to a new location and update the file's database entry. + * + * Moving a file is performed by copying the file to the new location and then + * deleting the original. + * - Checks if $source and $destination are valid and readable/writable. + * - Performs a file move if $source is not equal to $destination. + * - If file already exists in $destination either the call will error out, + * replace the file or rename the file based on the $replace parameter. + * - Adds the new file to the files database. + * + * @param $source + * A file object. + * @param $destination + * A string containing the directory $source should be copied to. If this + * value is omitted, Drupal's 'files' directory will be used. + * @param $replace + * Replace behavior when the destination file already exists: + * - FILE_EXISTS_REPLACE - Replace the existing file. + * - FILE_EXISTS_RENAME - Append _{incrementing number} until the filename is + * unique. * - FILE_EXISTS_ERROR - Do nothing and return FALSE. - * @return TRUE for success, FALSE for failure. + * @return + * Resulting file object for success, or FALSE in the event of an error. + * + * @see file_move_plain() */ -function file_move(&$source, $dest = 0, $replace = FILE_EXISTS_RENAME) { - $path_original = is_object($source) ? $source->filepath : $source; - - if (file_copy($source, $dest, $replace)) { - $path_current = is_object($source) ? $source->filepath : $source; - - if ($path_original == $path_current || file_delete($path_original)) { - return TRUE; +function file_move($source, $destination = NULL, $replace = FILE_EXISTS_RENAME) { + if ($result = file_move_plain($source->filepath, $destination, $replace)) { + $file = clone $source; + $file->filename = basename($result); + $file->filepath = $result; + if ($file = file_save($file)) { + module_invoke_all('file_move', $file, $source); + return $file; } - drupal_set_message(t('The removal of the original file %file has failed.', array('%file' => $path_original)), 'error'); + drupal_set_message(t('The removal of the original file %file has failed.', array('%file' => $source->filepath)), 'error'); } return FALSE; } /** + * Move a file to a new location. + * + * @param $source + * A string specifying the file location of the original file. + * @param $destination + * A string containing the directory $source should be copied to. If this + * value is omitted, Drupal's 'files' directory will be used. + * @param $replace + * Replace behavior when the destination file already exists: + * - FILE_EXISTS_REPLACE - Replace the existing file. + * - FILE_EXISTS_RENAME - Append _{incrementing number} until the filename is + * unique. + * - FILE_EXISTS_ERROR - Do nothing and return FALSE. + * @return + * The filepath of the moved file, or FALSE in the event of an error. + * + * @see file_move() + */ +function file_move_plain($source, $destination = NULL, $replace = FILE_EXISTS_RENAME) { + // TODO use PHP's rename rather than copy delete + $result = file_copy_plain($source, $destination, $replace); + if ($result == FALSE || !file_delete_plain($source)) { + return FALSE; + } + return $result; +} + +/** * Munge the filename as needed for security purposes. For instance the file * name "exploit.php.pps" would become "exploit.php_.pps". * @@ -438,9 +523,9 @@ function file_unmunge_filename($filename * @return */ function file_create_filename($basename, $directory) { - $dest = $directory . '/' . $basename; + $destination = $directory . '/' . $basename; - if (file_exists($dest)) { + if (file_exists($destination)) { // Destination file already exists, generate an alternative. if ($pos = strrpos($basename, '.')) { $name = substr($basename, 0, $pos); @@ -452,45 +537,106 @@ function file_create_filename($basename, $counter = 0; do { - $dest = $directory . '/' . $name . '_' . $counter++ . $ext; - } while (file_exists($dest)); + $destination = $directory . '/' . $name . '_' . $counter++ . $ext; + } while (file_exists($destination)); } - return $dest; + return $destination; +} + +/** + * Delete a file and its database record. + * + * @param $path + * A file object. + * @param $force + * Boolean indicating that the file should be deleted even if + * hook_file_references() reports that the file is in use. + * @return mixed + * TRUE for success, Array for reference count block, or FALSE in the event + * of an error. + * + * @see hook_file_references() + * @see file_delete_plain() + */ +function file_delete($file, $force = FALSE) { + // If any module returns a value from the reference hook, the + // file will not be deleted from Drupal, but file_delete will + // return a populated array that tests as TRUE. + if (!$force && ($references = module_invoke_all('file_references', $file))) { + return $references; + } + + // Let other modules clean up on delete. + module_invoke_all('file_delete', $file); + + // Make sure the file is deleted before removing its row from the + // database, so UIs can still find the file in the database. + if (file_delete_plain($file->filepath)) { + db_query('DELETE FROM {files} WHERE fid = %d', $file->fid); + return TRUE; + } + return FALSE; } /** * Delete a file. * - * @param $path A string containing a file path. - * @return TRUE for success, FALSE for failure. + * This function should be used when the file to be deleted does not have an + * entry recorded in the files table. + * + * @param $path + * A string containing a file path. + * @return + * TRUE for success or path does not exist, or FALSE in the event of an + * error. + * + * @see file_delete() */ -function file_delete($path) { +function file_delete_plain($path) { + if (is_dir($path)) { + watchdog('file', t('%path is a directory and cannot be removed with file_delete_plain.', array('%path' => $path)), WATCHDOG_ERROR); + return FALSE; + } if (is_file($path)) { return unlink($path); } + // Return TRUE for non-existant file, but log that nothing was actually + // deleted, as the intended result of file_delete_plain is in fact the + // current state. + if (!file_exists($path)) { + watchdog('file', t('The file %path was not deleted, because it does not exist.', array('%path' => $path)), WATCHDOG_NOTICE); + return TRUE; + } + // Catch all for everything else: sockets, symbolic links, etc. + return FALSE; } /** * Determine total disk space used by a single user or the whole filesystem. * * @param $uid - * An optional user id. A NULL value returns the total space used - * by all files. + * Optional. A user id, specifying NULL returns the total space used by all + * non-temporary files. + * @param $status + * Optional. File Status to return. Combine with a bitwise OR(|) to return + * multiple statuses. The default status is FILE_STATUS_PERMANENT. + * @return + * An integer containing the number of bytes used. */ -function file_space_used($uid = NULL) { +function file_space_used($uid = NULL, $status = FILE_STATUS_PERMANENT) { if (isset($uid)) { - return (int) db_result(db_query('SELECT SUM(filesize) FROM {files} WHERE uid = %d', $uid)); + return (int)db_result(db_query('SELECT SUM(filesize) FROM {files} WHERE uid = %d AND status & %d', $uid, $status)); } - return (int) db_result(db_query('SELECT SUM(filesize) FROM {files}')); + return (int)db_result(db_query('SELECT SUM(filesize) FROM {files} WHERE status & %d', $status)); } /** * Saves a file upload to a new location. The source file is validated as a * proper upload and handled as such. * - * The file will be added to the files table as a temporary file. Temporary files - * are periodically cleaned. To make the file permanent file call + * The file will be added to the files table as a temporary file. Temporary + * files are periodically cleaned. To make the file permanent file call * file_set_status() to change its status. * * @param $source @@ -502,7 +648,7 @@ function file_space_used($uid = NULL) { * functions should return an array of error messages, an empty array * indicates that the file passed validation. The functions will be called in * the order specified. - * @param $dest + * @param $destination * A string containing the directory $source should be copied to. If this is * not provided or is not writable, the temporary directory will be used. * @param $replace @@ -510,25 +656,27 @@ function file_space_used($uid = NULL) { * destination directory should overwritten. A false value will generate a * new, unique filename in the destination directory. * @return - * An object containing the file information, or FALSE in the event of an error. + * An object containing the file information, or FALSE in the event of an + * error. */ -function file_save_upload($source, $validators = array(), $dest = FALSE, $replace = FILE_EXISTS_RENAME) { +function file_save_upload($source, $validators = array(), $destination = FALSE, $replace = FILE_EXISTS_RENAME) { global $user; static $upload_cache; - // Add in our check of the the file name length. - $validators['file_validate_name_length'] = array(); - // Return cached objects without processing since the file will have // already been processed and the paths in _FILES will be invalid. if (isset($upload_cache[$source])) { return $upload_cache[$source]; } + // Add in our check of the the file name length. + $validators['file_validate_name_length'] = array(); + + // If a file was uploaded, process it. if (isset($_FILES['files']) && $_FILES['files']['name'][$source] && is_uploaded_file($_FILES['files']['tmp_name'][$source])) { - // Check for file upload errors and return FALSE if a - // lower level system error occurred. + // Check for file upload errors and return FALSE if a lower level system + // error occurred. switch ($_FILES['files']['error'][$source]) { // @see http://php.net/manual/en/features.file-upload.errors.php case UPLOAD_ERR_OK: @@ -560,9 +708,12 @@ function file_save_upload($source, $vali // Begin building file object. $file = new stdClass(); + $file->uid = $user->uid; + $file->status = FILE_STATUS_TEMPORARY; $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); + $file->filesize = $_FILES['files']['size'][$source]; // Rename potentially executable files, to help prevent exploits. if (preg_match('/\.(php|pl|py|cgi|asp|js)$/i', $file->filename) && (substr($file->filename, -4) != '.txt')) { @@ -573,26 +724,21 @@ function file_save_upload($source, $vali // If the destination is not provided, or is not writable, then use the // temporary directory. - if (empty($dest) || file_check_path($dest) === FALSE) { - $dest = file_directory_temp(); + if (empty($destination) || file_check_path($destination) === FALSE) { + $destination = file_directory_temp(); } $file->source = $source; - $file->destination = file_destination(file_create_path($dest . '/' . $file->filename), $replace); - $file->filesize = $_FILES['files']['size'][$source]; + $file->destination = file_destination(file_create_path($destination . '/' . $file->filename), $replace); - // Call the validation functions. - $errors = array(); - foreach ($validators as $function => $args) { - array_unshift($args, $file); - $errors = array_merge($errors, call_user_func_array($function, $args)); - } + // Call the validation functions specified by this function's caller. + $errors = file_validate($file, $validators); - // Check for validation errors. + // Check for errors. if (!empty($errors)) { - $message = t('The selected file %name could not be uploaded.', array('%name' => $file->filename)); + $message = t('The specified file %name could not be uploaded.', array('%name' => $file->filename)); if (count($errors) > 1) { - $message .= '