%PDF- %PDF-
| Direktori : /www/varak.net/dmarc.varak.net/classes/Report/ |
| Current File : /www/varak.net/dmarc.varak.net/classes/Report/OverallReport.php |
<?php
/**
* dmarc-srg - A php parser, viewer and summary report generator for incoming DMARC reports.
* Copyright (C) 2024-2025 Aleksey Andreev (liuch)
*
* Available at:
* https://github.com/liuch/dmarc-srg
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
* Software Foundation, either version 3 of the License.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along with
* this program. If not, see <http://www.gnu.org/licenses/>.
*
* =========================
*
* This file contains OverallReport class
*
* @category API
* @package DmarcSrg
* @author Aleksey Andreev (liuch)
* @license https://www.gnu.org/licenses/gpl-3.0.html GNU/GPLv3
*/
namespace Liuch\DmarcSrg\Report;
use Liuch\DmarcSrg\Common;
use Liuch\DmarcSrg\TextTable;
/**
* This class is for generating an overall report on accumulated data
*/
class OverallReport
{
private $rows = [];
/**
* Adds a report row
*
* @param array $data Report data array
*
* @return void
*/
public function appendData(array $data): void
{
$this->rows[] = $data;
}
/**
* Removes data for the specified domain from the report
*
* @param \Liuch\DmarcSrg\Domains\Domain $domain Domain to remove data for
*
* @return void
*/
public function removeRow($domain): void
{
$fqdn = $domain->fqdn();
foreach ($this->rows as $i => &$row) {
if ($row['fqdn'] === $fqdn) {
unset($this->rows[$i]);
break;
}
}
unset($row);
}
/**
* Returns the report data as an array
*
* @return array
*/
public function toArray(): array
{
return $this->rows;
}
/**
* Returns the report as an array of text strings
*
* @return array
*/
public function text(): array
{
$res = [ '# Overall by domains', '' ];
$table = new TextTable([ '', 'Emails', 'SPF only', 'DKIM only', 'Not aligned', 'Quar+Rej' ]);
$table->setMinColumnsWidth([ 15, 6, 8, 9, 11, 8 ])->setBorders('', '', '')
->setColumnAlignment(4, 'right')->setColumnAlignment(5, 'right');
foreach ($this->rows as &$row) {
$total = $row['total'];
$d_aln = $row['dkim_aligned'];
$s_aln = $row['spf_aligned'];
$q_dis = $row['quarantined'];
$r_dis = $row['rejected'];
$n_aln = $total - $row['dkim_spf_aligned'] - $d_aln - $s_aln;
if ($q_dis || $r_dis) {
$s_dis = Common::num2percent($q_dis + $r_dis, $total, false) . "({$q_dis}+{$r_dis})";
} else {
$s_dis = '0';
}
$table->appendRow([
$row['fqdn'], $total, $s_aln, $d_aln, Common::num2percent($n_aln, $total, true), $s_dis
]);
}
unset($row);
foreach ($table->toArray() as $line) {
$res[] = " $line";
}
$res[] = '';
return $res;
}
/**
* Returns the report as an array of html strings
*
* @return array
*/
public function html(): array
{
$h2a = 'style="margin:15px 0 5px;"';
$t2a = 'style="border-collapse:collapse;border-spacing:0;"';
$c1a = 'style="font-style:italic;"';
$d3s = 'border:1px solid #888;';
$d4s = 'text-align:right;';
$d5s = 'padding:.3em;';
$rs2 = 'rowspan="2"';
$cs2 = 'colspan="2"';
$get_color = function (string $name, int $num) {
$cn = '';
if ($num > 0) {
switch ($name) {
case 'red':
$cn = 'f00';
break;
case 'green':
$cn = '080';
break;
}
}
return empty($cn) ? '' : "color:#{$cn};";
};
$r_cnt = count($this->rows);
$res[] = "<h2 {$h2a}>Overall by domains</h2>";
$res[] = "<table {$t2a}>";
$res[] = " <caption {$c1a}>Total records: {$r_cnt}</caption>";
$res[] = ' <thead>';
$style = "style=\"{$d3s}{$d5s}\"";
$res[] = " <tr><th {$rs2} {$style}>Name</th><th {$rs2} {$style}>Emails</th>" .
"<th {$cs2} {$style}>Partial aligned</th><th {$rs2} {$style}>Not aligned</th>" .
"<th {$cs2} {$style}>Disposition</th></tr>";
$res[] = "<th {$style}>SPF only</th><th {$style}>DKIM only</th>" .
"<th {$style}>quar+rej</th><th {$style}>fail rate</th></tr>";
$res[] = ' </thead>';
$res[] = ' <tbody>';
$style = "style=\"{$d3s}{$d5s}";
foreach ($this->rows as &$row) {
$name = htmlspecialchars(trim($row['fqdn']));
$total = $row['total'];
$f_aln = $row['dkim_spf_aligned'];
$d_aln = $row['dkim_aligned'];
$s_aln = $row['spf_aligned'];
$n_aln = $total - $f_aln - $d_aln - $s_aln;
$q_dis = $row['quarantined'];
$r_dis = $row['rejected'];
$s_dis = ($q_dis || $r_dis) ? "{$q_dis}+{$r_dis}" : '0';
$res[] = " <tr><td {$style}\">{$name}</td><td {$style}{$d4s}\">{$total}</td>" .
"<td {$style}{$d4s}\">{$s_aln}</td><td {$style}{$d4s}\">{$d_aln}</td>" .
"<td {$style}{$d4s}{$get_color('red', $n_aln)}\">{$n_aln}</td>" .
"<td {$style}{$d4s}{$get_color('red', $q_dis + $r_dis)}\">{$s_dis}</td>" .
"<td {$style}{$d4s}\">" . Common::num2percent($q_dis + $r_dis, $total, false) .
'</td></tr>';
}
unset($row);
$res[] = ' </tbody>';
$res[] = '</table>';
return $res;
}
/**
* Returns the report data in CSV format
*
* @return string
*/
public function csv(): string
{
$res = [ 'Overall by domains' ];
$res[] = '';
$res[] = [ '', 'Emails', 'SPF only', 'DKIM only', 'Not aligned', 'Quar+Rej' ];
foreach ($this->rows as &$row) {
$total = $row['total'];
$d_aln = $row['dkim_aligned'];
$s_aln = $row['spf_aligned'];
$q_dis = $row['quarantined'];
$r_dis = $row['rejected'];
$n_aln = $total - $row['dkim_spf_aligned'] - $d_aln - $s_aln;
if ($q_dis || $r_dis) {
$s_dis = Common::num2percent($q_dis + $r_dis, $total, false) . "({$q_dis}+{$r_dis})";
} else {
$s_dis = '0';
}
$res[] = [
trim($row['fqdn']), $total, $s_aln, $d_aln, Common::num2percent($n_aln, $total, true), $s_dis
];
}
unset($row);
return Common::arrayToCSV($res);
}
}