diff --git a/root/usr/share/smanager/lib/SrvMngr/Controller/Backup.pm b/root/usr/share/smanager/lib/SrvMngr/Controller/Backup.pm index 54465b8..d7f46ea 100644 --- a/root/usr/share/smanager/lib/SrvMngr/Controller/Backup.pm +++ b/root/usr/share/smanager/lib/SrvMngr/Controller/Backup.pm @@ -32,6 +32,10 @@ use esmith::util; use esmith::lockfile; use esmith::BlockDevices; use constant DEBUG => $ENV{MOJO_SMANAGER_DEBUG} || 0; + +use constant FALSE => 0; +use constant TRUE => 1; + #our $cdb = esmith::ConfigDB->open || die "Couldn't open config db"; #remove as cached gives problems #our $adb = esmith::AccountsDB->open || die "Couldn't open accounts db"; #our $rdb = esmith::ConfigDB->open('/etc/e-smith/restore') || die "Couldn't open restore db"; @@ -932,7 +936,7 @@ sub workstnVerify { sub workstnRestore { my ($c) = @_; - my $out; + my $out = ''; my $restoreref = $c->param('Backupset'); my $set = $restoreref; $set =~ s/\/[^\/]*$//; @@ -1015,6 +1019,7 @@ sub workstnRestore { return "$c->l('bac_OPERATION_STATUS_REPORT') $c->l('bac_ERR_PRE_RESTORE')"; } $| = 1; + my $RD; if (open(RD, "-|")) { @@ -1047,8 +1052,8 @@ sub workstnRestore { or warn($c->l('bac_ERR_RESTORING_INITIAL_GRP') . "\n"); esmith::util::backgroundCommand(0, "/sbin/e-smith/signal-event", "post-upgrade"); - # system("/sbin/e-smith/signal-event", "post-upgrade") == 0 - # or die ($c->l('bac_ERROR_UPDATING_CONFIGURATION')."\n"); + #system("/sbin/e-smith/signal-event", "post-upgrade") == 0 + # or die ($c->l('bac_ERROR_UPDATING_CONFIGURATION')."\n"); } else { $message = $c->l('bac_RESTORE_FAILED'); } @@ -1076,9 +1081,111 @@ sub workstnRestore { die($error_message) if $error_message; exit(0); } ## end else [ if (open(RD, "-|")) ] - $rdb->reload; - $error_message .= $c->bunmount($mntdir, $VFSType); - return '#OK#' . $out; + + #my $RD; + + ## Fork-safe open with explicit error handling + #unless (open($RD, "-|")) { + ## Child process + #local $SIG{__DIE__} = sub { exit 255 }; + #$| = 1; # Autoflush + + #eval { + #foreach my $file (@restorefiles) { + ## Security: strict filename validation + #unless ($file =~ m{^[\w\/.-]+$}) { + #die "Invalid filename: $file"; + #} + + ## Check file existence + #unless (-e $file) { + #die "Backup file $file does not exist"; + #} + + ## Execute dar with error checking + #system("/usr/bin/dar", "-Q", "-x", $file, "-v", "-N", "-R", "/", "-wa"); + #if ($? == -1) { + #die "Failed to execute dar: $!"; + #} elsif ($? & 127) { + #die sprintf("dar died with signal %d, %s coredump", + #($? & 127), ($? & 128) ? 'with' : 'without'); + #} elsif ($? >> 8 != 0) { + #die "dar exited with error code " . ($? >> 8); + #} + #} + + ## Unmount with error checking + #if (my $unmount_err = $c->bunmount($mntdir, $VFSType)) { + #die "Unmount failed: $unmount_err"; + #} + #}; + + #if (my $child_err = $@) { + #print STDERR "CHILD ERROR: $child_err"; + #exit 254; + #} + #exit 0; + #} + #else { + ## Parent process + #eval { + ## Verify fork succeeded + #unless (defined $RD) { + #die "Fork failed: $!"; + #} + + #$out .= $c->l('bac_FILES_HAVE_BEEN_RESTORED') . "\n
"; - - while ("; - $out .= sprintf(") { - $out .= sprintf("%s", $_); - } - close QMAILQUEUEREPORT; - $out .= sprintf "
"; + # Get the selected report from the form submission + my $selected_report = $report_type; - while ("; $out .= sprintf(") { + # Call the relevant report sub based on the selection + if ($selected_report eq 'daily_summary') { + $out .= daily_summary_report($log_path); + } + elsif ($selected_report eq 'daily_summary_today') { + $out .= daily_summary_report_today($log_path); + } + elsif ($selected_report eq 'top_senders') { + $out .= top_senders_and_recipients($log_path); + } + elsif ($selected_report eq 'bounce_analysis') { + $out .= bounce_rate_analysis($log_path); + } + elsif ($selected_report eq 'spam_and_virus') { + $out .= spam_and_virus_filter_report($log_path); + } + elsif ($selected_report eq 'delivery_status') { + $out .= delivery_status_report($log_path); + } + elsif ($selected_report eq 'geo_analysis') { + $out .= geographical_analysis_of_email($log_path); + } + elsif ($selected_report eq 'traffic_analysis') { + $out .= traffic_analysis($log_path); + } + elsif ($selected_report eq 'auth_analysis') { + $out .= authentication_analysis($log_path); + } + elsif ($selected_report eq 'user_activity') { + $out .= user_activity_report($log_path); + } + elsif ($selected_report eq 'error_reporting') { + $out .= error_reporting($log_path); + } + elsif ($selected_report eq 'comparison_reports') { + $out .= comparison_reports($log_path, '/var/log/mail.log.1'); + } + elsif ($selected_report eq 'customized_reports') { + $out .= customized_reports($log_path); + } + else { + $out .= 'Invalid report selected'; + } - # Cook any special HTML characters - s/\&/\&/g; - s/\"/\"/g; - s/\>/\>/g; - s/\\</g; - $out .= sprintf("%s", $_); - } ## end while ( ) - close QMAILANALOG; + # The $output variable now contains the generated report output. + # Further processing can be done here, or you can render it later. + $out .= sprintf "
$content+HTML +} + + +### 1. Message Tracking +#sub trace_message { + #my ($log_path, $message_id) = @_; + ##my $tracer = Mail::Log::Trace::Postfix->new({log_file => $log_path}); + ##$tracer->set_message_id($message_id); + + #my $output = "Message Tracking Report for ID: $message_id\n"; + ##$output .= "=" x 50 . "\n"; + ##$output .= sprintf "%-12s: %s\n", 'From', $tracer->get_from_address; + ##$output .= sprintf "%-12s: %s\n", 'Status', $tracer->get_final_status; + + ##$output .= "\nRecipients:\n"; + ##$output .= join("\n", map { "- $_" } $tracer->get_recipient_addresses); + + ##$output .= "\n\nTimeline:\n"; + ##my $timeline = $tracer->get_timestamps; + ##while (my ($stage, $time) = each %$timeline) { + ##$output .= sprintf "%-10s: %s\n", ucfirst($stage), $time; + ##} + + #return $output || "No records found for message ID: $message_id"; +#} + +#### 2. Queue Analysis +#sub get_queue_stats { + #my $spool_dir = '/var/spool/postfix'; + #my %queues = map { $_ => 0 } qw(active deferred bounce hold corrupt); + + #foreach my $q (keys %queues) { + #opendir(my $dh, "$spool_dir/$q"); + #$queues{$q} = scalar(grep { -f "$spool_dir/$q/$_" } readdir($dh)); + #closedir($dh); + #} + + #my $output = "Current Postfix Queue Status\n"; + #$output .= "=" x 30 . "\n"; + #$output .= sprintf "%-10s: %3d messages\n", ucfirst($_), $queues{$_} + #for sort keys %queues; + #$output .= "\nTotal: " . sum(values %queues) . " messages in queue"; + + #return $output; +#} + +#### 3. Message Statistics +#sub get_message_stats { + #my ($log_path) = @_; + #my %stats = (received => 0, rejected => 0, delivered => 0, + #deferred => 0, bounced => 0, held => 0); + + #open(my $fh, '<', $log_path); + #while(<$fh>) { + #$stats{received}++ if /qmgr.*: [A-Z0-9]+: from=/; + #$stats{delivered}++ if /status=sent/; + #$stats{rejected}++ if /NOQUEUE: reject/; + #$stats{deferred}++ if /status=deferred/; + #$stats{bounced}++ if /status=bounced/; + #$stats{held}++ if /status=hold/; + #} + #close($fh); + + #my $output = "Message Statistics for " . localtime . "\n"; + #$output .= "=" x 40 . "\n"; + #$output .= sprintf "%-12s: %6d\n", 'Received', $stats{received}; + #$output .= sprintf "%-12s: %6d (%.1f%%)\n", 'Delivered', $stats{delivered}, + #($stats{received} ? ($stats{delivered}/$stats{received}*100) : 0); + #$output .= sprintf "%-12s: %6d\n", 'Rejected', $stats{rejected}; + #$output .= sprintf "%-12s: %6d\n", 'Deferred', $stats{deferred}; + #$output .= sprintf "%-12s: %6d\n", 'Bounced', $stats{bounced}; + #$output .= sprintf "%-12s: %6d\n", 'Held', $stats{held}; + + #return $output; +#} + +#### 4. User Activity Audit +#sub get_user_activity { + #my ($log_path, $email) = @_; + ##my $tracer = Mail::Log::Trace::Postfix->new({log_file => $log_path}); + + ##my $sent = scalar $tracer->find_messages_by_sender($email); + ##my $received = scalar $tracer->find_messages_by_recipient($email); + + #my $output = "Activity Report for: $email\n"; + ##$output .= "=" x (length($email) + 18) . "\n"; + ##$output .= "Messages sent: $sent\n"; + ##$output .= "Messages received: $received\n\n"; + + ##$output .= "Last week's activity:\n"; + ##$output .= join("\n", map { sprintf "- %s: %d messages", $_->[0], $_->[1] } + ##$tracer->get_weekly_stats($email)); + + #return $output || "No activity found for $email"; +#} + +#### 5. Security Monitoring +#sub detect_auth_failures { + #my ($log_path) = @_; + #my %failures; + + #open(my $fh, '<', $log_path); + #while(<$fh>) { + #if(/SASL (?:LOGIN|PLAIN) authentication failed.*?\[([0-9.]+)\]/) { + #$failures{$1}++; + #} + #} + #close($fh); + + #return "No authentication failures found" unless keys %failures; + + #my $output = "Authentication Failure Report\n"; + #$output .= "=" x 30 . "\n"; + #$output .= sprintf "%-15s %s\n", 'IP Address', 'Attempts'; + #$output .= sprintf "%-15s %s\n", '-' x 15, '-' x 7; + + #foreach my $ip (sort { $failures{$b} <=> $failures{$a} } keys %failures) { + #$output .= sprintf "%-15s %5d\n", $ip, $failures{$ip}; + #} + #$output .= "\nTotal failures: " . sum(values %failures); + + #return $output; +#} + + + + +1; \ No newline at end of file diff --git a/root/usr/share/smanager/lib/SrvMngr/I18N/Modules/General/general_en.lex b/root/usr/share/smanager/lib/SrvMngr/I18N/Modules/General/general_en.lex index a372ee7..9d8e0a4 100644 --- a/root/usr/share/smanager/lib/SrvMngr/I18N/Modules/General/general_en.lex +++ b/root/usr/share/smanager/lib/SrvMngr/I18N/Modules/General/general_en.lex @@ -151,4 +151,4 @@ SMALL => 'Small', MEDIUM => 'Medium', LARGE => 'Large', FIELD_INVALID_CHARS => 'A field you entered contains invalid characters.', - +'REPORT_GENERATED' => "Report generated", \ No newline at end of file diff --git a/root/usr/share/smanager/lib/SrvMngr/I18N/Modules/Qmailanalog/qmailanalog_en.lex b/root/usr/share/smanager/lib/SrvMngr/I18N/Modules/Qmailanalog/qmailanalog_en.lex index b3f5cbf..462b7e6 100644 --- a/root/usr/share/smanager/lib/SrvMngr/I18N/Modules/Qmailanalog/qmailanalog_en.lex +++ b/root/usr/share/smanager/lib/SrvMngr/I18N/Modules/Qmailanalog/qmailanalog_en.lex @@ -8,6 +8,14 @@ reports are available. these reports', 'qma_REPORT_TYPE' => 'Choose a report type', 'qma_GENERATE_REPORT' => 'Generate report', +'qma_INVALID_REPORT_TYPE' => 'Invalid report type: ', +'qma_REPORT_GENERATED' => 'Report generated: ', +'qma_END_OF_REPORT' => 'End of Report', +'Mail log file analysis' => 'Mail log file analysis', + +'qma_Daily_Summary_Report_yesterday' => 'Summary report for yesterday', +'qma_Daily_Summary_Report_today' => 'Summary report for today up to now', + 'qma_LIST_OUTGOING' => 'List outgoing messages and recipients', 'qma_SUMMARIZE_QUEUE' => 'Summarize status of mail queue', 'qma_SUCCESSFUL_DELIVERY_DELAY' => 'Successful delivery delay distribution', @@ -20,9 +28,4 @@ these reports', 'qma_SENDER_STATS' => 'Sender statistics', 'qma_SENDMAIL_STYLE' => 'Sendmail style log', 'qma_REASONS_SUCCESS' => 'Reasons for success', -'qma_SENDER_UIDS' => 'Sender uids', -'qma_INVALID_REPORT_TYPE' => 'Invalid report type: ', -'qma_REPORT_GENERATED' => 'Report generated: ', -'qma_END_OF_REPORT' => 'End of Report', -'Mail log file analysis' => 'Mail log file analysis', - +'qma_SENDER_UIDS' => 'Sender uids', \ No newline at end of file diff --git a/root/usr/share/smanager/themes/default/public/css/module.css b/root/usr/share/smanager/themes/default/public/css/module.css new file mode 100644 index 0000000..f4f77d8 --- /dev/null +++ b/root/usr/share/smanager/themes/default/public/css/module.css @@ -0,0 +1,43 @@ +/* General styles for the module panel */ +#module { + padding: 20px; + border: 1px solid #ccc; + border-radius: 10px; + background-color: #f9f9f9; + box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1); +} + +/* Debug information styling */ +#module p { + font-family: monospace; + color: #555; +} + +#module pre { + background-color: #eee; + padding: 10px; + border-radius: 5px; +} + +/* Error message styling */ +.sme-error { + color: #d9534f; + font-weight: bold; + margin-bottom: 15px; +} + +/* Title styling */ +#module h1 { + font-family: Arial, sans-serif; + color: #333; + text-align: center; + margin-bottom: 20px; +} + +/* Content styling */ +.module-content { + font-family: Georgia, serif; + font-size: 13px; + line-height: 1.2; + color: #555; +} \ No newline at end of file diff --git a/root/usr/share/smanager/themes/default/public/js/qmailanalog.js b/root/usr/share/smanager/themes/default/public/js/qmailanalog.js new file mode 100644 index 0000000..edcb9f5 --- /dev/null +++ b/root/usr/share/smanager/themes/default/public/js/qmailanalog.js @@ -0,0 +1,25 @@ +document.addEventListener('DOMContentLoaded', function() { + const analysisType = document.getElementById('analysis_type'); + const messageIdGroup = document.getElementById('message_id_group'); + const emailAddressGroup = document.getElementById('email_address_group'); + + // Initially hide both controls + messageIdGroup.style.display = 'none'; + emailAddressGroup.style.display = 'none'; + + analysisType.addEventListener('change', function() { + // Hide both controls first + messageIdGroup.style.display = 'none'; + emailAddressGroup.style.display = 'none'; + + // Show the relevant control based on the selected option + switch(this.value) { + case 'trace_message': + messageIdGroup.style.display = 'block'; + break; + case 'user_activity': + emailAddressGroup.style.display = 'block'; + break; + } + }); +}); \ No newline at end of file diff --git a/root/usr/share/smanager/themes/default/templates/module.html.ep b/root/usr/share/smanager/themes/default/templates/module.html.ep index 9eef738..01789e3 100644 --- a/root/usr/share/smanager/themes/default/templates/module.html.ep +++ b/root/usr/share/smanager/themes/default/templates/module.html.ep @@ -1,20 +1,27 @@ % layout 'default', title => "Sme server 2 - module"; % content_for 'module' => begin - +%= stylesheet '/css/module.css'
- %= dumper $c->current_route -
++ Debug Info: +
<%= dumper $c->current_route %>+ % } - % if ( stash 'error' ) { -
@@ -11,17 +11,34 @@
<%= $modul %>
<% my $btn = l('qma_GENERATE_REPORT'); %>
-
%= form_for 'qmailanalog' => (method => 'POST') => begin
-
- - %=l 'qma_REPORT_TYPE' - - - %= select_field 'report_type' => $c->reportType_list() - -
- %= submit_button "$btn", class => 'action' ++ + %=l 'qma_REPORT_TYPE' + + + %= select_field 'report_type' => $c->reportType_list(), id => 'analysis_type' + +
+ + +