diff --git a/admin/actions.php b/admin/actions.php index 532d7c35..e8f191e3 100755 --- a/admin/actions.php +++ b/admin/actions.php @@ -57,6 +57,52 @@ function request_delete_schedule() { } add_action( 'admin_post_hmbkp_request_delete_schedule', 'HM\BackUpWordPress\request_delete_schedule' ); +add_action( 'admin_post_hmbkp_request_credentials', function() { + + global $wp_filesystem; + + ob_start(); + $creds = request_filesystem_credentials( '' ); + ob_end_clean(); + + // Default to showing an error if we're not able to connect. + $url = add_query_arg( 'connection_error', 1, get_settings_url() ); + + /** + * If we have valid filesystem credentials then let's attempt + * to use them to create the backups directory. If we can't create it in + * WP_CONTENT_DIR then we fallback to trying in uploads. + */ + if ( WP_Filesystem( $creds ) ) { + + // If we're able to connect then no need to redirect with an error. + $url = get_settings_url(); + + // If the backup path exists then let's just try to chmod it to the correct permissions. + if ( + is_dir( Path::get_instance()->get_default_path() ) && + ! $wp_filesystem->chmod( Path::get_instance()->get_default_path(), FS_CHMOD_DIR ) + ) { + $url = add_query_arg( 'creation_error', 1, get_settings_url() ); + } else { + + // If the path doesn't exist then try to correct the permission for the parent directory and create it. + $wp_filesystem->chmod( dirname( Path::get_instance()->get_default_path() ), FS_CHMOD_DIR ); + + if ( + ! $wp_filesystem->mkdir( Path::get_instance()->get_default_path(), FS_CHMOD_DIR ) && + ! $wp_filesystem->mkdir( Path::get_instance()->get_fallback_path(), FS_CHMOD_DIR ) + ) { + $url = add_query_arg( 'creation_error', 1, get_settings_url() ); + } + } + } + + wp_safe_redirect( $url , 303 ); + die; + +} ); + /** * Perform a manual backup * diff --git a/admin/filesystem-credentials.php b/admin/filesystem-credentials.php new file mode 100644 index 00000000..ea570305 --- /dev/null +++ b/admin/filesystem-credentials.php @@ -0,0 +1,8 @@ + - + -
', '' ); ?>
+ - +', '' ); ?>
+ + + + + + + + diff --git a/classes/class-path.php b/classes/class-path.php index 47bfc5f9..4d94b8e6 100644 --- a/classes/class-path.php +++ b/classes/class-path.php @@ -275,6 +275,29 @@ public function get_existing_path() { */ public function calculate_path() { + $paths = $this->get_possible_paths(); + + // Loop through possible paths, use the first one that exists/can be created and is writable. + foreach ( $paths as $path ) { + // Also handles fixing perms / directory already exists. + if ( wp_mkdir_p( $path ) && wp_is_writable( $path ) ) { + break; + } + } + + /** + * If we managed to create a writable path then use that, + * otherwise just return the unwritable path. + */ + if ( file_exists( $path ) && wp_is_writable( $path ) ) { + $this->path = $path; + } else { + $this->path = reset( $paths ); + } + } + + public function get_possible_paths() { + $paths = array(); // If we have a custom path then try to use it. @@ -293,13 +316,7 @@ public function calculate_path() { // If that didn't work then fallback to a new directory in uploads. $paths[] = $this->get_fallback_path(); - // Loop through possible paths, use the first one that exists/can be created and is writable. - foreach ( $paths as $path ) { - if ( wp_mkdir_p( $path ) && file_exists( $path ) && wp_is_writable( $path ) ) { // Also handles fixing perms / directory already exists. - $this->path = $path; - break; - } - } + return $paths; } /** @@ -410,7 +427,6 @@ public function move_old_backups( $from ) { if ( false !== strpos( $from, WP_CONTENT_DIR ) && Path::get_path() !== $from ) { rmdirtree( $from ); } - } /** diff --git a/classes/class-requirement.php b/classes/class-requirement.php index a7959ab2..c9b47bca 100644 --- a/classes/class-requirement.php +++ b/classes/class-requirement.php @@ -281,7 +281,10 @@ class Requirement_Backup_Path_Permissions extends Requirement { * @return string */ public static function test() { - return substr( sprintf( '%o', fileperms( Path::get_path() ) ), - 4 ); + if ( is_readable( PATH::get_path() ) ) { + return substr( sprintf( '%o', fileperms( Path::get_path() ) ), - 4 ); + } + return 'Unreadable'; } } Requirements::register( 'HM\BackUpWordPress\Requirement_Backup_Path_Permissions', 'Site' ); diff --git a/classes/class-site-size.php b/classes/class-site-size.php index f34b6e53..94b8d89d 100644 --- a/classes/class-site-size.php +++ b/classes/class-site-size.php @@ -8,7 +8,7 @@ /** * Site Size class * - * Use to calculate the total or partial size of the sites database and files. + * Use to calculate the total or partial size of the site's database and files. */ class Site_Size { diff --git a/functions/core.php b/functions/core.php index 8201614f..ab94bdf7 100755 --- a/functions/core.php +++ b/functions/core.php @@ -393,17 +393,17 @@ function rmdirtree( $dir ) { @rmdir( $dir ); return true; + } /** - * Check if a backup is possible with regards to file - * permissions etc. + * Check if we have read and write permission on the server * * @return bool */ -function is_backup_possible() { +function has_server_permissions() { - if ( ! wp_is_writable( Path::get_path() ) || ! is_dir( Path::get_path() ) ) { + if ( ! wp_is_writable( Path::get_path() ) ) { return false; } @@ -411,6 +411,21 @@ function is_backup_possible() { return false; } + return true; +} + +/** + * Check if a backup is possible with regards to file + * permissions etc. + * + * @return bool + */ +function is_backup_possible() { + + if ( ! has_server_permissions() || ! is_dir( Path::get_path() ) ) { + return false; + } + if ( ! Requirement_Mysqldump_Command_Path::test() && ! Requirement_PDO::test() ) { return false; } diff --git a/functions/interface.php b/functions/interface.php index 57b512bf..3b69425a 100644 --- a/functions/interface.php +++ b/functions/interface.php @@ -33,7 +33,19 @@ function get_backup_row( $file, Scheduled_Backup $schedule ) { | - + + + @@ -42,8 +54,7 @@ function get_backup_row( $file, Scheduled_Backup $schedule ) { -' . esc_html( dirname( Path::get_path() ) ) . '
' );
- }
-
- if ( is_dir( Path::get_path() ) && ! wp_is_writable( Path::get_path() ) ) {
- $messages[] = __( 'The backups directory isn\'t writable. Please fix the permissions.', 'backupwordpress' );
- }
-
if ( Backup_Utilities::is_safe_mode_on() ) {
- $messages[] = sprintf( __( '%1$s is running in %2$s, please contact your host and ask them to disable it. BackUpWordPress may not work correctly whilst %3$s is on.', 'backupwordpress' ), 'PHP
', sprintf( '%2$s', __( 'http://php.net/manual/en/features.safe-mode.php', 'backupwordpress' ), __( 'Safe Mode', 'backupwordpress' ) ), '' . __( 'Safe Mode', 'backupwordpress' ) . '
' );
+
+ $messages[] = sprintf(
+ /* translators: 1: The `PHP` abbreviation. */
+ __( '%1$s is running in Safe Mode, please contact your host and ask them to disable it. BackUpWordPress may not work correctly whilst Safe Mode
is on.', 'backupwordpress' ),
+ 'PHP
'
+ );
}
if ( defined( 'HMBKP_PATH' ) && HMBKP_PATH ) {
// Suppress open_basedir warning https://bugs.php.net/bug.php?id=53041
if ( ! path_in_php_open_basedir( HMBKP_PATH ) ) {
- $messages[] = sprintf( __( 'Your server has an %1$s restriction in effect and your custom backups directory (%2$s) is not within the allowed path(s): (%3$s).', 'backupwordpress' ), 'open_basedir
', '' . esc_html( HMBKP_PATH ) . '
', '' . esc_html( @ini_get( 'open_basedir' ) ) . '
' );
- } elseif ( ! file_exists( HMBKP_PATH ) ) {
- $messages[] = sprintf( __( 'Your custom path does not exist', 'backupwordpress' ) );
+ $messages[] = sprintf(
+ __( 'Your server has an %1$s restriction in effect and your custom backups directory (%2$s) is not within the allowed path(s): (%3$s).', 'backupwordpress' ),
+ 'open_basedir
',
+ '' . esc_html( HMBKP_PATH ) . '
',
+ '' . esc_html( @ini_get( 'open_basedir' ) ) . '
'
+ );
- } else {
+ } elseif ( ! is_dir( HMBKP_PATH ) ) {
- if ( ! is_dir( HMBKP_PATH ) ) {
- $messages[] = sprintf( __( 'Your custom backups directory %1$s doesn\'t exist and can\'t be created, your backups will be saved to %2$s instead.', 'backupwordpress' ), '' . esc_html( HMBKP_PATH ) . '
', '' . esc_html( Path::get_path() ) . '
' );
- }
+ $messages[] = sprintf(
+ __( 'Your custom backups directory (%1$s) doesn't exist, your backups will be saved to %2$s instead.', 'backupwordpress' ),
+ '' . esc_html( HMBKP_PATH ) . '
',
+ '' . esc_html( Path::get_path() ) . '
'
+ );
- if ( is_dir( HMBKP_PATH ) && ! wp_is_writable( HMBKP_PATH ) ) {
- $messages[] = sprintf( __( 'Your custom backups directory %1$s isn\'t writable, new backups will be saved to %2$s instead.', 'backupwordpress' ), '' . esc_html( HMBKP_PATH ) . '
', '' . esc_html( Path::get_path() ) . '
' );
+ } elseif ( is_dir( HMBKP_PATH ) && ! wp_is_writable( HMBKP_PATH ) ) {
- }
+ $messages[] = sprintf(
+ __( 'Your custom backups directory (%1$s) isn't writable, new backups will be saved to %2$s instead.', 'backupwordpress' ),
+ '' . esc_html( HMBKP_PATH ) . '
',
+ '' . esc_html( Path::get_path() ) . '
'
+ );
+ }
+ }
+
+ if ( ! is_dir( Path::get_path() ) || is_dir( Path::get_path() ) && ! wp_is_writable( Path::get_path() ) ) {
+
+ if ( isset( $_GET['creation_error'] ) ) {
+
+ $messages[] = sprintf(
+ /* translators: 1: URL to BackupWordPress docs. */
+ __( 'We connected to your server successfully but still weren't able to automatically create the directory. You'll need to manually specify a valid directory', 'backupwordpress' ),
+ 'https://bwp.hmn.md/support-center/backupwordpress-faqs/#where'
+ );
+
+ } else {
+
+ $messages[] = sprintf(
+ /* translators: 1: Path to backup directory. 2: URL to BackupWordPress docs. */
+ __( 'We couldn't create the backups directory (%1$s). You'll need to manually specify a valid directory or you can have WordPress do it automatically by entering your server details below. This is a one time thing.', 'backupwordpress' ),
+ '' . esc_html( Path::get_path() ) . '
',
+ 'https://bwp.hmn.md/support-center/backupwordpress-faqs/#where'
+ );
}
}
if ( ! is_readable( Path::get_root() ) ) {
- $messages[] = sprintf( __( 'Your site root path %s isn\'t readable.', 'backupwordpress' ), '' . Path::get_root() . '
' );
+
+ $messages[] = sprintf(
+ __( 'Your site's root path (%s) isn't readable. Please contact support.', 'backupwordpress' ),
+ '' . Path::get_root() . '
'
+ );
}
if ( ! Requirement_Mysqldump_Command_Path::test() && ! Requirement_PDO::test() ) {
- $messages[] = sprintf( __( 'Your site cannot be backed up because your server doesn\'t support %1$s or %2$s. Please contact your host and ask them to enable them.', 'backupwordpress' ), 'mysqldump
', 'PDO::mysql
' );
+
+ $messages[] = sprintf(
+ /* translators: FYI: specified MySQL features. */
+ __( 'Your site cannot be backed up because your server doesn't support %1$s or %2$s. Please contact your host and ask them to enable them.', 'backupwordpress' ),
+ 'mysqldump
',
+ 'PDO::mysql
'
+ );
}
if ( ! Requirement_Zip_Command_Path::test() && ! Requirement_Zip_Archive::test() ) {
- $messages[] = sprintf( __( 'Your site cannot be backed up because your server doesn\'t support %1$s or %2$s. Please contact your host and ask them to enable them.', 'backupwordpress' ), 'zip
', 'ZipArchive
' );
+
+ $messages[] = sprintf(
+ /* translators: FYI: specified zip archiving features. */
+ __( 'Your site cannot be backed up because your server doesn't support %1$s or %2$s. Please contact your host and ask them to enable them.', 'backupwordpress' ),
+ 'zip
',
+ 'ZipArchive
'
+ );
}
if ( disk_space_low() ) {
- $messages[] = sprintf( __( 'Your server only has %s of disk space left which probably isn\'t enough to complete a backup. Try deleting some existing backups or other files to free up space.', 'backupwordpress' ), '' . size_format( disk_free_space( Path::get_path() ) ) . '
' );
+
+ $messages[] = sprintf(
+ __( 'Your server only has %s of disk space left which probably isn't enough to complete a backup. Try deleting some existing backups or other files to free up space.', 'backupwordpress' ),
+ '' . size_format( disk_free_space( Path::get_path() ) ) . '
'
+ );
}
if ( count( $messages ) > 0 ) {
$notices->set_notices( 'server_config', $messages, false );
}
-
}
+
add_action( 'admin_init', 'HM\BackUpWordPress\set_server_config_notices' );
/**
@@ -217,7 +276,6 @@ function plugin_row( $plugins ) {
return $plugins;
}
-
add_filter( 'all_plugins', 'HM\BackUpWordPress\plugin_row', 10 );
/**
@@ -460,6 +518,11 @@ function disk_space_low( $backup_size = false ) {
}
- return $backup_size >= $disk_space;
+ if ( ! is_readable( Path::get_path() ) ) {
+ return false;
+ }
+
+ $disk_space = disk_free_space( Path::get_path() );
+ return $disk_space && $backup_size >= $disk_space;
}
diff --git a/readme.txt b/readme.txt
index 96aaf187..4b71bbb2 100644
--- a/readme.txt
+++ b/readme.txt
@@ -985,7 +985,7 @@ users should see major improvements to reliability.
#### 2.0.6
-* Fix possible warning on plugin activation if the sites cron option is empty.
+* Fix possible warning on plugin activation if the site's cron option is empty.
* Don't show the version warning in the help for Constants as that comes from the current version.
#### 2.0.5
diff --git a/tests/class-backup-engine/test-class-backup-engine-file-zip-archive.php b/tests/class-backup-engine/test-class-backup-engine-file-zip-archive.php
index 3da6dae9..f7c71098 100644
--- a/tests/class-backup-engine/test-class-backup-engine-file-zip-archive.php
+++ b/tests/class-backup-engine/test-class-backup-engine-file-zip-archive.php
@@ -12,4 +12,4 @@ public function setUp() {
}
-}
\ No newline at end of file
+}