initial commit of file from CVS for smeserver-manager on Fri Mar 22 14:54:28 AEDT 2024
This commit is contained in:
336
root/usr/share/smanager/lib/SrvMngr/Controller/Viewlogfiles.pm
Normal file
336
root/usr/share/smanager/lib/SrvMngr/Controller/Viewlogfiles.pm
Normal file
@@ -0,0 +1,336 @@
|
||||
package SrvMngr::Controller::Viewlogfiles;
|
||||
|
||||
#----------------------------------------------------------------------
|
||||
# heading : Investigation
|
||||
# description : View log files
|
||||
# navigation : 7000 100
|
||||
#
|
||||
#
|
||||
# routes : end
|
||||
#----------------------------------------------------------------------
|
||||
use strict;
|
||||
use warnings;
|
||||
use Mojo::Base 'Mojolicious::Controller';
|
||||
|
||||
#use esmith::FormMagick qw(gen_locale_date_string);
|
||||
|
||||
use Locale::gettext;
|
||||
use SrvMngr::I18N;
|
||||
use SrvMngr qw(theme_list init_session);
|
||||
|
||||
use esmith::ConfigDB;
|
||||
use Time::TAI64;
|
||||
use File::Basename;
|
||||
use HTML::Entities;
|
||||
use esmith::FormMagick qw(gen_locale_date_string);
|
||||
use File::Temp qw(tempfile);
|
||||
|
||||
use constant TRUE => 1;
|
||||
use constant FALSE => 0;
|
||||
|
||||
our $cdb = esmith::ConfigDB->open() || die "Couldn't open config db";
|
||||
|
||||
our @logfiles = (); # with array
|
||||
|
||||
|
||||
sub main {
|
||||
my $c = shift;
|
||||
$c->app->log->info($c->log_req);
|
||||
|
||||
my %log_datas = ();
|
||||
my $title = $c->l('log_FORM_TITLE');
|
||||
my $notif = '';
|
||||
|
||||
$log_datas{default_op} =
|
||||
($cdb->get('viewlogfiles')->prop('DefaultOperation')) || 'view';
|
||||
|
||||
$c->stash( title => $title, notif => $notif, log_datas => \%log_datas);
|
||||
$c->render(template => 'viewlogfiles');
|
||||
};
|
||||
|
||||
|
||||
sub do_action {
|
||||
my $c = shift;
|
||||
$c->app->log->info($c->log_req);
|
||||
|
||||
my $title = $c->l('log_FORM_TITLE');
|
||||
my $notif = '';
|
||||
my $result = "";
|
||||
my %log_datas = ();
|
||||
|
||||
$log_datas{filename} = $c->param('Filename');
|
||||
$log_datas{matchpattern} = $c->param('Matchpattern');
|
||||
$log_datas{highlightpattern} = $c->param('Highlightpattern');
|
||||
$log_datas{operation} = $c->param('Operation');
|
||||
if ($log_datas{operation} eq 'download') {
|
||||
$log_datas{'trt'} = "DOWN"
|
||||
} else {
|
||||
$log_datas{'trt'} = "SHOW"
|
||||
}
|
||||
|
||||
|
||||
if ($log_datas{filename} =~ /^([\S\s]+)$/) {
|
||||
$log_datas{filename} = $1;
|
||||
} elsif ($log_datas{filename} =~ /^$/) {
|
||||
$log_datas{filename} = "messages";
|
||||
} else {
|
||||
$result .= $c->l("log_FILENAME_ERROR", $log_datas{filename} )
|
||||
. " ";
|
||||
}
|
||||
|
||||
if ($log_datas{matchpattern} =~ /^(\S+)$/) {
|
||||
$log_datas{matchpattern} = $1;
|
||||
} else {
|
||||
$log_datas{matchpattern} = ".";
|
||||
}
|
||||
|
||||
if ($log_datas{highlightpattern} =~ /^(\S+)$/) {
|
||||
$log_datas{highlightpattern} = $1;
|
||||
} else {
|
||||
$log_datas{highlightpattern} = '';
|
||||
}
|
||||
|
||||
my $fullpath = "/var/log/$log_datas{filename}";
|
||||
if (-z $fullpath) {
|
||||
$result .= $c->l("log_LOG_FILE_EMPTY", "$log_datas{filename}" );
|
||||
}
|
||||
|
||||
if ($log_datas{trt} eq "SHOW") {
|
||||
if ( ! $result ) {
|
||||
$result = $c->render_to_string(inline => showlogFile( $c, %log_datas ));
|
||||
}
|
||||
|
||||
if ( $result ) {
|
||||
$c->stash(title => $title, modul => $result, log_datas => \%log_datas);
|
||||
return $c->render(template => 'viewlogfiles2');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if ( $log_datas{trt} eq 'DOWN' ) {
|
||||
|
||||
my $modul = 'Log file download';
|
||||
|
||||
$notif = download_logFile( $c, %log_datas );
|
||||
return undef unless defined $notif;
|
||||
}
|
||||
|
||||
$c->stash( title => $title, notif => $notif, log_datas => \%log_datas);
|
||||
$c->render(template => 'viewlogfiles');
|
||||
|
||||
};
|
||||
|
||||
|
||||
sub timestamp2local
|
||||
{
|
||||
$_ = shift;
|
||||
if (/^(\@[0-9a-f]{24})(.*)/s)
|
||||
{
|
||||
return Time::TAI64::tai64nlocal($1) . $2;
|
||||
}
|
||||
elsif (/^([0-9]{10}\.[0-9]{3})(.*)/s)
|
||||
{
|
||||
return localtime($1) . $2;
|
||||
}
|
||||
return $_;
|
||||
}
|
||||
|
||||
|
||||
sub findlogFiles {
|
||||
|
||||
my $c = shift;
|
||||
|
||||
use File::Find;
|
||||
sub findlogfiles
|
||||
{
|
||||
my $path = $File::Find::name;
|
||||
|
||||
if (-f)
|
||||
{
|
||||
# Remove leading /var/log/messages
|
||||
$path =~ s:^/var/log/::;
|
||||
# don't bother to collect files known to be non-text
|
||||
# or not log files
|
||||
foreach (qw(
|
||||
lastlog
|
||||
btmp$
|
||||
wtmp
|
||||
lock
|
||||
(?<!qpsmtpd/)state
|
||||
httpd/ssl_mutex.\d*
|
||||
httpd/ssl_scache.pag
|
||||
httpd/ssl_scache.dir
|
||||
\/config$
|
||||
))
|
||||
{
|
||||
return if $path =~ /$_/;
|
||||
}
|
||||
|
||||
my ($file_base, $file_path, $file_type) = fileparse($path);
|
||||
|
||||
if ( $file_base =~ /@.*/ )
|
||||
{
|
||||
#$logfiles{$path} = $file_path . timestamp2local($file_base);
|
||||
push @logfiles, [ $file_path . timestamp2local($file_base), $path ];
|
||||
}
|
||||
else
|
||||
{
|
||||
#$logfiles{$path} = $path;
|
||||
push @logfiles, [ $path, $path ];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@logfiles = ();
|
||||
# Now go and find all the files under /var/log
|
||||
find({wanted => \&findlogfiles, no_chdir => 1}, '/var/log');
|
||||
|
||||
my @logf = sort { $a->[0] cmp $b->[0] } @logfiles;
|
||||
|
||||
return \@logf;
|
||||
}
|
||||
|
||||
|
||||
sub showlogFile {
|
||||
|
||||
my ($c, %log_datas) = @_;
|
||||
|
||||
my $fullpath = "/var/log/$log_datas{filename}";
|
||||
my $out = '';
|
||||
|
||||
$out .= sprintf("$fullpath: \n");
|
||||
|
||||
$out .= sprintf($c->l("log_VIEWING_TIME", $c->gen_locale_date_string() ));
|
||||
|
||||
unless ( $log_datas{matchpattern} eq '.' )
|
||||
{
|
||||
#$out .= sprintf("<p>\n");
|
||||
$out .= sprintf($c->l("log_MATCH_HEADER", $log_datas{matchpattern} ));
|
||||
}
|
||||
|
||||
if ( $log_datas{highlightpattern} )
|
||||
{
|
||||
#$out .= sprintf("<p>\n");
|
||||
$out .= sprintf($c->l("log_HIGHLIGHT_HEADER", "$log_datas{highlightpattern}" ));
|
||||
}
|
||||
|
||||
if ($log_datas{filename} =~ /\.gz$/) {
|
||||
my $pid = open(LOGFILE, "-|");
|
||||
die "Couldn't fork: $!" unless defined $pid;
|
||||
unless ($pid) {
|
||||
# Child
|
||||
exec("/bin/zcat", $fullpath)
|
||||
|| die "Can't exec zcat: $!";
|
||||
# NOTREACHED
|
||||
}
|
||||
} else {
|
||||
open(LOGFILE, "$fullpath");
|
||||
}
|
||||
|
||||
my $somethingMatched = 0;
|
||||
my $fileEmpty = 1;
|
||||
$out .= sprintf("<PRE>");
|
||||
while(<LOGFILE>)
|
||||
{
|
||||
$fileEmpty = 0;
|
||||
next unless /$log_datas{matchpattern}/;
|
||||
$somethingMatched = 1;
|
||||
|
||||
$_ = timestamp2local($_);
|
||||
$_ = HTML::Entities::encode_entities($_);
|
||||
($log_datas{highlightpattern} && /$log_datas{highlightpattern}/)
|
||||
? $out .= sprintf( "<b>$_</b>" )
|
||||
: $out .= sprintf("$_");
|
||||
}
|
||||
$out .= sprintf("</PRE>");
|
||||
|
||||
if ($fileEmpty) {
|
||||
$out .= sprintf("<p>\n");
|
||||
$out .= sprintf($c->l("log_LOG_FILE_EMPTY"));
|
||||
} else {
|
||||
unless ($somethingMatched)
|
||||
{
|
||||
$out .= sprintf("<p>\n");
|
||||
$out .= sprintf($c->l("log_NO_MATCHING_LINES"));
|
||||
}
|
||||
}
|
||||
|
||||
close LOGFILE;
|
||||
|
||||
return $out;
|
||||
}
|
||||
|
||||
|
||||
sub download_logFile {
|
||||
|
||||
my ($c, %log_datas) = @_;
|
||||
|
||||
my $fullpath = "/var/log/$log_datas{filename}";
|
||||
|
||||
# Save this information for later.
|
||||
|
||||
$cdb->get('viewlogfiles')->merge_props('DefaultOperation', $log_datas{operation});
|
||||
|
||||
# If the client is on windows, we must handle this a little differently.
|
||||
my $win32 = FALSE;
|
||||
my $mac = FALSE;
|
||||
my $agent = $ENV{HTTP_USER_AGENT} || "";
|
||||
if ($agent =~ /win32|windows/i) {
|
||||
$win32 = TRUE;
|
||||
} elsif ($agent =~ /mac/i) {
|
||||
$mac = TRUE;
|
||||
}
|
||||
|
||||
# Check for errors first. Once we start sending the file it's too late to
|
||||
# report them.
|
||||
my $error = "";
|
||||
unless (-f $fullpath) {
|
||||
$error = $c->l("log_ERR_NOEXIST_FILE") . $fullpath;
|
||||
}
|
||||
|
||||
local *FILE;
|
||||
open(FILE, "<$fullpath")
|
||||
or $error = $c->l("log_ERR_NOOPEN_FILE");
|
||||
# Put other error checking here.
|
||||
return $error if $error;
|
||||
|
||||
# Fix the filename, as it might have a directory prefixed to it.
|
||||
my $filename = $log_datas{filename};
|
||||
if ( $filename =~ m#/# ) {
|
||||
$filename = (split /\//, $filename)[-1];
|
||||
}
|
||||
|
||||
# And send the file.
|
||||
my $nl = "\n";
|
||||
if ($win32) { $nl = "\r\n" }
|
||||
elsif ($mac) { $nl = "\r" }
|
||||
|
||||
# Otherwise, send the file. Start with the headers.
|
||||
# Note: The Content-disposition must be attachment, or IE will view the
|
||||
# file inline like it's told. It ignores the Content-type, but it likes
|
||||
# the Content-disposition (an officially unsupported header) for some
|
||||
# reason. Yay Microsoft.
|
||||
|
||||
my $file2 = new File::Temp( UNLINK => 0 );
|
||||
|
||||
while (my $line = <FILE>) {
|
||||
chomp $line;
|
||||
my $linew = timestamp2local($line) . $nl;
|
||||
print $file2 $linew;
|
||||
}
|
||||
close(FILE);
|
||||
|
||||
$c->render_file(
|
||||
'filepath' => "$file2",
|
||||
'filename' => "$filename",
|
||||
'format' => 'x-download',
|
||||
'content_disposition' => 'attachment',
|
||||
'cleanup' => 1,
|
||||
);
|
||||
|
||||
return undef;
|
||||
}
|
||||
|
||||
|
||||
1;
|
||||
|
Reference in New Issue
Block a user