'render_tab1', 'tab2' => 'render_tab2', ); function __construct() { $this->render_menu_page(); } function set_menu_tabs() { if (AIOWPSecurity_Utility::is_multisite_install() && get_current_blog_id() != 1){ //Suppress the DB prefix change tab if site is a multi site AND not the main site $this->menu_tabs = array( //'tab1' => __('DB Prefix', 'all-in-one-wp-security-and-firewall'), 'tab2' => __('DB Backup', 'all-in-one-wp-security-and-firewall'), ); }else{ $this->menu_tabs = array( 'tab1' => __('DB Prefix', 'all-in-one-wp-security-and-firewall'), 'tab2' => __('DB Backup', 'all-in-one-wp-security-and-firewall'), ); } } function get_current_tab() { $tab_keys = array_keys($this->menu_tabs); $tab = isset( $_GET['tab'] ) ? sanitize_text_field($_GET['tab']) : $tab_keys[0]; return $tab; } /* * Renders our tabs of this menu as nav items */ function render_menu_tabs() { $current_tab = $this->get_current_tab(); echo ''; } /* * The menu rendering goes here */ function render_menu_page() { echo '
'; echo '

'.__('Database Security','all-in-one-wp-security-and-firewall').'

';//Interface title $this->set_menu_tabs(); $tab = $this->get_current_tab(); $this->render_menu_tabs(); ?>
menu_tabs); call_user_func(array(&$this, $this->menu_tabs_handler[$tab])); ?>
prefix; $new_db_prefix = ''; $perform_db_change = false; if (isset($_POST['aiowps_db_prefix_change']))//Do form submission tasks { $nonce=$_REQUEST['_wpnonce']; if (!wp_verify_nonce($nonce, 'aiowpsec-db-prefix-change-nonce')) { $aio_wp_security->debug_logger->log_debug("Nonce check failed for DB prefix change operation!",4); die(__('Nonce check failed for DB prefix change operation!','all-in-one-wp-security-and-firewall')); } //Let's first check if user's system allows writing to wp-config.php file. If plugin cannot write to wp-config we will not do the prefix change. $config_file = AIOWPSecurity_Utility_File::get_wp_config_file_path(); $file_write = AIOWPSecurity_Utility_File::is_file_writable($config_file); if (!$file_write) { $this->show_msg_error(__('The plugin has detected that it cannot write to the wp-config.php file. This feature can only be used if the plugin can successfully write to the wp-config.php file.', 'all-in-one-wp-security-and-firewall')); } else { if( isset($_POST['aiowps_enable_random_prefix'])) {//User has elected to generate a random DB prefix $string = AIOWPSecurity_Utility::generate_alpha_random_string('5'); $new_db_prefix = $string . '_'; $perform_db_change = true; }else { if (empty($_POST['aiowps_new_manual_db_prefix'])) { $this->show_msg_error(__('Please enter a value for the DB prefix.', 'all-in-one-wp-security-and-firewall')); } else { //User has chosen their own DB prefix value $new_db_prefix = wp_strip_all_tags( trim( $_POST['aiowps_new_manual_db_prefix'] ) ); $error = $wpdb->set_prefix( $new_db_prefix ); //validate the user chosen prefix if(is_wp_error($error)) { wp_die( __('ERROR: The table prefix can only contain numbers, letters, and underscores.', 'all-in-one-wp-security-and-firewall') ); } $wpdb->set_prefix( $old_db_prefix ); $perform_db_change = true; } } } } ?>

'.__('Your WordPress DB is the most important asset of your website because it contains a lot of your site\'s precious information.', 'all-in-one-wp-security-and-firewall').'
'.__('The DB is also a target for hackers via methods such as SQL injections and malicious and automated code which targets certain tables.', 'all-in-one-wp-security-and-firewall').'
'.__('One way to add a layer of protection for your DB is to change the default WordPress table prefix from "wp_" to something else which will be difficult for hackers to guess.', 'all-in-one-wp-security-and-firewall').'
'.__('This feature allows you to easily change the prefix to a value of your choice or to a random value set by this plugin.', 'all-in-one-wp-security-and-firewall').'

