;
my $act = &parse_logline($line);
next if (!$act);
# Check Webmin server
next if (!$in{'wall'} && $in{'webmin'} ne $act->{'webmin'});
# Check modified files
if ($gconfig{'logfiles'} && (!$in{'fall'} || !$in{'dall'})) {
# Make sure the specified file was modified
my $found = 0;
foreach my $d (&list_diffs($act)) {
my $filematch = $in{'fall'} ||
$d->{'object'} &&
$d->{'object'} eq $in{'file'};
my $diffmatch = $in{'dall'} ||
$d->{'diff'} =~ /\Q$in{'diff'}\E/i;
if ($filematch && $diffmatch) {
$found++;
last;
}
}
next if (!$found);
}
next if (!&can_user($act->{'user'}));
next if (!&can_mod($act->{'module'}));
# Check description
if (defined($in{'desc'}) && $in{'desc'} =~ /\S/) {
my $desc = &get_action_description($act, $in{'long'});
$desc =~ s/<[^>]+>//g;
next if ($desc !~ /\Q$in{'desc'}\E/i);
}
push(@match, $act);
}
}
close(LOG);
# Build search description
my $fromstr = &make_date($from, 1);
my $tostr = &make_date($to, 1);
my %minfo;
if (!$in{'mall'}) {
%minfo = &get_module_info($in{'module'});
}
my $searchmsg = join(" ",
$in{'uall'} == 0 ? &text('search_critu',
"".&html_escape($in{'user'})."") :
$in{'uall'} == 3 ? &text('search_critu',
"".&html_escape($in{'ouser'})."") :
$in{'uall'} == 2 ? &text('search_critnu',
"".&html_escape($in{'nuser'})."") : "",
$in{'mall'} ? '' : &text('search_critm',
"".&html_escape($minfo{'desc'}).""),
$in{'tall'} ? '' :
$fromstr eq $tostr ? &text('search_critt2', $tostr) :
&text('search_critt', $fromstr, $tostr),
$in{'desc'} ? &text('search_critd', &html_escape($in{'desc'}))
: "");
my %minfo_cache;
if ($in{'csv'}) {
# Show search results as CSV
my @cols;
foreach my $act (sort { $b->{'time'} <=> $a->{'time'} } @match) {
my $m = $act->{'module'};
my $minfo = $m eq "global" ?
{ 'desc' => $text{'search_global'} } :
$minfo_cache{$m};
if (!$minfo) {
my %minfo = &get_module_info($m);
$minfo = $minfo_cache{$m} = \%minfo;
}
my $desc = &get_action_description($act, $in{'long'});
$desc =~ s/<[^>]+>//g;
@cols = ( $desc,
$minfo->{'desc'},
$act->{'user'},
$act->{'ip'} );
if ($config{'host_search'}) {
push(@cols, $act->{'webmin'});
}
push(@cols, &make_date($act->{'time'},0 , "yyyy-mm-dd"));
print join(",", map { "\"$_\"" } @cols),"\n";
}
}
elsif (@match) {
# Show search results in table
if ($in{'sid'}) {
print "",&text('search_sid', "$match[0]->{'user'}",
"$in{'sid'}")," ..\n";
}
elsif ($in{'uall'} == 1 && $in{'mall'} && $in{'tall'}) {
print "$text{'search_critall'} ..
\n";
}
else {
my %minfo = &get_module_info($in{'module'}) if (!$in{'mall'});
print "$text{'search_crit'} $searchmsg ...
\n";
}
print &ui_columns_start(
[ $text{'search_action'},
$text{'search_module'},
$text{'search_user'},
$text{'search_host'},
$config{'host_search'} ? ( $text{'search_webmin'} ) : ( ),
$text{'time_ago_col'},
$text{'search_datetime'} ], "100");
foreach my $act (sort { $b->{'time'} <=> $a->{'time'} } @match) {
my @tm = localtime($act->{'time'});
my $m = $act->{'module'};
my $d;
my $minfo = $m eq "global" ?
{ 'desc' => $text{'search_global'} } :
$minfo_cache{$m};
if (!$minfo) {
# first time seeing module ..
my %minfo = &get_module_info($m);
$minfo = $minfo_cache{$m} = \%minfo;
}
my @cols;
my $desc = &get_action_description($act, $in{'long'});
my $anno = &get_annotation($act);
push(@cols, &ui_link("view.cgi?id=$act->{'id'}".
"&return=".&urlize($in{'return'} || "").
"&returndesc=".&urlize($in{'returndesc'} || "").
"&no_return=".&urlize($in{'no_return'} || "").
"&search_sub_title=".&urlize($in{'search_sub_title'} || "").
"&file=".($in{'fall'} ? "" : &urlize($in{'file'})).
"&search=".&urlize($in || ""),
&filter_javascript($desc)) );
if ($anno) {
$cols[$#cols] .= "
";
}
push(@cols, $minfo->{'desc'},
&html_escape($act->{'user'}),
&html_escape($act->{'ip'}));
if ($config{'host_search'}) {
push(@cols, $act->{'webmin'});
}
push(@cols, &make_date_relative($act->{'time'}));
push(@cols, &make_date($act->{'time'}));
print &ui_columns_row(\@cols);
}
print &ui_columns_end();
print &ui_link("search.cgi/webminlog.csv?$in&csv=1", $text{'search_csv'});
print "
\n";
}
else {
# Tell the user that nothing matches
print "
$text{'search_none2'}".(&trim($searchmsg) ? " @{[&trim($searchmsg, -1)]}" : "").".
\n";
}
if (!$in{'csv'} && !$in{'no_return'}) {
# Show page footer
if ($in{'return'}) {
&ui_print_footer($in{'return'}, $in{'returndesc'});
}
else {
&ui_print_footer("", $text{'index_return'});
}
}
sub parse_time
{
my $d = $in{"$_[0]_d"};
my $m = $in{"$_[0]_m"};
my $y = $in{"$_[0]_y"};
return 0 if (!$d && !$y);
my $rv;
eval { $rv = timelocal(0, 0, 0, $d, $m-1, $y-1900) };
&error($text{'search_etime'}) if ($@);
return $rv;
}