diff --git a/core/includes/file.inc b/core/includes/file.inc index 534d211..f362961 100644 --- a/core/includes/file.inc +++ b/core/includes/file.inc @@ -507,7 +507,7 @@ function file_prepare_directory(&$directory, $options = FILE_MODIFY_PERMISSIONS) return FALSE; } // The directory exists, so check to see if it is writable. - $writable = is_writable($directory); + $writable = file_directory_is_writable($directory); if (!$writable && ($options & FILE_MODIFY_PERMISSIONS)) { return drupal_chmod($directory); } @@ -1919,7 +1919,7 @@ function file_directory_os_temp() { $directories[] = sys_get_temp_dir(); foreach ($directories as $directory) { - if (is_dir($directory) && is_writable($directory)) { + if (is_dir($directory) && file_directory_is_writable($directory)) { return $directory; } } @@ -1927,5 +1927,45 @@ function file_directory_os_temp() { } /** + * Determines if a directory is writable by the web server. + * + * In order to be able to write files within the directory, the directory + * itself must be writable, and it must also have the executable bit set. This + * helper function checks both at the same time. + * + * @param $uri + * A URI or pathname pointing to the directory that will be checked. + * + * @return + * TRUE if the directory is writable and executable; FALSE otherwise. + */ +function file_directory_is_writable($uri) { + // By converting the URI to a normal path using drupal_realpath(), we can + // correctly handle both stream wrappers and normal paths. + return is_writable(drupal_realpath($uri)) && drupal_is_executable($uri); +} + +/** + * Determines if a file or directory is executable. + * + * PHP's is_executable() does not fully support stream wrappers, so this + * function fills that gap. + * + * @param $uri + * A URI or pathname pointing to the file or directory that will be checked. + * + * @return + * TRUE if the file or directory is executable; FALSE otherwise. + * + * @see is_executable() + * @ingroup php_wrappers + */ +function drupal_is_executable($uri) { + // By converting the URI to a normal path using drupal_realpath(), we can + // correctly handle both stream wrappers and normal paths. + return is_executable(drupal_realpath($uri)); +} + +/** * @} End of "defgroup file". */ diff --git a/core/includes/install.core.inc b/core/includes/install.core.inc index c4de9ee..f609ce5 100644 --- a/core/includes/install.core.inc +++ b/core/includes/install.core.inc @@ -1910,7 +1910,7 @@ function install_check_translations($install_state) { // Get values so the requirements errors can be specific. if (drupal_verify_install_file($translations_directory, FILE_EXIST|FILE_WRITABLE, 'dir')) { $readable = is_readable($translations_directory); - $writable = is_writable($translations_directory); + $writable = file_directory_is_writable($translations_directory); $translations_directory_exists = TRUE; } @@ -2074,7 +2074,7 @@ function install_check_requirements($install_state) { // Otherwise, if settings.php does not exist yet, we can try to copy // default.settings.php to create it. elseif (!$exists) { - $copied = drupal_verify_install_file($conf_path, FILE_EXIST|FILE_WRITABLE, 'dir') && @copy($default_settings_file, $settings_file); + $copied = drupal_verify_install_file($conf_path, FILE_EXIST|FILE_WRITABLE|FILE_EXECUTABLE, 'dir') && @copy($default_settings_file, $settings_file); if ($copied) { // If the new settings file has the same owner as default.settings.php, // this means default.settings.php is owned by the webserver user. diff --git a/core/includes/install.inc b/core/includes/install.inc index d33bb0a..c74e99f 100644 --- a/core/includes/install.inc +++ b/core/includes/install.inc @@ -316,7 +316,7 @@ function install_verify_config_directory($type) { // prepared settings.php that defines $config_directories already. try { $config_directory = config_get_config_directory($type); - if (is_dir($config_directory) && is_writable($config_directory)) { + if (is_dir($config_directory) && file_directory_is_writable($config_directory)) { return TRUE; } } @@ -493,7 +493,7 @@ function drupal_verify_install_file($file, $mask = NULL, $type = 'file') { } break; case FILE_EXECUTABLE: - if (!is_executable($file) && !drupal_install_fix_file($file, $mask)) { + if (!drupal_is_executable($file) && !drupal_install_fix_file($file, $mask)) { $return = FALSE; } break; @@ -508,7 +508,7 @@ function drupal_verify_install_file($file, $mask = NULL, $type = 'file') { } break; case FILE_NOT_EXECUTABLE: - if (is_executable($file) && !drupal_install_fix_file($file, $mask)) { + if (drupal_is_executable($file) && !drupal_install_fix_file($file, $mask)) { $return = FALSE; } break; @@ -608,7 +608,7 @@ function drupal_install_fix_file($file, $mask, $message = TRUE) { } break; case FILE_EXECUTABLE: - if (!is_executable($file)) { + if (!drupal_is_executable($file)) { $mod |= 0111; } break; @@ -623,7 +623,7 @@ function drupal_install_fix_file($file, $mask, $message = TRUE) { } break; case FILE_NOT_EXECUTABLE: - if (is_executable($file)) { + if (drupal_is_executable($file)) { $mod &= ~0111; } break; diff --git a/core/modules/system/system.admin.inc b/core/modules/system/system.admin.inc index b483e7e..d984701 100644 --- a/core/modules/system/system.admin.inc +++ b/core/modules/system/system.admin.inc @@ -1662,7 +1662,7 @@ function system_performance_settings($form, &$form_state) { ); $directory = 'public://'; - $is_writable = is_dir($directory) && is_writable($directory); + $is_writable = is_dir($directory) && file_directory_is_writable($directory); $disabled = !$is_writable; $disabled_message = ''; if (!$is_writable) { diff --git a/core/modules/system/system.install b/core/modules/system/system.install index 7f621d4..be81f1c 100644 --- a/core/modules/system/system.install +++ b/core/modules/system/system.install @@ -370,7 +370,7 @@ function system_requirements($phase) { if ($phase == 'install') { file_prepare_directory($directory, FILE_CREATE_DIRECTORY | FILE_MODIFY_PERMISSIONS); } - $is_writable = is_writable($directory); + $is_writable = file_directory_is_writable($directory); $is_directory = is_dir($directory); if (!$is_writable || !$is_directory) { $description = ''; diff --git a/core/modules/system/system.module b/core/modules/system/system.module index 1a659c5..8229366 100644 --- a/core/modules/system/system.module +++ b/core/modules/system/system.module @@ -2726,7 +2726,7 @@ function system_check_directory($form_element) { watchdog('file system', 'The directory %directory does not exist and could not be created.', array('%directory' => $directory), WATCHDOG_ERROR); } - if (is_dir($directory) && !is_writable($directory) && !drupal_chmod($directory)) { + if (is_dir($directory) && !file_directory_is_writable($directory) && !drupal_chmod($directory)) { // If the directory is not writable and cannot be made so. form_set_error($form_element['#parents'][0], t('The directory %directory exists but is not writable and could not be made writable.', array('%directory' => $directory))); watchdog('file system', 'The directory %directory exists but is not writable and could not be made writable.', array('%directory' => $directory), WATCHDOG_ERROR);