diff --git a/phpBB/docs/CHANGELOG.html b/phpBB/docs/CHANGELOG.html
index 3cd2116ddb..93c47b0477 100644
--- a/phpBB/docs/CHANGELOG.html
+++ b/phpBB/docs/CHANGELOG.html
@@ -88,6 +88,7 @@
1.i. Changes since 3.0.5
+ - [Fix] Correctly determine writable status of files on Windows operating system. (Bug #39035)
- [Feature] Backported 3.2 cpatcha plugins.
- [Feature] Introduced new ACM plugins: null
diff --git a/phpBB/includes/acp/acp_main.php b/phpBB/includes/acp/acp_main.php
index 8a92c06e04..365290e909 100644
--- a/phpBB/includes/acp/acp_main.php
+++ b/phpBB/includes/acp/acp_main.php
@@ -504,7 +504,7 @@ class acp_main
$template->assign_var('S_REMOVE_INSTALL', true);
}
- if (!defined('PHPBB_DISABLE_CONFIG_CHECK') && file_exists($phpbb_root_path . 'config.' . $phpEx) && is_writable($phpbb_root_path . 'config.' . $phpEx))
+ if (!defined('PHPBB_DISABLE_CONFIG_CHECK') && file_exists($phpbb_root_path . 'config.' . $phpEx) && phpbb_is_writable($phpbb_root_path . 'config.' . $phpEx))
{
// World-Writable? (000x)
$template->assign_var('S_WRITABLE_CONFIG', (bool) (@fileperms($phpbb_root_path . 'config.' . $phpEx) & 0x0002));
diff --git a/phpBB/includes/functions.php b/phpBB/includes/functions.php
index 58601be65b..78905beff6 100644
--- a/phpBB/includes/functions.php
+++ b/phpBB/includes/functions.php
@@ -669,6 +669,67 @@ function phpbb_chmod($filename, $perms = CHMOD_READ)
return $result;
}
+/**
+ * Test if a file/directory is writable
+ *
+ * This function calls the native is_writable() when not running under
+ * Windows and it is not disabled.
+ *
+ * @param string $file Path to perform write test on
+ * @return bool True when the path is writable, otherwise false.
+ */
+function phpbb_is_writable($file)
+{
+ if (substr(PHP_OS, 0, 3) === 'WIN' || !function_exists('is_writable'))
+ {
+ if (file_exists($file))
+ {
+ // Canonicalise path to absolute path
+ $file = phpbb_realpath($file);
+
+ if (is_dir($file))
+ {
+ // Test directory by creating a file inside the directory
+ $result = @tempnam($file, 'i_w');
+
+ if (is_string($result) && file_exists($result))
+ {
+ unlink($result);
+
+ // Ensure the file is actually in the directory (returned realpathed)
+ return (strpos($result, $file) === 0) ? true : false;
+ }
+ }
+ else
+ {
+ $handle = @fopen($file, 'r+');
+
+ if (is_resource($handle))
+ {
+ fclose($handle);
+ return true;
+ }
+ }
+ }
+ else
+ {
+ // file does not exist test if we can write to the directory
+
+ $dir = dirname($file);
+
+ if (file_exists($dir) && is_dir($dir) && phpbb_is_writable($dir))
+ {
+ return true;
+ }
+ }
+ return false;
+ }
+ else
+ {
+ return is_writable($file);
+ }
+}
+
// Compatibility functions
if (!function_exists('array_combine'))