'; ?>

output_feature_details_badge("db-security-db-prefix"); ?>
DB Backup'; $info_msg = '

'.sprintf( __('It is recommended that you perform a %s before using this feature', 'all-in-one-wp-security-and-firewall'), $backup_tab_link).'

'; echo $info_msg; ?>
: prefix; ?> '.__('Your site is currently using the default WordPress DB prefix value of "wp_". To increase your site\'s security you should consider changing the DB prefix value to another value.', 'all-in-one-wp-security-and-firewall').''; } ?>
: configs->get_value('aiowps_enable_random_prefix')=='1') echo ' checked="checked"'; ?> value="1"/>

change_db_prefix($old_db_prefix,$new_db_prefix); } } function render_tab2() { global $aio_wp_security; global $aiowps_feature_mgr; if (isset($_POST['aiowps_manual_db_backup'])) { $nonce=$_REQUEST['_wpnonce']; if (!wp_verify_nonce($nonce, 'aiowpsec-db-manual-change-nonce')) { $aio_wp_security->debug_logger->log_debug("Nonce check failed for manual DB backup operation!",4); die(__('Nonce check failed for manual DB backup operation!','all-in-one-wp-security-and-firewall')); } $result = $aio_wp_security->backup_obj->execute_backup(); if ($result) { $backup_file_name = $aio_wp_security->backup_obj->last_backup_file_name; if (function_exists('is_multisite') && is_multisite()) { $aiowps_backup_file_path = $aio_wp_security->backup_obj->last_backup_file_dir_multisite . '/' . $backup_file_name; } else { $aiowps_backup_dir = WP_CONTENT_DIR.'/'.AIO_WP_SECURITY_BACKUPS_DIR_NAME; $aiowps_backup_file_path = $aiowps_backup_dir. '/' . $backup_file_name; } echo '

'; _e('DB Backup was successfully completed! You will receive the backup file via email if you have enabled "Send Backup File Via Email", otherwise you can retrieve it via FTP from the following directory:','all-in-one-wp-security-and-firewall'); echo '

'; _e('Your DB Backup File location: '); echo ''.$aiowps_backup_file_path.''; echo '

'; } else { $aio_wp_security->debug_logger->log_debug("DB Backup - Backup operation failed!",4); $this->show_msg_error(__('DB Backup failed. Please check the permissions of the backup directory.','all-in-one-wp-security-and-firewall')); } } if(isset($_POST['aiowps_schedule_backups']))//Do form submission tasks { $error = ''; $nonce=$_REQUEST['_wpnonce']; if (!wp_verify_nonce($nonce, 'aiowpsec-scheduled-backup-nonce')) { $aio_wp_security->debug_logger->log_debug("Nonce check failed on scheduled DB backup options save!",4); die("Nonce check failed on scheduled DB backup options save!"); } $backup_frequency = sanitize_text_field($_POST['aiowps_db_backup_frequency']); if(!is_numeric($backup_frequency)) { $error .= '
'.__('You entered a non numeric value for the "backup time interval" field. It has been set to the default value.','all-in-one-wp-security-and-firewall'); $backup_frequency = '4';//Set it to the default value for this field } $files_to_keep = sanitize_text_field($_POST['aiowps_backup_files_stored']); if(!is_numeric($files_to_keep)) { $error .= '
'.__('You entered a non numeric value for the "number of backup files to keep" field. It has been set to the default value.','all-in-one-wp-security-and-firewall'); $files_to_keep = '2';//Set it to the default value for this field } $email_address = sanitize_email($_POST['aiowps_backup_email_address']); if(!is_email($email_address)) { $error .= '
'.__('You have entered an incorrect email address format. It has been set to your WordPress admin email as default.','all-in-one-wp-security-and-firewall'); $email_address = get_bloginfo('admin_email'); //Set the default value to the blog admin email } if($error) { $this->show_msg_error(__('Attention!','all-in-one-wp-security-and-firewall').$error); } //Save all the form values to the options $aio_wp_security->configs->set_value('aiowps_enable_automated_backups',isset($_POST["aiowps_enable_automated_backups"])?'1':''); $aio_wp_security->configs->set_value('aiowps_db_backup_frequency',absint($backup_frequency)); $aio_wp_security->configs->set_value('aiowps_db_backup_interval',$_POST["aiowps_db_backup_interval"]); $aio_wp_security->configs->set_value('aiowps_backup_files_stored',absint($files_to_keep)); $aio_wp_security->configs->set_value('aiowps_send_backup_email_address',isset($_POST["aiowps_send_backup_email_address"])?'1':''); $aio_wp_security->configs->set_value('aiowps_backup_email_address',$email_address); $aio_wp_security->configs->save_config(); //Recalculate points after the feature status/options have been altered $aiowps_feature_mgr->check_feature_status_and_recalculate_points(); $this->show_msg_settings_updated(); //Let's check if backup interval was set to less than 24 hours if (isset($_POST["aiowps_enable_automated_backups"]) && ($backup_frequency < 24) && $_POST["aiowps_db_backup_interval"]==0) { $alert_user_msg = 'ATTENTION: You have configured your backups to occur at least once daily. For most websites we recommended that you choose a less frequent backup schedule such as once every few days, once a week or once a month. Choosing a less frequent schedule will also help reduce your server load.'; $this->show_msg_updated_st(__($alert_user_msg, 'all-in-one-wp-security-and-firewall')); } } ?>

output_feature_details_badge("db-security-db-backup"); ?>
: configs->get_value('aiowps_enable_automated_backups')=='1') echo ' checked="checked"'; ?> value="1"/>
:
:
: configs->get_value('aiowps_send_backup_email_address')=='1') echo ' checked="checked"'; ?> value="1"/>
get_mysql_tables(DB_NAME); //Fix for deprecated php mysql_list_tables function //Count the number of tables if (is_array($result) && count($result) > 0){ $num_rows = count($result); }else{ echo '

