false, 'message' => __( 'You do not have permission to do this.', 'argus-wordpress-defence' ) ); } switch ( $type ) { case 'update_core': return self::update_core(); case 'update_plugin': return self::update_plugin( $params['plugin'] ?? '' ); case 'update_theme': return self::update_theme( $params['theme'] ?? '' ); case 'restore_quarantined_file': return self::restore_quarantined_file( $params['path'] ?? '' ); default: return array( 'success' => false, 'message' => __( 'Unknown action.', 'argus-wordpress-defence' ) ); } } protected static function restore_quarantined_file( $rel_path ) { if ( '' === $rel_path || Argus_Malware_Scanner::QUARANTINE_SUFFIX !== substr( $rel_path, -strlen( Argus_Malware_Scanner::QUARANTINE_SUFFIX ) ) ) { return array( 'success' => false, 'message' => __( 'Not a quarantined file.', 'argus-wordpress-defence' ) ); } $uploads = wp_get_upload_dir(); $base = wp_normalize_path( trailingslashit( ABSPATH ) ); $abs = wp_normalize_path( ABSPATH . ltrim( $rel_path, '/' ) ); $uploads_base = wp_normalize_path( trailingslashit( $uploads['basedir'] ?? '' ) ); if ( '' === $uploads_base || 0 !== strpos( $abs, $uploads_base ) || false !== strpos( $rel_path, '..' ) ) { return array( 'success' => false, 'message' => __( 'Refusing to restore a path outside the uploads directory.', 'argus-wordpress-defence' ) ); } if ( ! file_exists( $abs ) ) { return array( 'success' => false, 'message' => __( 'That file no longer exists.', 'argus-wordpress-defence' ) ); } $restored_abs = substr( $abs, 0, -strlen( Argus_Malware_Scanner::QUARANTINE_SUFFIX ) ); if ( file_exists( $restored_abs ) || ! @rename( $abs, $restored_abs ) ) { // phpcs:ignore WordPress.PHP.NoSilencedErrors return array( 'success' => false, 'message' => __( 'Could not restore the file (a file already exists at the original name, or the rename failed).', 'argus-wordpress-defence' ) ); } $restored_rel = str_replace( $base, '', $restored_abs ); Argus_Malware_Scanner::mark_restored_trusted( $restored_rel, hash_file( 'sha256', $restored_abs ) ); Argus_Events::record( 'action_completed', 'info', 'Restored quarantined file: ' . $restored_rel, array( 'type' => 'restore_quarantined_file', 'path' => $restored_rel ) ); return array( 'success' => true, 'message' => sprintf( __( 'Restored %s to its original name.', 'argus-wordpress-defence' ), $restored_rel ) ); } protected static function update_core() { require_once ABSPATH . 'wp-admin/includes/file.php'; require_once ABSPATH . 'wp-admin/includes/misc.php'; require_once ABSPATH . 'wp-admin/includes/template.php'; require_once ABSPATH . 'wp-admin/includes/class-wp-upgrader.php'; require_once ABSPATH . 'wp-admin/includes/update.php'; wp_version_check(); $updates = get_core_updates(); if ( empty( $updates ) || 'upgrade' !== ( $updates[0]->response ?? '' ) ) { return array( 'success' => true, 'message' => __( 'WordPress core is already up to date.', 'argus-wordpress-defence' ) ); } $upgrader = new Core_Upgrader(); $result = $upgrader->upgrade( $updates[0] ); if ( is_wp_error( $result ) ) { Argus_Events::record( 'action_failed', 'medium', 'Core update failed: ' . $result->get_error_message(), array( 'type' => 'update_core' ) ); return array( 'success' => false, 'message' => $result->get_error_message() ); } Argus_Events::record( 'action_completed', 'info', 'Updated WordPress core to ' . $updates[0]->version, array( 'type' => 'update_core', 'version' => $updates[0]->version ) ); return array( 'success' => true, 'message' => sprintf( __( 'Updated WordPress core to %s.', 'argus-wordpress-defence' ), $updates[0]->version ) ); } protected static function update_plugin( $plugin_file ) { if ( '' === $plugin_file ) { return array( 'success' => false, 'message' => __( 'Missing plugin.', 'argus-wordpress-defence' ) ); } require_once ABSPATH . 'wp-admin/includes/file.php'; require_once ABSPATH . 'wp-admin/includes/misc.php'; require_once ABSPATH . 'wp-admin/includes/template.php'; require_once ABSPATH . 'wp-admin/includes/class-wp-upgrader.php'; require_once ABSPATH . 'wp-admin/includes/update.php'; require_once ABSPATH . 'wp-admin/includes/plugin.php'; wp_update_plugins(); $upgrader = new Plugin_Upgrader(); $result = $upgrader->upgrade( $plugin_file ); if ( is_wp_error( $result ) || false === $result ) { $message = is_wp_error( $result ) ? $result->get_error_message() : __( 'Plugin update failed.', 'argus-wordpress-defence' ); Argus_Events::record( 'action_failed', 'medium', 'Plugin update failed: ' . $message, array( 'type' => 'update_plugin', 'plugin' => $plugin_file ) ); return array( 'success' => false, 'message' => $message ); } Argus_Events::record( 'action_completed', 'info', 'Updated plugin ' . $plugin_file, array( 'type' => 'update_plugin', 'plugin' => $plugin_file ) ); return array( 'success' => true, 'message' => __( 'Plugin updated.', 'argus-wordpress-defence' ) ); } protected static function update_theme( $stylesheet ) { if ( '' === $stylesheet ) { return array( 'success' => false, 'message' => __( 'Missing theme.', 'argus-wordpress-defence' ) ); } require_once ABSPATH . 'wp-admin/includes/file.php'; require_once ABSPATH . 'wp-admin/includes/misc.php'; require_once ABSPATH . 'wp-admin/includes/template.php'; require_once ABSPATH . 'wp-admin/includes/class-wp-upgrader.php'; require_once ABSPATH . 'wp-admin/includes/update.php'; wp_update_themes(); $upgrader = new Theme_Upgrader(); $result = $upgrader->upgrade( $stylesheet ); if ( is_wp_error( $result ) || false === $result ) { $message = is_wp_error( $result ) ? $result->get_error_message() : __( 'Theme update failed.', 'argus-wordpress-defence' ); Argus_Events::record( 'action_failed', 'medium', 'Theme update failed: ' . $message, array( 'type' => 'update_theme', 'theme' => $stylesheet ) ); return array( 'success' => false, 'message' => $message ); } Argus_Events::record( 'action_completed', 'info', 'Updated theme ' . $stylesheet, array( 'type' => 'update_theme', 'theme' => $stylesheet ) ); return array( 'success' => true, 'message' => __( 'Theme updated.', 'argus-wordpress-defence' ) ); } }