#!/usr/bin/perl
-#################################################################################
+################################################################################
+#
# File: $RCSfile: detail.cgi,v $
# Revision: $Revision: 1.1 $
# Description: Displays list of email addresses based on report type.
# Modified: $Date: 2013/06/12 14:05:47 $
# Language: perl
#
-# (c) Copyright 2000-2006, Andrew@DeFaria.com, all rights reserved.
+# (c) Copyright 2000-2021, Andrew@DeFaria.com, all rights reserved.
#
-################################################################################use strict;
+################################################################################
+use strict;
use warnings;
use MIME::Words qw(:all);
+
+use CGI qw(:standard *table start_td end_td start_Tr end_Tr start_div end_div);
+use CGI::Carp 'fatalsToBrowser';
+
use FindBin;
-$0 = $FindBin::Script;
-use lib $FindBin::Bin;
+local $0 = $FindBin::Script;
+
+use lib "$FindBin::Bin/../lib";
+use lib "$FindBin::Bin/../../lib";
use MAPS;
use MAPSLog;
-use MAPSUtil;
use MAPSWeb;
-use CGI qw (:standard *table start_td end_td start_Tr end_Tr start_div end_div);
-use CGI::Carp 'fatalsToBrowser';
+use DateUtils;
-my $type = param ('type');
-my $next = param ('next');
-my $lines = param ('lines');
-my $date = param ('date');
+my $type = param 'type';
+my $list = substr $type, 0, -4 if $type =~ /list$/;
+my $next = param 'next';
+my $lines = param 'lines';
+my $date = param 'date';
$date ||= '';
-my $userid;
-my $current;
-my $last;
-my $prev;
-my $total;
+my ($userid, $current, $last, $prev, $total);
+
my $table_name = 'detail';
my %types = (
]
);
-sub MakeButtons {
- my $type = shift;
+sub formatRule($) {
+ my ($rec) = @_;
+
+ return '' unless $rec->{pattern} or $rec->{domain};
+
+ $rec->{pattern} //= '';
+ $rec->{domain} //= '';
+
+ return "$rec->{pattern}\@$rec->{domain}";
+} # formatRule
+
+sub MakeButtons($) {
+ my ($type) = @_;
my $prev_button = $prev >= 0 ?
a ({-href => "detail.cgi?type=$type;date=$date;next=$prev",
if ($type eq 'whitelist') {
$buttons = $buttons .
submit ({-name => 'action',
- -value => 'Blacklist Marked',
- -onClick => 'return CheckAtLeast1Checked (document.detail);'}) .
+ -value => 'Blacklist',
+ -onClick => 'return CheckAtLeast1Checked (document.detail);'}) . ' ' .
submit ({-name => 'action',
- -value => 'Nulllist Marked',
- -onClick => 'return CheckAtLeast1Checked (document.detail);'}) .
+ -value => 'Nulllist',
+ -onClick => 'return CheckAtLeast1Checked (document.detail);'}) . ' ' .
submit ({-name => 'action',
- -value => 'Reset Marks',
+ -value => 'Reset',
-onClick => 'return ClearAll (document.detail);'});
} elsif ($type eq 'blacklist') {
$buttons = $buttons .
submit ({-name => 'action',
- -value => 'Whitelist Marked',
- -onClick => 'return CheckAtLeast1Checked (document.detail);'}) .
+ -value => 'Whitelist',
+ -onClick => 'return CheckAtLeast1Checked (document.detail);'}) . ' ' .
submit ({-name => 'action',
- -value => 'Nulllist Marked',
- -onClick => 'return CheckAtLeast1Checked (document.detail);'}) .
+ -value => 'Nulllist',
+ -onClick => 'return CheckAtLeast1Checked (document.detail);'}) . ' ' .
submit ({-name => 'action',
- -value => 'Reset Marks',
+ -value => 'Reset',
-onClick => 'return ClearAll (document.detail);'});
} elsif ($type eq 'nulllist') {
$buttons = $buttons .
submit ({-name => 'action',
- -value => 'Whitelist Marked',
- -onClick => 'return CheckAtLeast1Checked (document.detail);'}) .
+ -value => 'Whitelist',
+ -onClick => 'return CheckAtLeast1Checked (document.detail);'}) . ' ' .
submit ({-name => 'action',
- -value => 'Blacklist Marked',
- -onClick => 'return CheckAtLeast1Checked (document.detail);'}) .
+ -value => 'Blacklist',
+ -onClick => 'return CheckAtLeast1Checked (document.detail);'}) . ' ' .
submit ({-name => 'action',
- -value => 'Reset Marks',
+ -value => 'Reset',
-onClick => 'return ClearAll (document.detail);'});
} else {
$buttons = $buttons .
submit ({-name => 'action',
- -value => 'Whitelist Marked',
- -onClick => 'return CheckAtLeast1Checked (document.detail);'}) .
+ -value => 'Whitelist',
+ -onClick => 'return CheckAtLeast1Checked (document.detail);'}) . ' ' .
submit ({-name => 'action',
- -value => 'Blacklist Marked',
- -onClick => 'return CheckAtLeast1Checked (document.detail);'}) .
+ -value => 'Blacklist',
+ -onClick => 'return CheckAtLeast1Checked (document.detail);'}) . ' ' .
submit ({-name => 'action',
- -value => 'Nulllist Marked',
- -onClick => 'return CheckAtLeast1Checked (document.detail);'}) .
+ -value => 'Nulllist',
+ -onClick => 'return CheckAtLeast1Checked (document.detail);'}) . ' ' .
submit ({-name => 'action',
- -value => 'Reset Marks',
+ -value => 'Reset',
-onClick => 'return ClearAll (document.detail);'});
} # if
- return $buttons . $next_button;
+ print div {
+ -align => 'center',
+ -class => 'toolbar',
+ }, $buttons . $next_button;
+
+ return;
} # MakeButtons
-sub PrintTable {
+sub Body($) {
my ($type) = @_;
my $current = $next + 1;
+ my ($onlist, $rec);
+
print div {-align => 'center'}, b (
'(' . $current . '-' . $last . ' of ' . $total . ')');
print start_form {
-action => 'processaction.cgi',
-name => 'detail'
};
- print start_table ({-align => 'center',
- -id => $table_name,
- -border => 0,
- -cellspacing => 0,
- -cellpadding => 0,
- -width => '100%'}) . "\n";
- my $buttons = MakeButtons $type;
+ MakeButtons $type;
+
+ print start_div {-id => 'highlightrow'};
+
+ print start_table({-align => 'center',
+ -id => $table_name,
+ -border => 0,
+ -cellspacing => 0,
+ -cellpadding => 0,
+ -width => '100%'}) . "\n";
- print start_div {-class => 'toolbar'};
print
Tr [
- td {-class => 'tablebordertopleft',
- -valign => 'middle'},
- td {-class => 'tablebordertopright',
- -valign => 'middle',
- -align => 'center'}, $buttons,
+ th {-class => 'tablebordertopleft'}, '',
+ th {-class => 'tableborder'}, 'Sender',
+ th {-class => 'tableborder'}, 'List',
+ th {-class => 'tableborder'}, 'Hit Count',
+ th {-class => 'tableborder'}, 'Rule',
+ th {-class => 'tableborder'}, 'Retention',
+ th {-class => 'tablebordertopright'}, 'Comment/Date',
];
- print end_div;
- foreach my $sender (ReturnSenders $userid, $type, $next, $lines, $date) {
- my @msgs = ReturnMessages $userid, $sender;
- my @msgs2 = @msgs;
+ my @senders = ReturnSenders(
+ userid => $userid,
+ type => $type,
+ start_at => $next,
+ lines => $lines,
+ date => $date
+ );
+
+ for my $sender (@senders) {
+ my $msgs = ReturnMessages(
+ userid => $userid,
+ sender => $sender,
+ );
+
+ my $leftclass = 'tableleftdata';
+ my $dataclass = 'tabledata';
+ my $rightclass = 'tablerightdata';
+ my $senderclass = 'sender';
+ my $subjectclass = 'subject';
+
+ # Check to see if this is the last line
+ if ((($next + 1) % $lines) == (@senders % $lines)) {
+ # We always "bottom" the first column
+ $leftclass = 'tablebottomleft';
+
+ # Check to see if there any message lines to display
+ unless (@$msgs) {
+ $dataclass = 'tablebottomdata';
+ $rightclass = 'tablebottomright';
+ $senderclass = 'senderbottom';
+ } # unless
+ } # if
+
+ # This is for the purposes of supplying a subject line if the mailto address
+ # is clicked on. It's kludgy because we are simply grabbing the subject line
+ # of the first email sent where there may be many emails from this sender
+ # Still it is often the right subject (or a good enough one)
+ #
+ # A little tricky here because of transliteration. If I test for
+ # $msg->[0]{subject} when $msg->[0] is essentially empty I create the hash
+ # making it non empty. Therefore I need to first test if $msgs->[0] exists
+ # first.
+ my $heading = '';
+
+ if ($msgs->[0]) {
+ $heading = $msgs->[0]{subject} if $msgs->[0]{subject};
+ } # if
+
+ ($onlist, $rec) = OnWhitelist($sender, $userid, 0);
+
+ unless ($onlist) {
+ ($onlist, $rec) = OnBlacklist($sender, 0);
+
+ unless ($onlist) {
+ ($onlist, $rec) = OnNulllist($sender, 0);
+ } # unless
+ } # unless
$next++;
- print
- start_Tr {-valign => 'middle'};
- print
- td {-class => 'tableborder'}, small ($next,
- checkbox {-name => "action$next",
- -label => ''}),
- hidden ({-name => "email$next",
- -default => $sender});
- print
- start_td {-align => 'left'};
- print
- start_table {-class => 'tablerightdata',
- -cellpadding => 2,
- -callspacing => 0,
- -border => 0,
- -width => '100%',
- -bgcolor => '#d4d0c8'};
- print
- td {-class => 'tablelabel',
- -valign => 'middle',
- -width => '40'}, 'Sender:',
- td {-class => 'sender',
- -valign => 'middle'},
- a {-href => "mailto:$sender?subject=$msgs2[0][0]"}, $sender;
- print
- end_table;
-
- my $messages = 1;
-
- foreach (@msgs) {
- my $msg_date = pop @{$_};
- my $subject = pop @{$_};
-
- if ($date eq substr ($msg_date, 0, 10)) {
- $msg_date = b font {-color => 'green'}, SQLDatetime2UnixDatetime $msg_date;
+
+ # Start Sender line
+ my $rowspan = @$msgs + 1;
+
+ print start_Tr {-valign => 'middle'};
+ print td {
+ -class => $leftclass,
+ -align => 'right',
+ -valign => 'middle',
+ -rowspan => $rowspan,
+ }, $next,
+ checkbox {
+ -name => "action$next",
+ -label => '',
+ -valign => 'middle',
+ };
+
+ print hidden({
+ -name => "email$next",
+ -default => $sender,
+ });
+
+ # Get subject line
+ $heading = "?subject=$heading" if $heading;
+
+ print td {
+ -class => $senderclass,
+ }, a {
+ -href => "mailto:$sender$heading",
+ }, " $sender";
+
+ if ($rec) {
+ my $listlink = ($rec->{type} and $rec->{sequence}) ? "$rec->{type}:$rec->{sequence}" : '';
+
+ $rec->{comment} //= '';
+
+ print td {
+ -class => $dataclass,
+ -align => 'right',
+ }, a {
+ href => "/maps/php/list.php?type=$rec->{type}&next=" . ($rec->{sequence} - 1),
+ }, $listlink,
+ td {
+ -class => $dataclass,
+ -align => 'right',
+ }, "$rec->{hit_count} ",
+ td {
+ -class => $dataclass,
+ }, formatRule($rec),
+ td {
+ -class => $dataclass,
+ -align => 'right',
+ }, "$rec->{retention} ",
+ td {
+ -class => $rightclass,
+ }, $rec->{comment};
+ } else {
+ # $rec will be undefined if this message will be returned
+ print td {-class => $dataclass},
+ td {-class => $dataclass},
+ td {-class => $dataclass},
+ td {-class => $dataclass},
+ td {-class => $rightclass};
+ } # if
+
+ print end_Tr;
+
+ my $msgnbr = 0;
+
+ for my $rec (@$msgs) {
+ $msgnbr++;
+
+ # We increased $next earlier so do not add 1 here
+ if (($next % $lines) == (@senders % $lines)) {
+ $dataclass = 'tablebottomdata';
+ $rightclass = 'tablebottomright' if $msgnbr == @$msgs;
+
+ # Only subjectbottom the last message
+ $subjectclass = 'subjectbottom' if $msgnbr == @$msgs;
+ } # if
+
+ if ($date eq substr ($rec->{timestamp}, 0, 10)) {
+ $rec->{date} = b font {-color => 'green'}, SQLDatetime2UnixDatetime $rec->{timestamp};
} else {
- $msg_date = SQLDatetime2UnixDatetime $msg_date;
+ $rec->{date} = SQLDatetime2UnixDatetime $rec->{timestamp};
} # if
- $subject = $subject eq '' ? '<Unspecified>' : $subject;
- $subject = decode_mimewords ($subject);
- $subject =~ s/\>/>/g;
- $subject =~ s/\</</g;
+ $rec->{subject} //= '<Unspecified>';
+ $rec->{subject} = decode_mimewords ($rec->{subject});
+ $rec->{subject} =~ s/\>/>/g;
+ $rec->{subject} =~ s/\</</g;
- print
- start_table {-class => 'tablerightdata',
- -cellpadding => 2,
- -cellspacing => 2,
- -border => 0,
- -width => '100%'};
- my $msg_nbr = $messages;
print
Tr [
- td {-class => 'msgnbr',
- -valign => 'middle',
- -rowspan => 2,
- -width => '2%'}, $messages++,
- td {-class => 'tablelabel',
- -valign => 'middle',
- -width => '45'}, 'Subject:',
- td {-class => 'subject',
- -valign => 'middle',
- -bgcolor => '#ffffff'},
- a {-href => "display.cgi?sender=$sender;msg_nbr=$msg_nbr"}, $subject,
- td {-class => 'date',
- -width => '130',
- -valign => 'middle'}, $msg_date
+ td {
+ -class => $subjectclass,
+ -colspan => 5,
+ }, a {
+ -href => "display.cgi?sender=$sender;msg_date=$rec->{timestamp}",
+ }, ' ' . $rec->{subject},
+ td {-class => $rightclass,
+ -width => '150',
+ -align => 'right'}, span {-class => 'date'}, $rec->{date} . ' ',
];
- print end_table;
- } # foreach
- print end_td;
- print end_Tr;
- } # foreach
+ } # for
+ } # for
- print start_div {-class => 'toolbar'};
- print
- Tr [
- td {-class => 'tableborderbottomleft',
- -valign => 'middle'},
- td {-class => 'tableborderbottomright',
- -valign => 'middle'},
- $buttons
- ];
- print end_div;
print end_table;
+ print end_div;
+
+ MakeButtons $type;
+
print end_form;
-} # PrintTable
+
+ return;
+} # Body
# Main
+my $condition;
my @scripts = ('ListActions.js');
-my $heading_date =$date ne '' ? ' on ' . FormatDate ($date) : '';
+my $heading_date =$date ne '' ? ' on ' . FormatDate ($date, 1) : '';
-$userid = Heading (
+$userid = Heading(
'getcookie',
'',
(ucfirst ($type) . ' Report'),
- $types {$type} [0],
- $types {$type} [1] . $heading_date,
+ $types{$type} [0],
+ $types{$type} [1] . $heading_date,
$table_name,
@scripts
);
$userid ||= $ENV{USER};
-SetContext $userid;
-NavigationBar $userid;
+SetContext($userid);
+NavigationBar($userid);
unless ($lines) {
- my %options = GetUserOptions $userid;
+ my %options = GetUserOptions($userid);
$lines = $options{'Page'};
} # unless
if ($date eq '') {
- $condition .= "userid = '$userid' and type = '$type'";
+ $condition .= "type = '$type'";
} else {
my $sod = $date . ' 00:00:00';
my $eod = $date . ' 23:59:59';
- $condition .= "userid = '$userid' and type = '$type' "
- . "and timestamp > '$sod' and timestamp < '$eod' ";
+ $condition .= "type = '$type' and timestamp > '$sod' and timestamp < '$eod'";
} # if
-$total = MAPSDB::count_distinct ('log', 'sender', $condition);
+# Need to count distinct on sender
+$total = CountLogDistinct(
+ userid => $userid,
+ column => 'sender',
+ additional => $condition,
+);
$next ||= 0;
if (($next - $lines) > 0) {
$prev = $next - $lines;
} else {
- $prev = $next eq 0 ? -1 : 0;
+ $prev = $next == 0 ? -1 : 0;
} # if
-PrintTable $type;
+Body($type);
-Footing $table_name;
+Footing($table_name);
exit;