'.__('Error - Could not get tables or no tables found!', 'all-in-one-wp-security-and-firewall').'

'; return; } $table_count = 0; $info_msg_string = '

'.__('Starting DB prefix change operations.....', 'all-in-one-wp-security-and-firewall').'

'; $info_msg_string .= '

'.sprintf( __('Your WordPress system has a total of %s tables and your new DB prefix will be: %s', 'all-in-one-wp-security-and-firewall'), ''.$num_rows.'', ''.$table_new_prefix.'').'

'; echo ($info_msg_string); //Do a back of the config file if(!AIOWPSecurity_Utility_File::backup_and_rename_wp_config($config_file)) { echo '

'.__('Failed to make a backup of the wp-config.php file. This operation will not go ahead.', 'all-in-one-wp-security-and-firewall').'

'; return; } else{ echo '

'.__('A backup copy of your wp-config.php file was created successfully!', 'all-in-one-wp-security-and-firewall').'

'; } //Get multisite blog_ids if applicable if (AIOWPSecurity_Utility::is_multisite_install()) { $blog_ids = AIOWPSecurity_Utility::get_blog_ids(); } //Rename all the table names foreach ($result as $db_table) { //Get table name with old prefix $table_old_name = $db_table; if ( strpos( $table_old_name, $table_old_prefix ) === 0 ) { //Get table name with new prefix $table_new_name = $table_new_prefix . substr( $table_old_name, $old_prefix_length ); //Write query to rename tables name $sql = "RENAME TABLE `".$table_old_name."` TO `".$table_new_name."`"; //$sql = "RENAME TABLE %s TO %s"; //Execute the query if ( false === $wpdb->query($sql) ) { $error = 1; echo '

'.sprintf( __('%s table name update failed', 'all-in-one-wp-security-and-firewall'), ''.$table_old_name.'').'

'; $aio_wp_security->debug_logger->log_debug("DB Security Feature - Unable to change prefix of table ".$table_old_name,4); } else { $table_count++; } } else { continue; } } if ( $error == 1 ) { echo '

