#!/usr/local/cpanel/3rdparty/bin/perl
package autofixer2::CSF_switchover_email;
#                                      Copyright 2026 WebPros International, LLC
#                                                           All rights reserved.
# copyright@cpanel.net                                         http://cpanel.net
# This code is subject to the cPanel license. Unauthorized copying is prohibited.

use strict;
use warnings;

BEGIN { unshift @INC, '/usr/local/cpanel'; }

use Template;
use Template::Plugin;
use Template::Plugins;

use Cpanel::Debug    ();
use Cpanel::Notify   ();
use Cpanel::LoadFile ();
use Cpanel::FileType ();

exit run() if !caller();

{
	package Cpanel::iContact::Class::autofixer2::CSF_switchover_email;

	use parent qw{Cpanel::iContact::Class};

	sub _get_subject {
		return 'Important update regarding ConfigServer Security & Firewall (CSF)';
	}

	sub _get_parsed_template {
		my ($self) = @_;
		my $tmpl = <<"HERE";
[%
PROCESS "include/colors.tmpl";
PROCESS "include/styles.tmpl";
PROCESS "include/code_block.tmpl";

WRAPPER 'wrapper/main.html.tmpl';
%]
<h5>Dear WHM administrator,</h5>
<p>We're writing about ConfigServer Security & Firewall (CSF) and an important update to keep your servers protected.</p>
<p>Way to the Web LTD (W2W / ConfigServer), the vendor behind the CSF plugin, permanently shut down on August 31, 2025, ending all support and distribution for CSF. Before closing, W2W released the CSF code "as-is" under the GNU General Public License v3 (GPLv3), with no plans for further maintenance or support.</p>
<p>CSF remains widely deployed on cPanel & WHM servers and plays a critical role in server security. To maintain ecosystem security, cPanel will be publishing and maintaining a public fork of CSF focused solely on critical security and stability fixes. This fork is based on the final upstream release and will be made available in cPanel & WHM's public GitHub repository under GPLv3, consistent with the original project's license.</p>
<h5>What this means for you</h5>
<p>Currently, CSF installations that point to ConfigServer/W2W’s original update server at download.configserver.com cannot receive updates because that infrastructure is offline. This can leave servers without future security fixes and may also trigger update/cron errors during scheduled checks.</p>
<p>To restore a working update path, on February 18, 2026, we'll automatically update the CSF configuration on eligible cPanel & WHM servers to point to our update mirrors instead of the decommissioned ConfigServer/W2W source.</p>
<p>This configuration update applies only if all of the following are true:</p>
<ul>
<li>Your server is using cPanel & WHM with the original CSF plugin.</li>
<li>CSF is configured to use the original ConfigServer/W2W update source.</li>
<li>Your server is running CSF version 14.0 or newer.</li>
<li>The CSF AUTO_UPDATES setting is enabled.</li>
</ul>
<p>We will not make any changes if any of the following are true:</p>
<ul>
<li>Your server is already using an alternate CSF provider:<br>
<code>cat /etc/csf/version.txt</code><br>
Versions greater than 14.24 will not be switched over,
so if the provider has updated the version file,
you do <b>NOT</b> need to take the following action:<br>
<code>echo '14.25' > /etc/csf/version.txt</code>
</li>
<li>Your server is running CSF version 13.x or older.</li>
<li>The CSF AUTO_UPDATES setting is disabled.</li>
</ul>
<p>If you’re currently using CSF, it will continue to run with the same rules and configuration you already have in place. This effort is simply to ensure critical security and stability fixes from our fork can still be delivered.</p>
<h5>Manage updates yourself (optional)</h5>
<p>You're in control of how CSF updates are handled on your servers - whether you want updates to apply automatically, on your own schedule, or from a different source. If you do not want cPanel to update your CSF configuration on February 18, 2026, follow these steps before this date to disable automatic updates and exclude the server from the change:</p>
<ol>
<li>Navigate to ConfigServer Security & Firewall.</li>
<li>Select csf - ConfigServer Firewall.</li>
<li>Open Firewall Configuration.</li>
<li>Under Initial Settings, set AUTO_UPDATES to off.</li>
<li>Save your changes.</li>
</ol>
<p>If you disable the AUTO_UPDATES setting before February 18, the configuration change will not be applied to your server. If you later decide you’d like updates from the cPanel-maintained fork, run /scripts/autorepair cpanel_csf_install to update the source, then re-enable the AUTO_UPDATES setting.</p>
<p>Updates will be distributed through the same mechanism the original version used: servers with the AUTO_UPDATES setting enabled will receive patches automatically, and servers with the AUTO_UPDATES setting disabled can apply updates manually.</p>
<p>For more details and further updates, please review our full support article
<a href="https://support.cpanel.net/hc/en-us/articles/37654028162071-Will-cPanel-provide-its-own-fork-of-CSF">here</a>.
</p>
<p>If you have questions, our support team is here to help.</p>
<p>Best regards,<p>
<i>The cPanel Team</i>
[% END %]
HERE

		my @html_related;
		$self->{'_html_related'} = \@html_related;
		my $template_root = '/usr/local/cpanel/etc/icontact_templates/';
		my $out = '';
		my $obj = Template->new(
			( map { $_ => 0 } qw{ABSOLUTE PRE_CHOMP} ),
			( map { $_ => 1 } qw{RELATIVE TRIM POST_CHOMP} ),
			INCLUDE_PATH => $template_root,
			LOAD_PLUGINS => [
				Template::Plugins->new( { PLUGINS => { CPANEL => 'Cpanel::iContact::Class::Plugin::CPANEL' } } ),
			]
		);

		# Set up the CPANEL plugin with html_related tracking
		$obj->context()->stash()->set(
			CPANEL => $obj->context()->plugin( 'CPANEL', [
				template_root   => $template_root,
				locale_obj      => $self->_find_or_return_locale_handle_from_input( $self->{'_locale'} ),
				html_related    => \@html_related,
				icontact_object => $self,
			] ),
		);

		my $ok = $obj->process(
			\$tmpl,
			{
				NOTICE => {
					notification_cannot_be_disabled => 1,
				},
			},
			\$out,
		);
		die "Template failed to process: " . $obj->error() if !$ok;

		# Post-process html_related entries to load content and detect MIME types
		for my $html_rel (@html_related) {
			my $full_path = "$template_root/$html_rel->{'path'}";
			$html_rel->{'content'} = Cpanel::LoadFile::load_r($full_path);

			if ( !$html_rel->{'content_type'} ) {
				$html_rel->{'content_type'} = Cpanel::FileType::determine_mime_type($full_path) || 'application/octet-stream';
			}
		}

		return $out;
	}
	sub _should_not_be_disabled { return 1 }
1;
}

