<?php
######################################################################
# ZW3B.Site v7.1.2 : The Web Sites Management System
# --------------------------------------------------------------------
#
# Copyright (c) 2022 by LAB3W : O.Romain Jaillet-ramey - (orj+php+dmarc@lab3w.fr)
#
# Date Create : 2022/07/08
# Date Modify : 2023/03/21
#
# Web Domain : lab3w.fr
# Web Domain : lab3w.com
#
# Web Domain : zw3b.fr
# Web Domain : zw3b.tv
# Web Domain : zw3b.com
# Web Domain : zw3b.net
# Web Domain : zw3b.blog
#
# Web Domain : ipv01.net
# Web Domain : ipv10.net
#
# This module is to manage ---------------------------- :: Descripton
#
# 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 2 of the License.
######################################################################

//----------------------------------------------------------------
// INI Config

ini_set('track_errors','on');
ini_set('display_errors','on');
ini_set('default_charset''UTF-8');

// INI Config
//----------------------------------------------------------------

//----------------------------------------------------------------
// Systeme de cache

# On cache
#header("Cache-Control: max-age=300");
#header("Pragma: cache, max-age=300, max-stale=600");

# No cache
header("Cache-control: private, no-store, no-cache, must-revalidate, post-check=0, pre-check=0");
header("Pragma: no-cache");

// Systeme de cache
//----------------------------------------------------------------

//----------------------------------------------------------------
// Header Security

header('X-Frame-Options: deny'); // permet de ne pas charger cette page depuis un autre site via une iframe

// Header Security
//----------------------------------------------------------------

//----------------------------------------------------------------
// Constantes

# My Title default
define('MY_DMARC_TITLE''Global analysis of mail servers of spoofers from <a href="https://www.zw3b.com/dmarc/" title="ZW3B.Com :-: DMARC"><acronym title="Domain-based Message Authentication, Reporting and Conformance" lang="EN">DMARC</acronym> Reports</a> &copy; <a href="https://www.zw3b.site" title="ZW3B :-: The Web Site">ZW3B</a> ');

# My Title compagny
define('MY_DOMAIN_TITLE''by <a href="http://orj.lab3w.fr" title="LAB3W : O.Romain.Jaillet-ramey">LAB3W.ORJ</a>');

# HTML directory where JSON are stored (with write rights for www-data)
define('DIRECTORY_DMARC_STATS_JSON''/var/pro/web_sites/zw3b_com/www/web/var/dmarc/');

# Hide SPF (valid) rows in HTML table
define('HIDE_MY_SPF_LINE_IN_TABLE'true);

# Hide name request from spoofing mail servers
define('HIDE_NAMESERVER_FQDN_SPOOFER_COLS'false);

//----------------------------------------------------------------

//----------------------------------------------------------------
// Functions