'.sprintf( __('Please change the prefix manually for the above tables to: %s', 'all-in-one-wp-security-and-firewall'), ''.$table_new_prefix.'').'

'; } else { echo '

'.sprintf( __('%s tables had their prefix updated successfully!', 'all-in-one-wp-security-and-firewall'), ''.$table_count.'').'

'; } //Let's check for mysql tables of type "view" $this->alter_table_views($table_old_prefix, $table_new_prefix); //Get wp-config.php file contents and modify it with new info $config_contents = file($config_file); $prefix_match_string = '$table_prefix='; //this is our search string for the wp-config.php file foreach ($config_contents as $line_num => $line) { $no_ws_line = preg_replace( '/\s+/', '', $line ); //Strip white spaces if(strpos($no_ws_line, $prefix_match_string) !== FALSE){ $config_contents[$line_num] = str_replace($table_old_prefix, $table_new_prefix, $line); break; } } //Now let's modify the wp-config.php file if (AIOWPSecurity_Utility_File::write_content_to_file($config_file, $config_contents)) { echo '

'. __('wp-config.php file was updated successfully!', 'all-in-one-wp-security-and-firewall').'

'; }else { echo '

'.sprintf( __('The "wp-config.php" file was not able to be modified. Please modify this file manually using your favourite editor and search for variable "$table_prefix" and assign the following value to that variable: %s', 'all-in-one-wp-security-and-firewall'), ''.$table_new_prefix.'').'

