#!/usr/local/cpanel/3rdparty/bin/perl # gniza4cp WHM Plugin — Main Config Editor use strict; use warnings; use lib '/usr/local/cpanel/whostmgr/docroot/cgi/gniza4cp-whm/lib'; use Whostmgr::HTMLInterface (); use Cpanel::Form (); use Gniza4cpWHM::Config; use Gniza4cpWHM::Validator; use Gniza4cpWHM::UI; my $CONFIG_FILE = '/etc/gniza4cp/gniza4cp.conf'; my $form = Cpanel::Form::parseform(); my $method = $ENV{'REQUEST_METHOD'} // 'GET'; my $action = $form->{'action'} // ''; # ── Handle SMTP Test (JSON) ────────────────────────────────── if ($action eq 'test_smtp') { print "Content-Type: application/json\r\n\r\n"; unless ($method eq 'POST' && Gniza4cpWHM::UI::verify_csrf_token($form->{'gniza4cp_csrf'})) { print qq({"success":false,"message":"Invalid or expired token. Please reload and try again."}); exit; } # Generate fresh token after consuming the old one my $new_csrf = Gniza4cpWHM::UI::generate_csrf_token(); my $host = $form->{'SMTP_HOST'} // ''; my $port = $form->{'SMTP_PORT'} || '587'; my $user = $form->{'SMTP_USER'} // ''; my $password = $form->{'SMTP_PASSWORD'} // ''; my $from = $form->{'SMTP_FROM'} // ''; my $security = $form->{'SMTP_SECURITY'} || 'tls'; my $to = $form->{'NOTIFY_EMAIL'} // ''; if ($host eq '') { print qq({"success":false,"message":"SMTP Host is required.","csrf":"$new_csrf"}); exit; } if ($to eq '') { print qq({"success":false,"message":"Notification email is required for test.","csrf":"$new_csrf"}); exit; } my ($ok, $err) = Gniza4cpWHM::UI::test_smtp_connection( host => $host, port => $port, user => $user, password => $password, from => $from, security => $security, to => $to, ); if ($ok) { print qq({"success":true,"message":"Test email sent successfully. Check your inbox.","csrf":"$new_csrf"}); } else { $err //= 'Unknown error'; $err =~ s/\\/\\\\/g; $err =~ s/"/\\"/g; $err =~ s/\n/\\n/g; $err =~ s/\r/\\r/g; $err =~ s/\t/\\t/g; $err =~ s/[\x00-\x1f]//g; print qq({"success":false,"message":"SMTP test failed: $err","csrf":"$new_csrf"}); } exit; } # ── Handle POST ────────────────────────────────────────────── my @errors; my $saved = 0; if ($method eq 'POST') { unless (Gniza4cpWHM::UI::verify_csrf_token($form->{'gniza4cp_csrf'})) { push @errors, 'Invalid or expired form token. Please try again.'; } if (!@errors) { my %data; for my $key (@Gniza4cpWHM::Config::MAIN_KEYS) { $data{$key} = $form->{$key} // ''; } my $validation_errors = Gniza4cpWHM::Validator::validate_main_config(\%data); if (@$validation_errors) { @errors = @$validation_errors; } else { my ($ok, $err) = Gniza4cpWHM::Config::save($CONFIG_FILE, \%data, \@Gniza4cpWHM::Config::MAIN_KEYS); if ($ok) { Gniza4cpWHM::UI::set_flash('success', 'Configuration saved successfully.'); print "Status: 302 Found\r\n"; print "Location: settings.cgi\r\n\r\n"; exit; } else { push @errors, "Failed to save config: $err"; } } } } # ── Render Page ────────────────────────────────────────────── print "Content-Type: text/html\r\n\r\n"; Whostmgr::HTMLInterface::defheader('GNIZA4CP Backup Manager — Settings', '', '/cgi/gniza4cp-whm/settings.cgi'); print Gniza4cpWHM::UI::page_header('Settings'); print Gniza4cpWHM::UI::render_nav('settings.cgi'); print Gniza4cpWHM::UI::render_flash(); if (@errors) { print Gniza4cpWHM::UI::render_errors(\@errors); } # Load current config (or use POST data if validation failed) my $conf; if (@errors && $method eq 'POST') { $conf = {}; for my $key (@Gniza4cpWHM::Config::MAIN_KEYS) { $conf->{$key} = $form->{$key} // ''; } } else { $conf = Gniza4cpWHM::Config::parse($CONFIG_FILE, 'main'); } # Helper to output a text field row sub field_text { my ($key, $label, $hint, $extra, $tip) = @_; $extra //= ''; my $val = Gniza4cpWHM::UI::esc($conf->{$key} // ''); my $hint_html = $hint ? qq{ } . Gniza4cpWHM::UI::esc($hint) . qq{} : ''; my $tip_html = $tip ? qq{ } : ''; print qq{
\n}; print qq{ \n}; print qq{ \n}; print qq{ $hint_html\n} if $hint; print qq{
\n}; } # Helper to output a select field row sub field_select { my ($key, $label, $options_ref) = @_; my $current = $conf->{$key} // ''; print qq{
\n}; print qq{ \n}; print qq{ \n}; print qq{
\n}; } # ── Form ───────────────────────────────────────────────────── print qq{
\n}; print Gniza4cpWHM::UI::csrf_hidden_field(); # Section: Local Settings print qq{
\n
\n}; print qq{

Local Settings

\n}; field_text('TEMP_DIR', 'Working Directory', 'Default: /usr/local/gniza4cp/workdir', '', 'Temporary directory used for pkgacct output before transfer'); print qq{
\n
\n}; # Section: Account Filtering print qq{
\n
\n}; print qq{

Account Filtering

\n}; my $inc_val = Gniza4cpWHM::UI::esc($conf->{INCLUDE_ACCOUNTS} // ''); my $exc_val = Gniza4cpWHM::UI::esc($conf->{EXCLUDE_ACCOUNTS} // ''); print qq{
\n}; print qq{ \n}; print qq{ \n}; print qq{
\n}; print qq{
\n}; print qq{ \n}; print qq{ \n}; print qq{
\n}; my @accounts = Gniza4cpWHM::UI::get_cpanel_accounts(); if (@accounts) { print qq{
}; print qq{Available accounts: } . Gniza4cpWHM::UI::esc(join(', ', @accounts)); print qq{
\n}; } print qq{
\n
\n}; # Section: Logging print qq{
\n
\n}; print qq{

Logging

\n}; field_text('LOG_DIR', 'Log Directory', 'Default: /var/log/gniza4cp'); field_select('LOG_LEVEL', 'Log Level', ['debug', 'info', 'warn', 'error']); field_text('LOG_RETAIN', 'Log Retention (days)', 'Default: 90', '', 'Log files older than this are automatically deleted'); print qq{
\n
\n}; # Section: Notifications print qq{
\n
\n}; print qq{

Notifications

\n}; field_text('NOTIFY_EMAIL', 'Email Address(es)', 'Comma-separated, empty = disabled'); field_select('NOTIFY_ON', 'Notify On', ['always', 'failure', 'never']); print qq{
\n
\n}; # Section: SMTP Settings print qq{
\n
\n}; print qq{

SMTP Settings

\n}; print qq{

Optional. When SMTP Host is empty, system mail/sendmail is used.

\n}; field_text('SMTP_HOST', 'SMTP Host', 'e.g. smtp.gmail.com'); field_text('SMTP_PORT', 'SMTP Port', 'Default: 587'); field_text('SMTP_USER', 'SMTP Username', 'e.g. user@gmail.com'); # SMTP Password (type=password) my $smtp_pw_val = Gniza4cpWHM::UI::esc($conf->{SMTP_PASSWORD} // ''); print qq{
\n}; print qq{ \n}; print qq{ \n}; print qq{
\n}; field_text('SMTP_FROM', 'From Address', 'Falls back to SMTP Username'); field_select('SMTP_SECURITY', 'Security', ['tls', 'ssl', 'none']); print qq{
\n}; print qq{ \n}; print qq{
\n}; print qq{
\n}; print qq{
\n
\n}; # Section: User Restore (cPanel Plugin) print qq{
\n
\n}; print qq{

User Restore (cPanel Plugin)

\n}; print qq{

Controls which remotes are available for cPanel user self-service restore.

\n}; field_text('USER_RESTORE_REMOTES', 'Allowed Remotes', '"all" = all remotes, comma-separated names, empty = disabled', '', 'Which backup remotes cPanel users can restore from. Set to "all" for all remotes, specific names like "nas,offsite", or leave empty to disable user restore.'); print qq{
\n
\n}; # Section: Advanced print qq{
\n
\n}; print qq{

Advanced

\n}; field_text('LOCK_FILE', 'Lock File', 'Default: /var/run/gniza4cp.lock', '', 'Prevents multiple backup processes from running simultaneously'); field_text('SSH_TIMEOUT', 'SSH Timeout (seconds)', 'Default: 30', '', 'How long to wait for an SSH connection before giving up'); field_text('SSH_RETRIES', 'SSH Retries', 'Default: 3', '', 'Number of rsync retry attempts with exponential backoff on failure'); field_text('RSYNC_EXTRA_OPTS', 'Extra rsync Options', 'Additional flags for rsync', '', 'Global extra flags appended to all rsync commands, e.g. --compress'); print qq{
\n
\n}; # Submit print qq{
\n}; print qq{ \n}; print qq{
\n}; print qq{
\n}; my $smtp_csrf = Gniza4cpWHM::UI::generate_csrf_token(); print qq{ JS print Gniza4cpWHM::UI::page_footer(); Whostmgr::HTMLInterface::footer();