sub run {
    return 0 unless supported_on_this_major( 110, 136 );    # Set this to the Min/Max we support this autofixer on.
	return 0 if time() > 1771394400; # February 18, 2026
    return 0 unless supported_on_this_csf( 14.0, 14.24 );

	my $class = __PACKAGE__;

	# Fool the notifier into not loading what's already in memory.
	$INC{'Cpanel/iContact/Class/autofixer2/CSF_switchover_email.pm'} = 1;
	$INC{'Cpanel/iContact/Class/Plugin/CPANEL.pm'} = 1;

    my $notify = Cpanel::Notify::notification_class(
		'constructor_args' => [],
		map { $_ => $class } qw{class application},
	);
    waitpid( $notify->{'_icontact_pid'}, 0 ) if $notify->{_icontact_pid};
    return 0;
}

# Do we run this code?
sub supported_on_this_major {
    my ( $min_ver, $max_ver ) = @_;

    my $major = get_major_version();

    return 0 if $major < $min_ver;
    return 0 if $major > $max_ver;

    return 1;
}

sub supported_on_this_csf {
    my ( $min_ver, $max_ver ) = @_;
    my $ver = Cpanel::LoadFile::load_if_exists('/etc/csf/version.txt');
    return unless length $ver;
    chomp($ver);
    return if $ver !~ qr/^\d+\.\d+$/; # Reject versions that don't "look" right.
    return if $ver < $min_ver || $ver > $max_ver;
    return 1;
}

sub get_major_version {
    my $major_version;

    if ( open( my $fh, '<', '/usr/local/cpanel/version' ) ) {
        my $full_version = <$fh>;
        close($fh);
        if ( length $full_version ) {
            chomp $full_version;
            ($major_version) = $full_version =~ /^[0-9]+\.([0-9]+)/;
        }
    }

    # Safe default.
    return $major_version || 30;
}

1;