'; $aio_wp_security->debug_logger->log_debug("DB Security Feature - Unable to modify wp-config.php",4); } //Now let's update the options table $update_option_table_query = $wpdb->prepare("UPDATE " . $table_new_prefix . "options SET option_name = '".$table_new_prefix ."user_roles' WHERE option_name = %s LIMIT 1", $table_old_prefix."user_roles"); if ( false === $wpdb->query($update_option_table_query) ) { echo '

'.sprintf( __('Update of table %s failed: unable to change %s to %s', 'all-in-one-wp-security-and-firewall'),$table_new_prefix.'options', $table_old_prefix.'user_roles', $table_new_prefix.'user_roles').'

'; $aio_wp_security->debug_logger->log_debug("DB Security Feature - Error when updating the options table",4);//Log the highly unlikely event of DB error } else { echo '

'.sprintf( __('The options table records which had references to the old DB prefix were updated successfully!', 'all-in-one-wp-security-and-firewall')).'

'; } //Now let's update the options tables for the multisite subsites if applicable if (AIOWPSecurity_Utility::is_multisite_install()) { if(!empty($blog_ids)){ foreach ($blog_ids as $blog_id) { if ($blog_id == 1){continue;} //skip main site $new_pref_and_site_id = $table_new_prefix.$blog_id.'_'; $old_pref_and_site_id = $table_old_prefix.$blog_id.'_'; $update_ms_option_table_query = $wpdb->prepare("UPDATE " . $new_pref_and_site_id . "options SET option_name = '".$new_pref_and_site_id."user_roles' WHERE option_name = %s LIMIT 1", $old_pref_and_site_id."user_roles"); if ( false === $wpdb->query($update_ms_option_table_query) ) { echo '

'.sprintf( __('Update of table %s failed: unable to change %s to %s', 'all-in-one-wp-security-and-firewall'),$new_pref_and_site_id.'options', $old_pref_and_site_id.'user_roles', $new_pref_and_site_id.'user_roles').'

'; $aio_wp_security->debug_logger->log_debug("DB change prefix feature - Error when updating the subsite options table: ".$new_pref_and_site_id.'options',4);//Log the highly unlikely event of DB error } else { echo '

'.sprintf( __('The %s table records which had references to the old DB prefix were updated successfully!', 'all-in-one-wp-security-and-firewall'),$new_pref_and_site_id.'options').'

'; } } } } //Now let's update the user meta table $custom_sql = "SELECT user_id, meta_key FROM " . $table_new_prefix . "usermeta WHERE meta_key LIKE '" . $table_old_prefix . "%'"; $meta_keys = $wpdb->get_results( $custom_sql ); $error_update_usermeta = ''; //Update all meta_key field values which have the old table prefix in user_meta table foreach ($meta_keys as $meta_key ) { //Create new meta key $new_meta_key = $table_new_prefix . substr( $meta_key->meta_key, $old_prefix_length ); $update_user_meta_sql = $wpdb->prepare("UPDATE " . $table_new_prefix . "usermeta SET meta_key='" . $new_meta_key . "' WHERE meta_key=%s AND user_id=%s", $meta_key->meta_key, $meta_key->user_id); if (false === $wpdb->query($update_user_meta_sql)) { $error_update_usermeta .= '

'.sprintf( __('Error updating user_meta table where new meta_key = %s, old meta_key = %s and user_id = %s.', 'all-in-one-wp-security-and-firewall'),$new_meta_key,$meta_key->meta_key,$meta_key->user_id).'

'; echo $error_update_usermeta; $aio_wp_security->debug_logger->log_debug("DB Security Feature - Error updating user_meta table where new meta_key = ".$new_meta_key." old meta_key = ".$meta_key->meta_key." and user_id = ".$meta_key->user_id,4);//Log the highly unlikely event of DB error } } echo '

'.__('The usermeta table records which had references to the old DB prefix were updated successfully!', 'all-in-one-wp-security-and-firewall').'

'; //Display tasks finished message $tasks_finished_msg_string = '

'. __('DB prefix change tasks have been completed.', 'all-in-one-wp-security-and-firewall').'

'; echo ($tasks_finished_msg_string); } /** * This is an alternative to the deprecated "mysql_list_tables" * Returns an array of table names */ function get_mysql_tables($database='') { global $aio_wp_security; $tables = array(); $list_tables_sql = "SHOW TABLES FROM `{$database}`;"; $mysqli = new mysqli(DB_HOST, DB_USER, DB_PASSWORD, DB_NAME); if ($mysqli->connect_errno) { $aio_wp_security->debug_logger->log_debug("AIOWPSecurity_Database_Menu->get_mysql_tables() - DB connection error.",4); return false; } if ($result = $mysqli->query($list_tables_sql, MYSQLI_USE_RESULT)) { //Alternative way to get the tables while ($row = $result->fetch_assoc()) { foreach( $row AS $value ) { $tables[] = $value; } } $result->close(); } $mysqli->close(); return $tables; } /** * Will modify existing table view definitions to reflect the new DB prefix change * * @param type $old_prefix * @param type $new_prefix */ function alter_table_views($old_db_prefix, $new_db_prefix) { global $wpdb; $table_count = 0; $info_msg_string = '

'.__('Checking for MySQL tables of type "view".....', 'all-in-one-wp-security-and-firewall').'

'; echo ($info_msg_string); //get tables which are views $query = "SELECT * FROM INFORMATION_SCHEMA.VIEWS"; $res = $wpdb->get_results($query); if(empty($res)) return; $view_count = 0; foreach ($res as $item){ $old_def = $item->VIEW_DEFINITION; $new_def = str_replace($old_db_prefix, $new_db_prefix, $old_def); $new_def_no_bt = str_replace("`", "", $new_def); //remove any backticks because these will cause the "ALTER" command used later to fail $view_name = $item->TABLE_NAME; $chg_view_sql = "ALTER VIEW $view_name AS $new_def_no_bt"; //Note: cannot use $wpdb->prepare because it adds single quotes which cause the ALTER query to fail $view_res = $wpdb->query($chg_view_sql); if($view_res === false){ echo '

'.sprintf( __('Update of the following MySQL view definition failed: %s', 'all-in-one-wp-security-and-firewall'),$old_def).'

'; $aio_wp_security->debug_logger->log_debug("Update of the following MySQL view definition failed: ".$old_def,4);//Log the highly unlikely event of DB error }else{ $view_count++; } } if($view_count > 0){ echo '

'.sprintf( __('%s view definitions were updated successfully!', 'all-in-one-wp-security-and-firewall'), ''.$view_count.'').'

'; } return; } } //end class