function check_dmarc_json_files_directory()
{
    
    
$directory constant('DIRECTORY_DMARC_STATS_JSON').'';
    
//$file = 'dmarc_stats-'.constant('URL_DMARC_STATS_JSON_NAME').'-'.$date.'.json';
    
    
$c 0;
    foreach(@
scandir($directory) as $k => $file)
    {
        if(
$file != "." && $file != ".." && substr("$file"01) != "." && substr($filestrlen($file)-4strlen($file)) == 'json')
        {
            
            
$currentfile $directory.$file.'';
            
            
$statfile = @stat($currentfile);
            
            
$stats = new stdClass();
            
            
$stats->uid $statfile['uid'];
            
$stats->gid $statfile['gid'];
            
            
$stats->date = new stdClass();
            
$stats->date->atime = new stdClass();
            
$stats->date->atime->timestamp $statfile['atime'];
            
$stats->date->atime->human date('Ymdhis'$statfile['atime']);
            
$stats->date->mtime = new stdClass();
            
$stats->date->mtime->timestamp $statfile['mtime'];
            
$stats->date->mtime->human date('Ymdhis'$statfile['mtime']);
            
$stats->date->ctime = new stdClass();
            
$stats->date->ctime->timestamp $statfile['ctime'];
            
$stats->date->ctime->human date('Ymdhis'$statfile['ctime']);

            
$stats->mode decoct($statfile['mode']);
            
$stats->mode substr($stats->mode25);
            
            
$stats->mime_type = @mime_content_type($currentfile);
            
            
// infos on file               
            
$json_files[$c] = new stdClass();
            
$json_files[$c]->file = new stdClass();
            
$json_files[$c]->file->directory $currentfile;
            
$json_files[$c]->file->stats $stats;
            
// infos on file
            
            // data in file
            
$json_data file_get_contents($currentfile); 
            
$json_files[$c]->data json_decode($json_data);
            
// data in file
        
            
$c += 1;
            
        } 
// if
        
    
// foreach
            
    
return $json_files;
}

function 
statistics_dmarc_json_files() 
{
    
$json_data check_dmarc_json_files_directory();
    
    
//echo '<pre>'.print_r($json_data,1).'</pre>';
    
    
$statistics = new stdClass();
    
$statistics->infos = new stdClass();
    
$statistics->infos->title = new stdClass();
    
$statistics->infos->mailserver = new stdClass();
    
$statistics->infos->spf = array();
    
    
$statistics->infos->date = new stdClass();
    
$statistics->infos->date->since = new stdClass();
    
$statistics->infos->date->until = new stdClass();
    
    
$statistics->count = new stdClass();
    
$statistics->count->emails = new stdClass();
    
    
$statistics->count->emails->passed 0;
    
$statistics->count->emails->errors 0;
    
$statistics->count->emails->sent 0;
    
    
$statistics->servers_error = array();
    
    foreach(
$json_data as $file) {
        
        
$statistics->infos->title $file->data->infos->title;
        
$statistics->infos->mailserver str_replace('_''.'$file->data->infos->mailserver);
        
        foreach(
$file->data->infos->spf as $k => $spf$statistics->infos->spf[$k] = in_array($spf$statistics->infos->spf) ? $spf $spf;
        
        
$statistics->count->emails->passed += $file->data->stats->count->emails->passed;
        
$statistics->count->emails->errors += $file->data->stats->count->emails->errors;
        
$statistics->count->emails->sent += $file->data->stats->count->emails->sent;
    
        foreach(
$file->data->stats->servers_error as $server_error)
        {
            
$servers_error[$server_error->address_ip] = !isset($servers_error[$server_error->address_ip]) ? new stdClass() : $servers_error[$server_error->address_ip];
            
            
$servers_error[$server_error->address_ip]->address_ip $server_error->address_ip;
            
$servers_error[$server_error->address_ip]->fqdn $server_error->fqdn;
            
$servers_error[$server_error->address_ip]->count_mails_error = isset($servers_error[$server_error->address_ip]->count_mails_error) ? $servers_error[$server_error->address_ip]->count_mails_error $server_error->count_mails_error $server_error->count_mails_error;
            
$servers_error[$server_error->address_ip]->auth = isset($servers_error[$server_error->address_ip]->auth) && $servers_error[$server_error->address_ip]->auth == $server_error->auth $servers_error[$server_error->address_ip]->auth $server_error->auth;
            
            
$servers_error[$server_error->address_ip]->date = !isset($servers_error[$server_error->address_ip]->date) ? new stdClass() : $servers_error[$server_error->address_ip]->date;
            
$servers_error[$server_error->address_ip]->date->year = isset($servers_error[$server_error->address_ip]->date->year) && $servers_error[$server_error->address_ip]->date->year == $file->data->infos->date->year $servers_error[$server_error->address_ip]->date->year $file->data->infos->date->year;
            
$servers_error[$server_error->address_ip]->date->month = isset($servers_error[$server_error->address_ip]->date->month) && $servers_error[$server_error->address_ip]->date->month == $file->data->infos->date->month $servers_error[$server_error->address_ip]->date->month $file->data->infos->date->month;

            
$statistics->infos->date->since->year = isset($statistics->infos->date->since->year) && $statistics->infos->date->since->year $file->data->infos->date->year $statistics->infos->date->since->year $file->data->infos->date->year;
            
$statistics->infos->date->since->month = isset($statistics->infos->date->since->month) && $statistics->infos->date->since->year == $file->data->infos->date->year && $statistics->infos->date->since->month <= $file->data->infos->date->month $statistics->infos->date->since->month : (isset($statistics->infos->date->since->month) ? $statistics->infos->date->since->month $file->data->infos->date->month);
            
            
$statistics->infos->date->until->year = isset($statistics->infos->date->until->year) && $statistics->infos->date->until->year $file->data->infos->date->year $statistics->infos->date->until->year $file->data->infos->date->year;
            
$statistics->infos->date->until->month = isset($statistics->infos->date->until->month) && $statistics->infos->date->until->year == $file->data->infos->date->year && $statistics->infos->date->until->month <= $file->data->infos->date->month $file->data->infos->date->month '00';
            
        }
        
        
$c = -1;
        foreach(
$servers_error as $k => $s_error)
            
$serv_err[$c+=1] = $s_error;
            
        
usort($serv_err"count_mails_error_sort");

        
$statistics->servers_error array_reverse($serv_err);
        
    }
    
    
$statistics->count->servers_error count($statistics->servers_error);
    
    return 
$statistics;
    
}

function 
check_number($nbr) {
    if (
preg_match("/^[0-9]/",$nbr) and preg_match("/([0-9]{1,})/"$nbr$temp)) {
        
$nbr $temp[1];
    }
    
    return 
$nbr;
}

function 
count_mails_error_sort($a,$b) {
    if (
check_number($a->count_mails_error) == check_number($b->count_mails_error)) {
        return 
0;
    }
    return (
check_number($a->count_mails_error) < check_number($b->count_mails_error) ? -1);
}

// Functions
//----------------------------------------------------------------


//----------------------------------------------------------------
// Request Cross-Origin
//
// 20220710 : Style API REST - en dev - test for the fun ;)
//
// Autoriser un client (autre serveur web) Ã  accèder Ã  la ressource au format JSON.
// 
// Exemple sans security CORS de notre ressource JSON :
//
// $data = file_get_contents('https://www.zw3b.com/dmarc-reports-analytics.php?get=json');
// $json = json_decode($data);
// echo '<pre>'.print_r($json,1).'</pre>';
//
// Exemple avec security CORS sur notre ressource JSON : 
//
// Il faut faire une demande avec : 
// https://developer.mozilla.org/fr/docs/Web/API/Fetch_API
// https://developer.mozilla.org/fr/docs/Web/API/XMLHttpRequest
//
// CF : https://developer.mozilla.org/fr/docs/Web/HTTP/CORS
//----------

$API['config']['client'] = array('debian-dev-test''zw3b');

//$API['access']['origins'] = array('https://wwd.zw3b.site', 'https://www.zw3b.site');
//$API['access']['name_api_client'] = 'api_dmarc_zw3b';

$API['client']['debian-dev-test']['name'] = 'debian-dev-test';
//$API['client']['debian-dev-test']['key'] = 'fjsklshklhfjshfjksfhjkshfjksfhjkshfjk';
$API['client']['debian-dev-test']['access']['name_api_dmarc_client'] = 'api_dmarc_client';
$API['client']['debian-dev-test']['access']['origins'] = array('dev.debian-fr.org');

$API['client']['zw3b']['name'] = 'zw3b';
//$API['client']['zw3b']['key'] = 'fjdskljljgdiozeuotrioruuiruerituetiutm';
$API['client']['zw3b']['access']['name_api_dmarc_client'] = 'api_dmarc_client';
$API['client']['zw3b']['access']['origins'] = array('https://wwd.zw3b.site''https://www.zw3b.site''https://admin.lab3w.com''https://adm.lab3w.fr');


if(isset(
$_GET['get']) && $_GET['get'] == 'json')
{
    
    
header("Content-type: application/json; charset=utf-8");
    
//header("Cache-Control: max-age=60");
   
    
header("X-Content-Type-Options: nosniff"); // par default depuis le début de l'année
    
    //header("Sec-Fetch-User:    ?1"); // un navigateur web peut voir la ressource ?
    
    /*
    header("Sec-Fetch-Dest: document");
    //header("Sec-Fetch-Mode: navigate");
    header("Sec-Fetch-Mode: no-cors"); // pas d'origine croisée
    #header("Sec-Fetch-Site: same-origin"); // même origine vhost.domaine.tld
    #header("Sec-Fetch-Site: same-site"); // même site domaine.tld
    header("Sec-Fetch-Site: cross-site"); // origine croisée
    #header("Sec-Fetch-Site:    none"); // origine non vérifiée
    
    
    header("Cross-Origin-Opener-Policy: same-origin"); // unsafe-none | same-origin-allow-popups | same-origin
    header("Cross-Origin-Embedder-Policy: require-corp"); // require-corp | unsafe-none
    header("Cross-Origin-Resource-Policy: same-origin"); // same-site | same-origin | cross-origin
    */
    
    //header("Sec-Fetch-Mode: cors"); // origine croisée
    //header("Sec-Fetch-Site: cross-site"); // origine croisée
    
    
header("Access-Control-Allow-Methods: GET, OPTIONS");
    
header('Access-Control-Allow-Headers: Access-Control-Allow-Origin, X-API-Client-ID, X-API-Origin');
    
    
//header("Access-Control-Allow-Headers: Content-type, Access-Control-Allow-Headers, Authorization, X-Requested-With");
    //header('Access-Control-Allow-Headers: Access-Control-Allow-Origin, X-ZW3B-Api-Origin');
    
    //header("Access-Control-Allow-Origin: ".(isset($_SERVER['HTTP_ORIGIN']) ? $_SERVER['HTTP_ORIGIN'] : "*")."");
    //header("Connection: Upgrade, keep-alive");
    
    //HTTP_X_ZW3B_API_ORIGIN    "my_server_home"
    //HTTP_SEC_FETCH_DEST    "empty"
    //HTTP_SEC_FETCH_MODE    "cors"
    //HTTP_SEC_FETCH_SITE    "same-origin"
        
    //-------------------------
    
if(isset($_SERVER['REQUEST_METHOD']) && $_SERVER['REQUEST_METHOD'] == "OPTIONS") {
        
        
header("Access-Control-Allow-Methods: OPTIONS");
        
header("Access-Control-Allow-Origin: ".(isset($_SERVER['HTTP_ORIGIN']) ? $_SERVER['HTTP_ORIGIN'] : "*")."");
        
        
// Custom headers
        
header("X-API-Client-ID: ".(isset($_SERVER['HTTP_X_API_CLIENT_ID']) ? $_SERVER['HTTP_X_API_CLIENT_ID'] : null)."");
        
//header("X-API-Name: ".(isset($_SERVER['HTTP_X_API_NAME']) ? $_SERVER['HTTP_X_API_NAME'] : null)."");
        
header("X-API-Origin: ".(isset($_SERVER['HTTP_X_API_ORIGIN']) ? $_SERVER['HTTP_X_API_ORIGIN'] : null)."");
        
// Custom headers
        
        
$client_id = isset($_SERVER['HTTP_X_API_CLIENT_ID']) && in_array($_SERVER['HTTP_X_API_CLIENT_ID'], $API['config']['client']) ? $_SERVER['HTTP_X_API_CLIENT_ID'] : null;
        
        
$client = isset($client_id) ? $API['client'][$client_id] : null;
        
        
//header("Connection: Upgrade, keep-alive");
        
    
}
    
    if(isset(
$_SERVER['REQUEST_METHOD']) && $_SERVER['REQUEST_METHOD'] == "GET") {
            
        
header("Access-Control-Allow-Methods: GET");
        
header("Access-Control-Allow-Origin: ".(isset($_SERVER['HTTP_ORIGIN']) ? $_SERVER['HTTP_ORIGIN'] : "*")."");
        
        
// Custom headers
        
header("X-API-Client-ID: ".(isset($_SERVER['HTTP_X_API_CLIENT_ID']) ? $_SERVER['HTTP_X_API_CLIENT_ID'] : null)."");
        
//header("X-API-Name: ".(isset($_SERVER['HTTP_X_API_NAME']) ? $_SERVER['HTTP_X_API_NAME'] : null)."");
        
header("X-API-Origin: ".(isset($_SERVER['HTTP_X_API_ORIGIN']) ? $_SERVER['HTTP_X_API_ORIGIN'] : null)."");
        
// Custom headers
        
        
$client_id = isset($_SERVER['HTTP_X_API_CLIENT_ID']) && in_array($_SERVER['HTTP_X_API_CLIENT_ID'], $API['config']['client']) ? $_SERVER['HTTP_X_API_CLIENT_ID'] : null;
        
        
$client = isset($client_id) ? $API['client'][$client_id] : null;
        
        if(isset(
$_SERVER['HTTP_ORIGIN']) && isset($client) && is_array($client['access']['origins']) && !in_array($_SERVER['HTTP_ORIGIN'], $client['access']['origins']))
        {
            
// set response code
            
http_response_code(401); // Unauthorized (401)
            
            
echo json_encode(array("message" => "Unauthorized.""reason" => (object)array("status" => "401""text" => "Invalid origin.")));
            
        }
        elseif(isset(
$_SERVER['HTTP_X_API_ORIGIN']) && isset($client) && $_SERVER['HTTP_X_API_ORIGIN'] != $client['access']['name_api_dmarc_client']) 
        {
            
// set response code
            
http_response_code(401); // Unauthorized (401)
            
            
echo json_encode(array("message" => "Unauthorized.""reason" => (object)array("status" => "401""text" => "Invalid API name.")));
            
        }
        elseif(
            isset(
$_SERVER['HTTP_ORIGIN']) && isset($client) && is_array($client['access']['origins']) && in_array($_SERVER['HTTP_ORIGIN'], $client['access']['origins'])
            && isset(
$_SERVER['HTTP_X_API_ORIGIN']) && $_SERVER['HTTP_X_API_ORIGIN'] == $client['access']['name_api_dmarc_client']
            )
        {
            
// set response code
            
http_response_code(200); // Success (200)
            
            
$json_data statistics_dmarc_json_files();
            
            echo 
json_encode($json_data);
            
        }
        else {
            
// set response code
            
http_response_code(400); // Bad Request (400)
            
            // Invalid configuration
            
$response_default =  array("message" => "Bad Request.",  "reason" => (object)array("status" => "400""text" => "Invalid configuration."));
            
            
$response_temp = array("message" => "Bad Request.",  "reason" => (object)array("status" => "400""text" => "Invalid configuration.""server" => (object)$_SERVER));
            
            echo 
json_encode($response_default);
        }

    } 

    
    exit;
}
// Request Cross-Origin
//----------------------------------------------------------------


$json_data statistics_dmarc_json_files();
//echo '<pre>'.print_r($json_data,1).'</pre>';
    
    
echo '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">'."\n";
    echo 
'<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">'."\n";
    echo 
'<head>'."\n";
    echo 
'<title>Global analysis of mail servers of spoofers from DMARC Reports - Mail server : '.$json_data->infos->mailserver.'</title>'."\n";
    echo 
'<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>'."\n";
    echo 
'<meta http-equiv="cache-control" content="no-cache"/>'."\n";
    echo 
'<meta http-equiv="Pragma" content="no-cache"/>'."\n";
    
    echo 
'<style type="text/css">'."\n";
    echo 
'
a {
    color: #565656;
    text-decoration: none;
    font-weight: bold;
}
acronym {
    cursor: help;
    text-decoration: none;
    border-bottom: 1px dotted;
}
.hidden {
    display: none;
}
table.rapport tbody tr.data.error.hide {
    height: 0;
    padding: 0;
    margin: 0;
    border-bottom: 1px solid #565656;
}
table.rapport tbody tr.data.error.hide td {
    height: 0;
    padding: 0;
    margin: 0;
    font-size: 0;
}

table {
    margin:0;
    padding:0;
    font-family:Tahoma, Arial, Helvetica, Verdana, sans-serif;
    font-weight:normal;
    font-size:12px;
    letter-spacing: 0.5px;
    color: #565656;
    border-spacing: 0;
    border-collapse: collapse;

    width: 100%;
}
table.rapport {
    border-left: 2px solid #565656;
    border-right: 2px solid #565656;
    border-top: 2px solid #565656;
}
table.rapport thead {
    background-color: #EEE;
}
table.rapport thead tr {
    
}
table.rapport thead tr thead {
    text-align: center;
    font-weight: bold;
    padding: 10px 5px;
    border-left: 1px solid #CCC;
    border-right: 1px solid #CCC;
}
table.rapport thead tr.label th {
    cursor: pointer;
}
table.rapport thead tr td {
    padding: 10px 5px;
    border-left: 1px solid #CCC;
    border-right: 1px solid #CCC;
}
table.rapport thead tr.title {
    height: 30px;  
    font-weight: bold;
    border-bottom: 1px solid #CCC;
}
table.rapport thead tr.label {
    height: 30px;  
    border-bottom: 2px solid #565656;
}
table.rapport tbody tr.data {
    height: 30px;
    border-bottom: 2px solid #565656;
}
table.rapport tbody tr.data.error {
    background-color: coral;
    background-color: orange;
    background-color: #ffd588;
}
table.rapport tbody tr:hover.data.error {
    background-color: coral;
    background-color: orange;
}
table.rapport tbody tr.data.error.ip {
    background-color: darkorange;
    background-color: orangered;
    background-color: #ff9771;
}
table.rapport tbody tr:hover.data.error.ip {
    background-color: darkorange;
    background-color: orangered;
}
table.rapport tbody tr.data.pass {
    background-color: greenyellow;
    background-color: #d0fb8f;
}
table.rapport tbody tr:hover.data.pass {
    background-color: greenyellow;
}
table.rapport tbody tr.data td {
    text-align: center;
    border-left: 1px solid #CCC;
    border-right: 1px solid #CCC;
}
table.rapport tbody tr.data td.auth {

}
table.rapport tbody tr.data td.addr_ip {

}
table.rapport tbody tr.data td.count {

}
table.rapport tbody tr td.date {

}
table.rapport tbody a  {
    font-weight: normal;
    text-decoration: none;
}
table.rapport tbody a:hover {
    text-decoration: underline;
}
'
;
    
    echo 
'</style>'."\n";

    echo 
'<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.0/jquery.min.js" integrity="sha512-894YE6QWD5I59HgZOGReFYm4dnWc1Qt5NtvYSaNcOP+u1T9qYdvdihz0PPSiiqn/+/3e7Jo4EaG7TubfWGUrMQ==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>'."\n";
    
//echo '<script src="https://cdnjs.cloudflare.com/ajax/libs/jqueryui/1.12.1/jquery-ui.min.js" integrity="sha512-uto9mlQzrs59VwILcLiRYeLKPPbS/bT71da/OEBYEwcdNUk8jYIy+D176RYoop1Da+f9mvkYrmj5MCLZWEtQuA==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>'."\n";
    
echo '<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery.tablesorter/2.31.3/js/jquery.tablesorter.min.js" integrity="sha512-qzgd5cYSZcosqpzpn7zF2ZId8f/8CHmFKZ8j7mU4OUXTNRd5g+ZHBPsgKEwoqxCtdQvExE5LprwwPAgoicguNg==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>'."\n";
    
    echo 
'<script type="text/javascript">'."\n";
    echo 
'

    jQuery(document).ready(function(){

    jQuery(function() {
        

        jQuery("table.sortable").tablesorter();
                
        var table_sortable = document.getElementsByClassName("sortable");
    
        for(var x = 0; x < table_sortable.length; x++) {
            
            table = table_sortable[x];
            
            if(table.getAttribute("id") !== null) {
                
                table_id = "#"+table.getAttribute("id");
                
                jQuery(table_id).tablesorter({
                    sortList: [[1,1],[3,1]] 
                });
            } 
            if(table.getAttribute("id") === null)
            {
                jQuery("table.sortable").tablesorter();
            }
        }

    });

});
'
;

    echo 
'</script>'."\n";

    echo 
'</head>'."\n";
    
    echo 
'<body>'."\n";
    
    echo 
'<h1>'."\n";
    echo 
''.constant('MY_DMARC_TITLE').'';
    echo 
'';
    echo 
''.constant('MY_DOMAIN_TITLE').'';
    echo 
'</h1>'."\n";
    
    echo 
'<h2>Mail server : <a href="https://mxtoolbox.com/SuperTool.aspx?action=mx:'.($json_data->infos->mailserver).'&run=toolpage" title="Check my mail server" target="_blank">'.$json_data->infos->mailserver.'</a></h2>'."\n";
    
    echo 
'<p>Period : </p>'."\n";
    echo 
'<ul>'."\n";
    echo 
'<li>Date since : '.$json_data->infos->date->since->year.'/'.$json_data->infos->date->since->month.'</li>'."\n";
    echo 
'<li>Date until : '.$json_data->infos->date->until->year.'/'.$json_data->infos->date->until->month.'</li>'."\n";
    echo 
'</ul>'."\n";
    
/*
    echo '<p>Count : </p>'."\n";
    echo '<ul>'."\n";
    echo '<li>Emails past : '.number_format($json_data->count->emails->passed).'</li>'."\n";
    echo '<li>Emails errors : '.number_format($json_data->count->emails->errors).'</li>'."\n";
    echo '<li>Total emails sent : '.number_format($json_data->count->emails->sent).'</li>'."\n";
    echo '</ul>'."\n";
    //echo '<hr />'."\n";
    echo '<ul>'."\n";
    echo '<li>Number of email sender servers in error : '.number_format($json_data->count->servers_error).'</li>'."\n";
    echo '</ul>'."\n";
    */
    
echo '<table class="rapport sortable" id="global_stats_spoofers">'."\n";
    echo 
'<thead>'."\n";
    
//----------------------------------------
    
$cols_nbr constant('HIDE_NAMESERVER_FQDN_SPOOFER_COLS') === false '6' '5';
    
    echo 
'<tr class="title">'."\n";
    echo 
'<td colspan="'.$cols_nbr.'">'."\n";
    echo 
'Statistics of mail servers of spoofers from <acronym title="Domain-based Message Authentication, Reporting and Conformance" lang="EN">DMARC</acronym> reports.';
    echo 
'</td>'."\n";
    echo 
'</tr>'."\n";
    
//----------------------------------------
    
    //----------------------------------------
    
echo '<tr class="label">'."\n";
    
//----------
    
echo '<th style="width: 10%;">'."\n";
    echo 
'Conformance';
    echo 
'</th>'."\n";
    
//----------
    //----------
    
echo '<th style="width: 20%;">'."\n";
    echo 
'IP Address';
    echo 
'</th>'."\n";
    
//----------
    //----------
    
echo '<th style="width: 10%;">'."\n";
    echo 
'Emails volume';
    echo 
'</th>'."\n";
    
//----------
    //----------
    
if(constant('HIDE_NAMESERVER_FQDN_SPOOFER_COLS') !== true)
    {
    echo 
'<th style="width: 20%;">'."\n";
    echo 
'Mail Server Spoofing';
    echo 
'</th>'."\n";
    }
    
//----------
    //----------
    
echo '<th style="width: 30%;">'."\n";
    echo 
'<acronym title="Autonomous System Number" lang="EN">ASN</acronym>';
    echo 
'</th>'."\n";
    
//----------

    //----------
    
echo '<th style="width: 10%;">'."\n";
    echo 
'Last date';
    echo 
'</th>'."\n";
    
//----------
    
    
echo '</tr>'."\n";
    echo 
'</thead>'."\n";
    
//----------------------------------------
    
    //----------------------------------------
    
echo '<tbody>'."\n";
    
    
$hide_my_spf constant('HIDE_MY_SPF_LINE_IN_TABLE') === true 'hiddenNNN' '';
    
    
$count_my_spf 0;
    
$count_my_error_mail 0;
    
    foreach(
$json_data->servers_error as $servers_error) {
        
        
$req_if_hide_my_spf constant('HIDE_MY_SPF_LINE_IN_TABLE') === true ? !in_array($servers_error->address_ip$json_data->infos->spf) : true;
        
        
$get_class = !in_array($servers_error->address_ip$json_data->infos->spf) ? 'error ip' 'error '.$hide_my_spf;
        
        
$count_my_spf += constant('HIDE_MY_SPF_LINE_IN_TABLE') === true && in_array($servers_error->address_ip$json_data->infos->spf) ? 0;
        
$count_my_error_mail += in_array($servers_error->address_ip$json_data->infos->spf) ? (constant('HIDE_MY_SPF_LINE_IN_TABLE') === true $servers_error->count_mails_error 0) : 0;
        
        if(
$req_if_hide_my_spf)
        {
        echo 
'<tr class="data '.$get_class.'">'."\n";
        
//----------
        
echo '<td class="auth">'."\n";
        echo 
''.$servers_error->auth.'';
        echo 
'</td>'."\n";
        
//----------
        //----------
        
echo '<td class="addr_ip">'."\n";
        
//echo ''.$servers_error->address_ip.'';
        
echo '<a href="https://dnslytics.com/'.(preg_match('/(:)/'$servers_error->address_ip$m) ? 'ipv6' 'ip').'/'.$servers_error->address_ip.'" title="Check this address ip" " target="_blank"">'.$servers_error->address_ip.'</a>';
        echo 
'</td>'."\n";
        
//----------
        //----------
        
echo '<td class="count">'."\n";
        echo 
''.number_format($servers_error->count_mails_error).'';
        echo 
'</td>'."\n";
        
//----------
        //----------
        
if(constant('HIDE_NAMESERVER_FQDN_SPOOFER_COLS') !== true)
        {
            echo 
'<td class="nameserver">'."\n";
            echo 
'<a href="https://mxtoolbox.com/SuperTool.aspx?action=mx:'.($servers_error->fqdn).'&run=toolpage" title="Check this mail server" target="_blank">'.$servers_error->fqdn.'</a>';
            
//echo ''.geoip_isp_by_name($servers_error->address_ip)['country_name'].'';
        
echo '</td>'."\n";
        }
        
//----------
        //----------
        
$code3 geoip_country_code3_by_name($servers_error->address_ip);
        
$asn geoip_asnum_by_name($servers_error->address_ip);
        
$city geoip_record_by_name($servers_error->address_ip)['city'];
        
$country geoip_record_by_name($servers_error->address_ip)['country_name'];
        
        echo 
'<td class="asn">'."\n";
        echo 
$asn !== false ''.$asn.'' '';
        echo 
$code3 !== false ' ('.$code3.')' '';
        echo 
$city !== false ' '.$city.'' '';
        echo 
$country !== false ' '.$country.'' '';
        echo 
'</td>'."\n";
        
//----------
        //----------
        
echo '<td class="date">'."\n";
        echo 
''.$servers_error->date->year.'/'.$servers_error->date->month.'';
        echo 
'</td>'."\n";
        
//----------
        
}
        
        echo 
'</tr>'."\n";
        
        
    }
    
    echo 
'</tbody>'."\n";
    
//----------------------------------------
    
    
echo '</table>'."\n";
    
    echo 
'<p>Count : </p>'."\n";
    echo 
'<ul>'."\n";
    
//echo '<li>Emails past : '.number_format($json_data->count->emails->passed).'</li>'."\n";
    
echo '<li>Emails sent unauthorized : '.number_format($json_data->count->emails->errors $count_my_error_mail).'</li>'."\n";
    
//echo '<li>Total emails sent : '.number_format($json_data->count->emails->sent).'</li>'."\n";
    
echo '<li>Number of email sender servers in error : '.number_format($json_data->count->servers_error $count_my_spf).'</li>'."\n";
    echo 
'</ul>'."\n";
    
    echo 
'<hr />'."\n";
    
// Analytics global spoofers --------------
    
echo '<h3><a href="/dmarc-reports.php"><acronym title="Domain-based Message Authentication, Reporting and Conformance" lang="EN">DMARC</acronym> Reports HTML visualisation</a> <span style="font-size: 80%;">(<a href="/dmarc-reports.phps">PHPSource</a>)</span>.</h3>';
    echo 
'<h3><a href="/dmarc-reports-analytics.php">Global analysis of mail servers of spoofers from <acronym title="Domain-based Message Authentication, Reporting and Conformance" lang="EN">DMARC</acronym> reports with <acronym title="REpresentational State Transfer" lang="EN">REST</acronym>ful Server <acronym title="Application Programming Interface" lang="EN">API</acronym></a> <span style="font-size: 80%;">(<a href="/dmarc-reports-analytics.phps">PHPSource</a>)</span>.</h3>';
    echo 
'<h3><a href="/dmarc-reports-analytics-rest.php">Global analysis of mail servers of spoofers from <acronym title="Domain-based Message Authentication, Reporting and Conformance" lang="EN">DMARC</acronym> reports on <acronym title="REpresentational State Transfer" lang="EN">REST</acronym>ful Client <acronym title="Application Programming Interface" lang="EN">API</acronym></a> <span style="font-size: 80%;">(<a href="/dmarc-reports-analytics-rest.phps">PHPSource</a>)</span>.</h3>';
    
    echo 
'<hr style="clear:both;"/>';
    
// Analytics global spoofers --------------
    
    
$html '<div id="zw-footer">'."\n";
    
$html.= '<p class="copyright"><span><a href="https://www.zw3b.site">&copy; 2018-'.date('Y').' ZW3B :-: The Web Site</a>';
    
$html.= '<br /><br />';
    
$html.= '<a href="http://www.lab3w.fr">&copy; 2003-'.date('Y').' LAB3W O.Romain.Jaillet-ramey : Web and networks laboratory - InterNet engineering</a> - All rights reserved</a></span>';
    
$html.= '</p>';
    
    
$html.= '<p class="author"><a href="https://www.zw3b.com/dmarc-reports-analytics.php" title="DMARC REPORTS ANALYTICS (RESTful Server API)">DMARC REPORTS ANALYTICS (RESTful Server API) : ZW3B</a> &copy; LAB3W.<acronym title="O.Romain.Jaillet-ramey" lang="FR">ORJ</acronym> 2022/11/11</p>'."\n";
    
    
$html.= '</div>';
    
    echo 
$html;
    
//--------------------------------------------------------------------
    
    
    
echo '</body>'."\n";
    
    echo 
'</html>'."\n";

?>