Add files via upload

This commit is contained in:
LX1IQ 2025-10-21 14:15:32 +02:00 committed by GitHub
parent 7176e44386
commit 37a79a95a0
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
23 changed files with 2728 additions and 0 deletions

190
dashboard1/css/layout.css Normal file
View file

@ -0,0 +1,190 @@
body {
margin : 0px;
padding : 0px;
background-color : #D3D3D3;
font-family : calibri, verdana, arial, comic sans;
min-width : 760px;
}
h1 {
font-size : 25pt;
}
a img {
border: 0;
}
a.tip {
text-decoration : none;
}
a.tip:hover {
position : relative;
}
a.tip span {
display : none
}
a.tip:hover span {
background : #000000;
opacity : 0.8;
border : none;
border-radius : 5px 5px 5px 5px;
font-family : calibri, verdana, arial, comic sans;
font-size : 12pt;
text-decoration : none;
white-space : nowrap;
color : #FFFFFF;
padding : 6px 6px 6px 6px;
margin : 10px;
display : block;
z-index : 50;
position : absolute;
top : 10px;
}
#top {
height : 115px;
background-color : #FFFFFF;
width : 100%;
background-image : url('../img/dvc.jpg');
background-repeat : no-repeat;
background-position : 98.5%;
position : absolute;
left : 0px;
top : 0px;
min-width : 760px;
}
#menu {
margin-top : 5px;
height : 34px;
float : left;
}
#menubar {
height : 40px;
width : 100%;
background-color : #FEC456;
position : absolute;
left : 0px;
top : 115px;
min-width : 760px;
}
#content {
width : 100%;
position : absolute;
left : 0px;
top : 175px;
}
.menulink {
font-size : 14pt;
text-decoration : none;
white-space : nowrap;
border : 1px #000000 solid;
padding-left : 10px;
padding-top : 3px;
padding-bottom : 3px;
padding-right : 10px;
margin-left : 10px;
background-color : #FFFFC6;
color : #000000;
}
.menulinkactive {
font-size : 14pt;
text-decoration : none;
white-space : nowrap;
border : 1px #000000 solid;
padding-left : 10px;
padding-top : 3px;
padding-bottom : 3px;
padding-right : 10px;
margin-left : 10px;
background-color : #87dcfc;
color : #000000;
}
.pl {
font-size : 12pt;
text-decoration : none;
color : #000000;
}
.listingtable {
margin-top : 10px;
border : 1px #C1DAD7 solid;
font-size : 12pt;
}
.listingtable th {
height : 35px;
text-align : center;
background-color : #D5EBF0;
background-image : -webkit-gradient(
linear,
left top,
left bottom,
color-stop(0, rgb(201, 231, 233)),
color-stop(0.8, rgb(220, 237, 244))
);
background-image: -o-linear-gradient(bottom, rgb(201, 231, 233) 0%, rgb(220, 237, 244) 80%);
background-image: -moz-linear-gradient(bottom, rgb(201, 231, 233) 0%, rgb(220, 237, 244) 80%);
background-image: -webkit-linear-gradient(bottom, rgb(201, 231, 233) 0%, rgb(220, 237, 244) 80%);
background-image: -ms-linear-gradient(bottom, rgb(201, 231, 233) 0%, rgb(220, 237, 244) 80%);
background-image: linear-gradient(to bottom, rgb(201, 231, 233) 0%, rgb(220, 237, 244) 80%);
}
.listingtable td {
padding-left : 5px;
}
.listinglink {
font-size : 12pt;
text-decoration : underline;
color : #60A1DE;
}
.error {
font-size : 12pt;
text-decoration : none,
font-weight : bold;
color : #FF0000;
background-color : #FFFFFF;
width : 90%;
padding : 15px;
margin : 5px;
}
.FilterField {
font-size : 10pt;
text-decoration : none,
color : #000000;
background-color : #FFFFFF;
width : 150px;
height : 20px;
padding-left : 5px;
padding-top : 3px;
border : 1px #60A1DE solid;
}
.FilterSubmit {
font-size : 10pt;
text-decoration : none,
color : #000000;
background-color : #FFFFFF;
height : 26px;
width : 60px;
padding-left : 5px;
padding-top : 3px;
border : 1px #60A1DE solid;
}
.smalllink {
font-size : 12pt;
text-decoration : none;
color : #0E0789;
}

BIN
dashboard1/favicon.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

227
dashboard1/index.php Normal file
View file

@ -0,0 +1,227 @@
<?php
// Secure session configuration
ini_set('session.cookie_httponly', 1);
ini_set('session.cookie_samesite', 'Strict');
if (isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] === 'on') {
ini_set('session.cookie_secure', 1);
}
session_start();
// Security headers
header("X-Content-Type-Options: nosniff");
header("X-Frame-Options: SAMEORIGIN");
header("X-XSS-Protection: 1; mode=block");
header("Referrer-Policy: strict-origin-when-cross-origin");
if (file_exists("./pgs/functions.php")) { require_once("./pgs/functions.php"); } else { die("functions.php does not exist."); }
if (file_exists("./pgs/config.inc.php")) { require_once("./pgs/config.inc.php"); } else { die("config.inc.php does not exist."); }
if (!class_exists('ParseXML')) require_once("./pgs/class.parsexml.php");
if (!class_exists('Node')) require_once("./pgs/class.node.php");
if (!class_exists('xReflector')) require_once("./pgs/class.reflector.php");
if (!class_exists('Station')) require_once("./pgs/class.station.php");
if (!class_exists('Peer')) require_once("./pgs/class.peer.php");
if (!class_exists('Interlink')) require_once("./pgs/class.interlink.php");
// Validate 'show' parameter
$allowed_pages = ['users', 'repeaters', 'liveircddb', 'peers', 'modules', 'reflectors', 'traffic'];
if (!isset($_GET['show'])) {
$_GET['show'] = '';
} elseif (!in_array($_GET['show'], $allowed_pages, true)) {
$_GET['show'] = '';
}
// Validate 'do' parameter for filter resets
if (isset($_GET['do']) && $_GET['do'] !== 'resetfilter') {
unset($_GET['do']);
}
// Validate 'callhome' parameter
if (isset($_GET['callhome'])) {
$_GET['callhome'] = filter_var($_GET['callhome'], FILTER_VALIDATE_BOOLEAN, FILTER_NULL_ON_FAILURE);
if ($_GET['callhome'] === null) {
unset($_GET['callhome']);
}
}
$Reflector = new xReflector();
$Reflector->SetFlagFile("./pgs/country.csv");
$Reflector->SetPIDFile($Service['PIDFile']);
$Reflector->SetXMLFile($Service['XMLFile']);
$Reflector->LoadXML();
if ($CallingHome['Active']) {
$CallHomeNow = false;
$LastSync = 0;
$Hash = "";
if (!file_exists($CallingHome['HashFile'])) {
$Ressource = fopen($CallingHome['HashFile'], "w+");
if ($Ressource) {
$Hash = CreateCode(16);
@fwrite($Ressource, "<?php\n");
@fwrite($Ressource, "\n".'$Hash = "'.$Hash.'";');
@fwrite($Ressource, "\n\n".'?>');
@fflush($Ressource);
@fclose($Ressource);
@chmod($HashFile, 0777);
}
}
else {
require_once($CallingHome['HashFile']);
}
if (@file_exists($CallingHome['LastCallHomefile'])) {
if (@is_readable($CallingHome['LastCallHomefile'])) {
$tmp = @file($CallingHome['LastCallHomefile']);
if (isset($tmp[0])) {
$LastSync = $tmp[0];
}
unset($tmp);
}
}
if ($LastSync < (time() - $CallingHome['PushDelay'])) {
$CallHomeNow = true;
$Ressource = @fopen($CallingHome['LastCallHomefile'], "w+");
if ($Ressource) {
@fwrite($Ressource, time());
@fflush($Ressource);
@fclose($Ressource);
@chmod($HashFile, 0777);
}
}
if ($CallHomeNow || isset($_GET['callhome'])) {
$Reflector->SetCallingHome($CallingHome, $Hash);
$Reflector->ReadInterlinkFile();
$Reflector->PrepareInterlinkXML();
$Reflector->PrepareReflectorXML();
$Reflector->CallHome();
}
}
else {
$Hash = "";
}
?><!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
<meta name="description" content="<?php echo sanitize_attribute($PageOptions['MetaDescription']); ?>" />
<meta name="keywords" content="<?php echo sanitize_attribute($PageOptions['MetaKeywords']); ?>" />
<meta name="author" content="<?php echo sanitize_attribute($PageOptions['MetaAuthor']); ?>" />
<meta name="revisit" content="<?php echo sanitize_attribute($PageOptions['MetaRevisit']); ?>" />
<meta name="robots" content="<?php echo sanitize_attribute($PageOptions['MetaRobots']); ?>" />
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title><?php echo sanitize_output($Reflector->GetReflectorName()); ?> Reflector Dashboard</title>
<link rel="stylesheet" type="text/css" href="./css/layout.css">
<link rel="icon" href="./favicon.ico" type="image/vnd.microsoft.icon"><?php
if ($PageOptions['PageRefreshActive']) {
echo '
<script src="./js/jquery-1.12.4.min.js"></script>
<script>
var PageRefresh;
function ReloadPage() {
$.get("./index.php'.((!empty($_GET['show'])) ? '?show='.urlencode($_GET['show']) : '').'", function(data) {
var BodyStart = data.indexOf("<bo"+"dy");
var BodyEnd = data.indexOf("</bo"+"dy>");
if ((BodyStart >= 0) && (BodyEnd > BodyStart)) {
BodyStart = data.indexOf(">", BodyStart)+1;
$("body").html(data.substring(BodyStart, BodyEnd));
}
})
.always(function() {
PageRefresh = setTimeout(ReloadPage, '.$PageOptions['PageRefreshDelay'].');
});
}';
if (!isset($_GET['show']) || (($_GET['show'] != 'liveircddb') && ($_GET['show'] != 'reflectors') && ($_GET['show'] != 'interlinks'))) {
echo '
PageRefresh = setTimeout(ReloadPage, '.$PageOptions['PageRefreshDelay'].');';
}
echo '
function SuspendPageRefresh() {
clearTimeout(PageRefresh);
}
</script>';
}
if (!isset($_GET['show'])) $_GET['show'] = "";
?>
</head>
<body>
<?php if (file_exists("./tracking.php")) { include_once("tracking.php"); }?>
<div id="top"><img src="./img/header.jpg" alt="XLX Multiprotocol Gateway Reflector" style="margin-top:15px;" />
<br />&nbsp;&nbsp;&nbsp;<?php echo sanitize_output($Reflector->GetReflectorName()); ?>&nbsp;v<?php echo sanitize_output($Reflector->GetVersion()); ?>&nbsp;-&nbsp;Dashboard v<?php echo sanitize_output($PageOptions['DashboardVersion']); ?>&nbsp;<?php echo sanitize_output($PageOptions['CustomTXT']); ?>&nbsp;&nbsp;/&nbsp;&nbsp;Service uptime: <span id="suptime"><?php echo FormatSeconds($Reflector->GetServiceUptime()); ?></span></div>
<div id="menubar">
<div id="menu">
<table border="0">
<tr>
<td><a href="./index.php" class="menulink<?php if ($_GET['show'] == '') { echo 'active'; } ?>">Users / Modules</a></td>
<td><a href="./index.php?show=repeaters" class="menulink<?php if ($_GET['show'] == 'repeaters') { echo 'active'; } ?>">Repeaters / Nodes (<?php echo intval($Reflector->NodeCount()); ?>)</a></td>
<td><a href="./index.php?show=peers" class="menulink<?php if ($_GET['show'] == 'peers') { echo 'active'; } ?>">Peers (<?php echo intval($Reflector->PeerCount()); ?>)</a></td>
<td><a href="./index.php?show=modules" class="menulink<?php if ($_GET['show'] == 'modules') { echo 'active'; } ?>">Modules list</a></td>
<td><a href="./index.php?show=reflectors" class="menulink<?php if ($_GET['show'] == 'reflectors') { echo 'active'; } ?>">Reflectors list</a></td>
<?php
if ($PageOptions['Traffic']['Show']) {
echo '
<td><a href="./index.php?show=traffic" class="menulink';
if ($_GET['show'] == 'traffic') { echo 'active'; }
echo '">Traffic statistics</a></td>';
}
if ($PageOptions['IRCDDB']['Show']) {
echo '
<td><a href="./index.php?show=liveircddb" class="menulink';
if ($_GET['show'] == 'liveircddb') { echo 'active'; }
echo '">D-Star live</a></td>';
}
?>
</tr>
</table>
</div>
</div>
<div id="content" align="center">
<?php
if ($CallingHome['Active']) {
if (!is_readable($CallingHome['HashFile']) && (!is_writeable($CallingHome['HashFile']))) {
echo '
<div class="error">
your private hash in '.sanitize_output($CallingHome['HashFile']).' could not be created, please check your config file and the permissions for the defined folder.
</div>';
}
}
switch ($_GET['show']) {
case 'users' : require_once("./pgs/users.php"); break;
case 'repeaters' : require_once("./pgs/repeaters.php"); break;
case 'liveircddb' : require_once("./pgs/liveircddb.php"); break;
case 'peers' : require_once("./pgs/peers.php"); break;
case 'modules' : require_once("./pgs/modules.php"); break;
case 'reflectors' : require_once("./pgs/reflectors.php"); break;
case 'traffic' : require_once("./pgs/traffic.php"); break;
default : require_once("./pgs/users.php");
}
?>
<div style="width:100%;text-align:center;margin-top:50px;"><a href="mailto:<?php echo sanitize_attribute($PageOptions['ContactEmail']); ?>" style="font-family:verdana;color:#000000;font-size:12pt;text-decoration:none;"><?php echo sanitize_output($PageOptions['ContactEmail']); ?></a></div>
</div>
</body>
</html>

5
dashboard1/js/jquery-1.12.4.min.js vendored Normal file

File diff suppressed because one or more lines are too long

View file

81
dashboard1/log/xlxlog.php Normal file
View file

@ -0,0 +1,81 @@
<?php
session_start();
if (isset($_POST['password'])) {
$_SESSION['password'] = $_POST['password'];
}
if (isset($_SESSION['password'])) {
if ($_SESSION['password'] != "-D-Star+") {
echo '
<form name="frmpass" action="./xlxlog.php" method="post">
<input type="password" name="password" />
<input type="submit" />
</form>';
die();
}
}
else {
echo '
<form name="frmpass" action="./xlxlog.php" method="post">
<input type="password" name="password" />
<input type="submit" />
</form>';
die();
}
?>
<!DOCTYPE html PUBLIC"-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>XLX Live Log</title>
<script>
function ReloadPage() {
document.location.href = "./xlxlog.php";
}
setTimeout(ReloadPage, 1000);
</script>
</head>
<body>
<pre>
<?php
$a = array();
$handle = fopen("/var/log/messages","r");
if ($handle) {
while(!feof($handle)) {
$a[] = fgets($handle, 1024);
}
fclose($handle);
}
$a = array_reverse($a);
$max = 65;
if (count($a) < 65) $max = count($a);
for ($i=0;$i<$max;$i++) {
echo $a[$i];
}
?>
</pre>
</body>
</html>

View file

@ -0,0 +1,66 @@
<?php
class Interlink {
private $ReflectorName;
private $ReflectorAddress;
private $Modules;
public function __construct() {
$this->ReflectorName = null;
$this->ReflectorAddress = null;
$this->Modules = null;
}
public function SetName($RefName) {
$RefName = trim($RefName);
// Validate reflector name format (XLX + 3 alphanumeric)
if (preg_match('/^[A-Z0-9]{3,10}$/i', $RefName)) {
$this->ReflectorName = strtoupper($RefName);
}
}
public function SetAddress($RefAdd) {
$RefAdd = trim($RefAdd);
// Validate it's a valid hostname or IP
if (filter_var($RefAdd, FILTER_VALIDATE_IP) ||
filter_var($RefAdd, FILTER_VALIDATE_DOMAIN, FILTER_FLAG_HOSTNAME)) {
$this->ReflectorAddress = $RefAdd;
}
}
public function GetName() { return $this->ReflectorName; }
public function GetAddress() { return $this->ReflectorAddress; }
public function GetModules() { return $this->Modules; }
public function AddModule($Module) {
$Module = trim(strtoupper($Module));
if (strlen($Module) != 1) return false;
if (!preg_match('/^[A-Z]$/', $Module)) return false; // Only A-Z
if (strpos($this->Modules, $Module) === false) {
$this->Modules .= $Module;
}
return true;
}
public function RemoveModule($Module) {
$Module = trim(strtoupper($Module));
if (strlen($Module) != 1) return false;
if (!preg_match('/^[A-Z]$/', $Module)) return false; // Only A-Z
if (strpos($this->Modules, $Module) !== false) {
$this->Modules = str_replace($Module, '', $this->Modules);
}
return true;
}
public function HasModuleEnabled($Module) {
$Module = trim(strtoupper($Module));
if (strlen($Module) != 1 || !preg_match('/^[A-Z]$/', $Module)) {
return false;
}
return (strpos($this->Modules, $Module) !== false);
}
}

View file

@ -0,0 +1,70 @@
<?php
class Node {
private $Callsign;
private $IP;
private $LinkedModule;
private $Protocol;
private $ConnectTime;
private $LastHeardTime;
private $Suffix;
private $Prefix;
private $RandomID;
public function __construct($Callsign, $IP, $LinkedModule, $Protocol, $ConnectTime, $LastHeardTime, $RandomID) {
// Validate and sanitize IP
$IP = trim($IP);
$this->IP = filter_var($IP, FILTER_VALIDATE_IP) ? $IP : '0.0.0.0';
// Validate protocol
$Protocol = trim($Protocol);
$allowed_protocols = ['DPlus', 'DExtra', 'DCS', 'DMR', 'YSF', 'DEXTRA', 'DPLUS', 'DMRMmdvm'];
$this->Protocol = in_array($Protocol, $allowed_protocols, true) ? $Protocol : 'Unknown';
$this->ConnectTime = ParseTime($ConnectTime);
$this->LastHeardTime = ParseTime($LastHeardTime);
// Sanitize callsign (remove excessive spaces, validate format)
$Callsign = trim(preg_replace('/\s+/', ' ', $Callsign));
$this->FullCallsign = str_replace(" ", "-", $Callsign);
if (strpos($Callsign, " ") !== false) {
$this->Callsign = trim(substr($Callsign, 0, strpos($Callsign, " ")));
$this->Suffix = trim(substr($Callsign, strpos($Callsign, " ")));
$this->Prefix = strtoupper(trim(substr($Callsign, 0, 3)));
}
else {
$this->Callsign = trim($Callsign);
$this->Suffix = "";
$this->Prefix = "";
}
// Validate callsign format (basic check)
if (!preg_match('/^[A-Z0-9]{1,10}$/i', $this->Callsign)) {
$this->Callsign = 'INVALID';
}
// Validate LinkedModule (single letter A-Z)
$LinkedModule = trim(strtoupper($LinkedModule));
$this->LinkedModule = preg_match('/^[A-Z]$/', $LinkedModule) ? $LinkedModule : '';
$this->RandomID = $RandomID;
}
public function GetFullCallsign() { return $this->FullCallsign; }
public function GetCallsign() { return $this->Callsign; }
public function GetIP() { return $this->IP; }
public function GetLinkedModule() { return $this->LinkedModule; }
public function GetProtocol() { return $this->Protocol; }
public function GetConnectTime() { return $this->ConnectTime; }
public function GetLastHeardTime() { return $this->LastHeardTime; }
public function GetSuffix() { return $this->Suffix; }
public function GetPrefix() { return $this->Prefix; }
public function GetRandomID() { return $this->RandomID; }
}
?>

View file

@ -0,0 +1,39 @@
<?php
class ParseXML {
public function __construct() {
return true;
}
public function GetElement($InputString, $ElementName) {
// Sanitize element name to prevent XML injection
$ElementName = preg_replace('/[^a-zA-Z0-9_\-\s]/', '', $ElementName);
if (strpos($InputString, "<".$ElementName.">") === false) return false;
if (strpos($InputString, "</".$ElementName.">") === false) return false;
$Element = substr($InputString, strpos($InputString, "<".$ElementName.">")+strlen($ElementName)+2, strpos($InputString, "</".$ElementName.">")-strpos($InputString, "<".$ElementName.">")-strlen($ElementName)-2);
// Return raw content - sanitization happens at output time
return $Element;
}
public function GetAllElements($InputString, $ElementName) {
// Sanitize element name to prevent XML injection
$ElementName = preg_replace('/[^a-zA-Z0-9_\-\s]/', '', $ElementName);
$Elements = array();
while (strpos($InputString, $ElementName) !== false) {
$element = $this->GetElement($InputString, $ElementName);
if ($element !== false) {
$Elements[] = $element;
}
$InputString = substr($InputString, strpos($InputString, "</".$ElementName.">")+strlen($ElementName)+3, strlen($InputString));
}
return $Elements;
}
}
?>

View file

@ -0,0 +1,49 @@
<?php
class Peer {
private $Callsign;
private $IP;
private $LinkedModule;
private $Protocol;
private $ConnectTime;
private $LastHeardTime;
public function __construct($Callsign, $IP, $LinkedModule, $Protocol, $ConnectTime, $LastHeardTime) {
// Validate and sanitize IP
$IP = trim($IP);
$this->IP = filter_var($IP, FILTER_VALIDATE_IP) ? $IP : '0.0.0.0';
// Validate protocol
$Protocol = trim($Protocol);
$allowed_protocols = ['DPlus', 'DExtra', 'DCS', 'DMR', 'YSF', 'DEXTRA', 'DPLUS', 'XLX'];
$this->Protocol = in_array($Protocol, $allowed_protocols, true) ? $Protocol : 'Unknown';
$this->ConnectTime = ParseTime($ConnectTime);
$this->LastHeardTime = ParseTime($LastHeardTime);
// Sanitize and validate callsign
$Callsign = trim($Callsign);
if (preg_match('/^[A-Z0-9]{3,10}$/i', $Callsign)) {
$this->Callsign = strtoupper($Callsign);
} else {
$this->Callsign = 'INVALID';
}
// Validate LinkedModule (single letter A-Z)
$LinkedModule = trim(strtoupper($LinkedModule));
$this->LinkedModule = preg_match('/^[A-Z]$/', $LinkedModule) ? $LinkedModule : '';
}
public function GetCallsign() { return $this->Callsign; }
public function GetIP() { return $this->IP; }
public function GetLinkedModule() { return $this->LinkedModule; }
public function GetProtocol() { return $this->Protocol; }
public function GetConnectTime() { return $this->ConnectTime; }
public function GetLastHeardTime() { return $this->LastHeardTime; }
}
?>

View file

@ -0,0 +1,556 @@
<?php
class xReflector {
public $Nodes = null;
public $Stations = null;
public $Peers = null;
private $Flagarray = null;
private $Flagarray_DXCC = null;
private $Flagfile = null;
private $CallingHomeActive = null;
private $CallingHomeHash = null;
private $CallingHomeDashboardURL = null;
private $CallingHomeServerURL = null;
private $ReflectorName = null;
private $ServiceUptime = null;
private $ProcessIDFile = null;
private $XMLContent = null;
private $XMLFile = null;
private $ServiceName = null;
private $Version = null;
private $CallingHomeCountry = null;
private $CallingHomeComment = null;
private $CallingHomeOverrideIP = null;
private $Transferinterlink = null;
private $Interlinkfile = null;
public $Interlinks = null;
private $InterlinkXML = null;
private $ReflectorXML = null;
public function __construct() {
$this->Nodes = array();
$this->Stations = array();
$this->Peers = array();
$this->Interlinks = array();
$this->Transferinterlink = false;
}
public function LoadXML() {
if ($this->XMLFile != null) {
$handle = fopen($this->XMLFile, 'r');
$this->XMLContent = fread($handle, filesize($this->XMLFile));
fclose($handle);
# XLX alphanumeric naming...
$this->ServiceName = substr($this->XMLContent, strpos($this->XMLContent, "<XLX")+4, 3);
// Validate service name
if (!preg_match('/^[a-zA-Z0-9]{3}$/', $this->ServiceName)) {
$this->ServiceName = null;
return false;
}
$this->ReflectorName = "XLX".$this->ServiceName;
$LinkedPeersName = "XLX".$this->ServiceName." linked peers";
$LinkedNodesName = "XLX".$this->ServiceName." linked nodes";
$LinkedUsersName = "XLX".$this->ServiceName." heard users";
$XML = new ParseXML();
$AllNodesString = $XML->GetElement($this->XMLContent, $LinkedNodesName);
$tmpNodes = $XML->GetAllElements($AllNodesString, "NODE");
for ($i=0;$i<count($tmpNodes);$i++) {
$Node = new Node(
$XML->GetElement($tmpNodes[$i], 'Callsign'),
$XML->GetElement($tmpNodes[$i], 'IP'),
$XML->GetElement($tmpNodes[$i], 'LinkedModule'),
$XML->GetElement($tmpNodes[$i], 'Protocol'),
$XML->GetElement($tmpNodes[$i], 'ConnectTime'),
$XML->GetElement($tmpNodes[$i], 'LastHeardTime'),
CreateCode(16)
);
$this->AddNode($Node);
}
$AllStationsString = $XML->GetElement($this->XMLContent, $LinkedUsersName);
$tmpStations = $XML->GetAllElements($AllStationsString, "STATION");
for ($i=0;$i<count($tmpStations);$i++) {
$Station = new Station(
$XML->GetElement($tmpStations[$i], 'Callsign'),
$XML->GetElement($tmpStations[$i], 'Via node'),
$XML->GetElement($tmpStations[$i], 'Via peer'),
$XML->GetElement($tmpStations[$i], 'LastHeardTime'),
$XML->GetElement($tmpStations[$i], 'On module')
);
$this->AddStation($Station, false);
}
$AllPeersString = $XML->GetElement($this->XMLContent, $LinkedPeersName);
$tmpPeers = $XML->GetAllElements($AllPeersString, "PEER");
for ($i=0;$i<count($tmpPeers);$i++) {
$Peer = new Peer(
$XML->GetElement($tmpPeers[$i], 'Callsign'),
$XML->GetElement($tmpPeers[$i], 'IP'),
$XML->GetElement($tmpPeers[$i], 'LinkedModule'),
$XML->GetElement($tmpPeers[$i], 'Protocol'),
$XML->GetElement($tmpPeers[$i], 'ConnectTime'),
$XML->GetElement($tmpPeers[$i], 'LastHeardTime')
);
$this->AddPeer($Peer, false);
}
$this->Version = strip_tags($XML->GetElement($this->XMLContent, "Version"));
}
}
public function GetVersion() {
return $this->Version;
}
public function GetReflectorName() {
return $this->ReflectorName;
}
public function SetXMLFile($XMLFile) {
// Prevent path traversal
$XMLFile = basename($XMLFile);
$XMLFile = '/var/log/' . $XMLFile; // Force it to expected directory
if (file_exists($XMLFile) && is_readable($XMLFile)) {
$this->XMLFile = $XMLFile;
}
else {
error_log("XML File ".$XMLFile." does not exist or is not readable");
$this->XMLFile = null;
$this->XMLContent = null;
}
}
public function SetPIDFile($ProcessIDFile) {
// Prevent path traversal
$ProcessIDFile = basename($ProcessIDFile);
$ProcessIDFile = '/var/log/' . $ProcessIDFile;
if (file_exists($ProcessIDFile)) {
$this->ProcessIDFile = $ProcessIDFile;
$this->ServiceUptime = time() - filectime($ProcessIDFile);
}
else {
$this->ProcessIDFile = null;
$this->ServiceUptime = null;
}
}
public function GetServiceUptime() {
return $this->ServiceUptime;
}
public function SetFlagFile($Flagfile) {
// Security: Only allow country.csv from the pgs directory
$expectedFile = dirname(__FILE__) . '/country.csv';
$realPath = realpath($Flagfile);
// Must resolve to the exact expected file
if ($realPath !== $expectedFile) {
error_log("Flag file must be country.csv in pgs directory. Expected: " . $expectedFile . ", Got: " . $realPath);
return false;
}
if (file_exists($realPath) && is_readable($realPath)) {
$this->Flagfile = $realPath;
return true;
}
error_log("Flag file not readable: " . $realPath);
return false;
}
public function LoadFlags() {
if ($this->Flagfile != null) {
$this->Flagarray = array();
$this->Flagarray_DXCC = array();
$handle = fopen($this->Flagfile,"r");
if ($handle) {
$i = 0;
while(!feof($handle)) {
$row = fgets($handle,1024);
$tmp = explode(";", $row);
if (isset($tmp[0])) { $this->Flagarray[$i]['Country'] = $tmp[0]; } else { $this->Flagarray[$i]['Country'] = 'Undefined'; }
if (isset($tmp[1])) { $this->Flagarray[$i]['ISO'] = $tmp[1]; } else { $this->Flagarray[$i]['ISO'] = "Undefined"; }
//$this->Flagarray[$i]['DXCC'] = array();
if (isset($tmp[2])) {
$tmp2 = explode("-", $tmp[2]);
for ($j=0;$j<count($tmp2);$j++) {
//$this->Flagarray[$i]['DXCC'][] = $tmp2[$j];
$this->Flagarray_DXCC[ trim($tmp2[$j]) ] = $i;
}
}
$i++;
}
fclose($handle);
}
return true;
}
return false;
}
public function AddNode($NodeObject) {
if (is_object($NodeObject)) {
$this->Nodes[] = $NodeObject;
}
}
public function NodeCount() {
return count($this->Nodes);
}
public function GetNode($ArrayIndex) {
if (isset($this->Nodes[$ArrayIndex])) {
return $this->Nodes[$ArrayIndex];
}
return false;
}
public function AddPeer($PeerObject) {
if (is_object($PeerObject)) {
$this->Peers[] = $PeerObject;
}
}
public function PeerCount() {
return count($this->Peers);
}
public function GetPeer($ArrayIndex) {
if (isset($this->Peer[$ArrayIndex])) {
return $this->Peer[$ArrayIndex];
}
return false;
}
public function AddStation($StationObject, $AllowDouble = false) {
if (is_object($StationObject)) {
if ($AllowDouble) {
$this->Stations[] = $StationObject;
}
else {
$FoundStationInList = false;
$i = 0;
$tmp = explode(" ", $StationObject->GetCallsign());
$RealCallsign = trim($tmp[0]);
while (!$FoundStationInList && $i<$this->StationCount()) {
if ($this->Stations[$i]->GetCallsignOnly() == $RealCallsign) {
$FoundStationInList = true;
}
$i++;
}
if (!$FoundStationInList) {
if (strlen(trim($RealCallsign)) > 3) {
$this->Stations[] = $StationObject;
}
}
}
}
}
public function GetSuffixOfRepeater($Repeater, $LinkedModul, $StartWithIndex = 0) {
$suffix = "";
$found = false;
$i = $StartWithIndex;
while (!$found && $i < $this->NodeCount()) {
if ($this->Nodes[$i]->GetLinkedModule() == $LinkedModul) {
if (strpos($this->Nodes[$i]->GetCallSign(), $Repeater) !== false) {
$suffix = $this->Nodes[$i]->GetSuffix();
$found = true;
}
}
$i++;
}
return $suffix;
}
public function GetCallsignAndSuffixByID($RandomId) {
$suffix = "";
$callsign = "";
$i = 0;
while ($i < $this->NodeCount()) {
if ($this->Nodes[$i]->GetRandomID() == $RandomId) {
if (trim($this->Nodes[$i]->GetSuffix()) == "") {
return $this->Nodes[$i]->GetCallSign();
}
else {
return $this->Nodes[$i]->GetCallSign().'-'.$this->Nodes[$i]->GetSuffix();
}
}
$i++;
}
return 'N/A';
}
public function StationCount() {
return count($this->Stations);
}
public function GetStation($ArrayIndex) {
if (isset($this->Stations[$ArrayIndex])) {
return $this->Stations[$ArrayIndex];
}
return false;
}
public function GetFlag($Callsign) {
$Image = "";
$Letters = 4;
$Name = "";
while ($Letters >= 2) {
$Prefix = substr(trim($Callsign), 0, $Letters);
if (isset($this->Flagarray_DXCC[$Prefix])) {
$Image = $this->Flagarray[ $this->Flagarray_DXCC[$Prefix] ]['ISO'];
$Name = $this->Flagarray[ $this->Flagarray_DXCC[$Prefix] ]['Country'];
break;
}
$Letters--;
}
return array(strtolower($Image), $Name);
}
public function GetModules() {
$out = array();
for ($i=0;$i<$this->NodeCount();$i++) {
$Found = false;
$b = 0;
while ($b < count($out) && !$Found) {
if ($out[$b] == $this->Nodes[$i]->GetLinkedModule()) {
$Found = true;
}
$b++;
}
if (!$Found && (trim($this->Nodes[$i]->GetLinkedModule()) != "")) {
$out[] = $this->Nodes[$i]->GetLinkedModule();
}
}
return $out;
}
public function GetModuleOfNode($Node) {
die("FUNCTION DEPRECATED...");
$Node = trim(str_replace(" ", "-", $Node));
$Node = trim(str_replace(" ", "-", $Node));
$Node = trim(str_replace(" ", "-", $Node));
$found = false;
$i = 0;
$Module = "";
while (!$found && $i<$this->NodeCount()) {
if (strpos($Node, $this->Nodes[$i]->GetFullCallsign()) !== false) {
$Module = $this->Nodes[$i]->GetLinkedModule();
$found = true;
}
$i++;
}
return $Module;
}
public function GetCallSignsInModules($Module) {
$out = array();
for ($i=0;$i<$this->NodeCount();$i++) {
if ($this->Nodes[$i]->GetLinkedModule() == $Module) {
$out[] = $this->Nodes[$i]->GetCallsign();
}
}
return $out;
}
public function GetNodesInModulesById($Module) {
$out = array();
for ($i=0;$i<$this->NodeCount();$i++) {
if ($this->Nodes[$i]->GetLinkedModule() == $Module) {
$out[] = $this->Nodes[$i]->GetRandomID();
}
}
return $out;
}
public function SetCallingHome($CallingHomeVariables, $Hash) {
if (!isset($CallingHomeVariables['Active'])) { $CallingHomeVariables['Active'] = false; }
if (!isset($CallingHomeVariables['MyDashBoardURL'])) { $CallingHomeVariables['MyDashBoardURL'] = ''; }
if (!isset($CallingHomeVariables['ServerURL'])) { $CallingHomeVariables['ServerURL'] = ''; }
if (!isset($CallingHomeVariables['Country'])) { $CallingHomeVariables['Country'] = ''; }
if (!isset($CallingHomeVariables['Comment'])) { $CallingHomeVariables['Comment'] = ''; }
if (!isset($CallingHomeVariables['OverrideIPAddress'])) { $CallingHomeVariables['OverrideIPAddress'] = false; }
if (!isset($CallingHomeVariables['InterlinkFile'])) { $CallingHomeVariables['InterlinkFile'] = ''; }
// Validate URLs
if (!empty($CallingHomeVariables['MyDashBoardURL'])) {
if (filter_var($CallingHomeVariables['MyDashBoardURL'], FILTER_VALIDATE_URL) === false) {
$CallingHomeVariables['MyDashBoardURL'] = '';
}
}
if (!empty($CallingHomeVariables['ServerURL'])) {
if (filter_var($CallingHomeVariables['ServerURL'], FILTER_VALIDATE_URL) === false) {
$CallingHomeVariables['ServerURL'] = '';
}
}
if (!file_exists($CallingHomeVariables['InterlinkFile'])) {
$this->Interlinkfile = '';
$this->Transferinterlink = false;
}
else {
$this->Transferinterlink = true;
$this->Interlinkfile = $CallingHomeVariables['InterlinkFile'];
}
$this->CallingHomeActive = ($CallingHomeVariables['Active'] === true);
$this->CallingHomeHash = $Hash;
$this->CallingHomeDashboardURL = $CallingHomeVariables['MyDashBoardURL'];
$this->CallingHomeServerURL = $CallingHomeVariables['ServerURL'];
$this->CallingHomeCountry = $CallingHomeVariables['Country'];
$this->CallingHomeComment = $CallingHomeVariables['Comment'];
$this->CallingHomeOverrideIP = $CallingHomeVariables['OverrideIPAddress'];
}
public function PushCallingHome() {
$CallingHome = @fopen($this->CallingHomeServerURL."?ReflectorName=".$this->ReflectorName."&ReflectorUptime=".$this->ServiceUptime."&ReflectorHash=".$this->CallingHomeHash."&DashboardURL=".$this->CallingHomeDashboardURL."&Country=".urlencode($this->CallingHomeCountry)."&Comment=".urlencode($this->CallingHomeComment)."&OverrideIP=".$this->CallingHomeOverrideIP, "r");
}
public function ReadInterlinkFile() {
if (empty($this->Interlinkfile)) {
return false;
}
// Prevent path traversal
$realPath = realpath($this->Interlinkfile);
if ($realPath === false || strpos($realPath, '/xlxd/') === false) {
error_log("ReadInterlinkFile blocked - invalid path");
return false;
}
if (file_exists($realPath) && is_readable($realPath)) {
$this->Interlinks = array();
$this->InterlinkXML = "";
$Interlinkfilecontent = file($realPath);
for ($i=0;$i<count($Interlinkfilecontent);$i++) {
if (substr($Interlinkfilecontent[$i], 0, 1) != '#') {
$Interlink = explode(" ", $Interlinkfilecontent[$i]);
$this->Interlinks[] = new Interlink();
if (isset($Interlink[0])) {
$this->Interlinks[count($this->Interlinks)-1]->SetName(trim($Interlink[0]));
}
if (isset($Interlink[1])) {
$this->Interlinks[count($this->Interlinks)-1]->SetAddress(trim($Interlink[1]));
}
if (isset($Interlink[2])) {
$Modules = str_split(trim($Interlink[2]), 1);
for ($j=0;$j<count($Modules);$j++) {
$this->Interlinks[count($this->Interlinks)-1]->AddModule($Modules[$j]);
}
}
}
}
return true;
}
return false;
}
public function PrepareInterlinkXML() {
$xml = '
<interlinks>';
for ($i=0;$i<count($this->Interlinks);$i++) {
$xml .= '
<interlink>
<name>'.htmlspecialchars($this->Interlinks[$i]->GetName(), ENT_XML1, 'UTF-8').'</name>
<address>'.htmlspecialchars($this->Interlinks[$i]->GetAddress(), ENT_XML1, 'UTF-8').'</address>
<modules>'.htmlspecialchars($this->Interlinks[$i]->GetModules(), ENT_XML1, 'UTF-8').'</modules>
</interlink>';
}
$xml .= '
</interlinks>';
$this->InterlinkXML = $xml;
}
public function PrepareReflectorXML() {
$this->ReflectorXML = '
<reflector>
<name>'.htmlspecialchars($this->ReflectorName, ENT_XML1, 'UTF-8').'</name>
<uptime>'.intval($this->ServiceUptime).'</uptime>
<hash>'.htmlspecialchars($this->CallingHomeHash, ENT_XML1, 'UTF-8').'</hash>
<url>'.htmlspecialchars($this->CallingHomeDashboardURL, ENT_XML1, 'UTF-8').'</url>
<country>'.htmlspecialchars($this->CallingHomeCountry, ENT_XML1, 'UTF-8').'</country>
<comment>'.htmlspecialchars($this->CallingHomeComment, ENT_XML1, 'UTF-8').'</comment>
<ip>'.htmlspecialchars($this->CallingHomeOverrideIP, ENT_XML1, 'UTF-8').'</ip>
<reflectorversion>'.htmlspecialchars($this->Version, ENT_XML1, 'UTF-8').'</reflectorversion>
</reflector>';
}
public function CallHome() {
// Validate ServerURL is not localhost/internal IP
$parsed = parse_url($this->CallingHomeServerURL);
if (!isset($parsed['host'])) {
error_log("CallHome failed - invalid URL");
return false;
}
$ip = gethostbyname($parsed['host']);
if (filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE) === false) {
error_log("CallHome blocked - internal/private IP detected");
return false;
}
// Sanitize all data being sent
$xml = '<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<query>CallingHome</query>'.$this->ReflectorXML.$this->InterlinkXML;
$p = @stream_context_create(array('http' => array(
'header' => "Content-type: application/x-www-form-urlencoded\r\n",
'method' => 'POST',
'content' => http_build_query(array('xml' => $xml)),
'timeout' => 10
)));
$result = @file_get_contents($this->CallingHomeServerURL, false, $p);
if ($result === false) {
error_log("CallHome connection failed");
return false;
}
return true;
}
public function InterlinkCount() {
return count($this->Interlinks);
}
public function GetInterlink($Index) {
if (isset($this->Interlinks[$Index])) {
return $this->Interlinks[$Index];
}
return false;
}
public function IsInterlinked($Reflectorname) {
$i = -1;
$f = false;
while (!$f && $i < $this->InterlinkCount()) {
$i++;
if (isset($this->Interlinks[$i])) {
if ($this->Interlinks[$i]->GetName() == $Reflectorname) {
$f = true;
return $i;
}
}
}
return -1;
}
}
?>

View file

@ -0,0 +1,54 @@
<?php
class Station {
private $Callsign;
private $Via;
private $LastHeardTime;
private $Suffix;
private $CallsignOnly;
private $Peer;
private $OnModule;
public function __construct($Callsign, $Via, $Peer, $LastHeardTime, $OnModule) {
// Sanitize and validate callsign
$Callsign = trim($Callsign);
$this->Callsign = $Callsign;
// Sanitize Via and Peer
$this->Via = trim($Via);
$this->Peer = trim($Peer);
$this->LastHeardTime = ParseTime($LastHeardTime);
if (strpos($Callsign, " / ") !== false) {
$this->Suffix = trim(substr($Callsign, strpos($Callsign, " / ")+3));
}
else {
$this->Suffix = "";
}
$tmp = explode(" ", $Callsign);
$this->CallsignOnly = isset($tmp[0]) ? trim($tmp[0]) : '';
// Validate callsign format
if (!empty($this->CallsignOnly) && !preg_match('/^[A-Z0-9]{1,10}$/i', $this->CallsignOnly)) {
$this->CallsignOnly = 'INVALID';
}
// Validate OnModule (single letter A-Z)
$OnModule = trim(strtoupper($OnModule));
$this->OnModule = preg_match('/^[A-Z]$/', $OnModule) ? $OnModule : '';
}
public function GetCallsign() { return $this->Callsign; }
public function GetVIA() { return $this->Via; }
public function GetPeer() { return $this->Peer; }
public function GetLastHeardTime() { return $this->LastHeardTime; }
public function GetSuffix() { return $this->Suffix; }
public function GetCallsignOnly() { return $this->CallsignOnly; }
public function GetModule() { return $this->OnModule; }
}
?>

View file

@ -0,0 +1,84 @@
<?php
/*
Possible values for IPModus
HideIP
ShowFullIP
ShowLast1ByteOfIP
ShowLast2ByteOfIP
ShowLast3ByteOfIP
*/
$Service = array();
$CallingHome = array();
$PageOptions = array();
$VNStat = array();
$PageOptions['ContactEmail'] = 'your_email'; // Support E-Mail address
$PageOptions['DashboardVersion'] = '2.4.3'; // Dashboard Version
$PageOptions['PageRefreshActive'] = true; // Activate automatic refresh
$PageOptions['PageRefreshDelay'] = '10000'; // Page refresh time in miliseconds
$PageOptions['NumberOfModules'] = 10; // Number of Modules enabled on reflector
$PageOptions['RepeatersPage'] = array();
$PageOptions['RepeatersPage']['LimitTo'] = 99; // Number of Repeaters to show
$PageOptions['RepeatersPage']['IPModus'] = 'ShowFullIP'; // See possible options above
$PageOptions['RepeatersPage']['MasqueradeCharacter'] = '*'; // Character used for masquerade
$PageOptions['PeerPage'] = array();
$PageOptions['PeerPage']['LimitTo'] = 99; // Number of peers to show
$PageOptions['PeerPage']['IPModus'] = 'ShowFullIP'; // See possible options above
$PageOptions['PeerPage']['MasqueradeCharacter'] = '*'; // Character used for masquerade
$PageOptions['LastHeardPage']['LimitTo'] = 39; // Number of stations to show
$PageOptions['ModuleNames'] = array(); // Module nomination
$PageOptions['ModuleNames']['A'] = 'Int.';
$PageOptions['ModuleNames']['B'] = 'Regional';
$PageOptions['ModuleNames']['C'] = 'National';
$PageOptions['ModuleNames']['D'] = '';
$PageOptions['MetaDescription'] = 'XLX is a D-Star Reflector System for Ham Radio Operators.'; // Meta Tag Values, usefull for Search Engine
$PageOptions['MetaKeywords'] = 'Ham Radio, D-Star, XReflector, XLX, XRF, DCS, REF, '; // Meta Tag Values, usefull forSearch Engine
$PageOptions['MetaAuthor'] = 'LX1IQ'; // Meta Tag Values, usefull for Search Engine
$PageOptions['MetaRevisit'] = 'After 30 Days'; // Meta Tag Values, usefull for Search Engine
$PageOptions['MetaRobots'] = 'index,follow'; // Meta Tag Values, usefull for Search Engine
$PageOptions['UserPage']['ShowFilter'] = true; // Show Filter on Users page
$PageOptions['Traffic']['Show'] = false; // Enable vnstat traffic statistics
$PageOptions['IRCDDB']['Show'] = true; // Show liveircddb, set it to false if you are running your db in https
$PageOptions['CustomTXT'] = ''; // custom text in your header
$Service['PIDFile'] = '/var/log/xlxd.pid';
$Service['XMLFile'] = '/var/log/xlxd.xml';
$CallingHome['Active'] = false; // xlx phone home, true or false
$CallingHome['MyDashBoardURL'] = 'http://your_dashboard'; // dashboard url
$CallingHome['ServerURL'] = 'http://xlxapi.rlx.lu/api.php'; // database server, do not change !!!!
$CallingHome['PushDelay'] = 600; // push delay in seconds
$CallingHome['Country'] = "your_country"; // Country
$CallingHome['Comment'] = "your_comment"; // Comment. Max 100 character
$CallingHome['HashFile'] = "/tmp/callinghome.php"; // Make sure the apache user has read and write permissions in this folder.
$CallingHome['LastCallHomefile'] = "/tmp/lastcallhome.php"; // lastcallhome.php can remain in the tmp folder
$CallingHome['OverrideIPAddress'] = ""; // Insert your IP address here. Leave blank for autodetection. No need to enter a fake address.
$CallingHome['InterlinkFile'] = "/xlxd/xlxd.interlink"; // Path to interlink file
$VNStat['Interfaces'] = array();
$VNStat['Interfaces'][0]['Name'] = 'eth0';
$VNStat['Interfaces'][0]['Address'] = 'eth0';
$VNStat['Binary'] = '/usr/bin/vnstat';
/*
include an extra config file for people who dont like to mess with shipped config.ing.php
this makes updating dashboard from git a little bit easier
*/
if (file_exists("../config.inc.php")) {
include ("../config.inc.php");
}
?>

309
dashboard1/pgs/country.csv Normal file
View file

@ -0,0 +1,309 @@
Afghanistan;AF;YA-T6
Agalega & St. Brandon Island;MU;3B6-3B7
Aland Islands;AX;OH0
Alaska;US;AL-KL-NL-WL
Albania;AL;ZA
Algeria;DZ;7T-7U-7V-7W-7X-7Y
American Samoa;AS;KH8
Andaman & Nicobar Islands;IN;VU4
Andorra;AD;C3
Angola;AO;D2-D3
Anguilla;AI;VP2E
Annobon Island;GQ;3C0
Antarctica;AQ;CE9-KC4A-KC4U
Antigua and Barbuda;AG;V2
Argentina;AR;LO-LP-LQ-LR-LS-LT-LU-LV-LW
Armenia;AM;EK
Aruba;AW;P4
Ascension Island;SH;ZD8
Asiatic Russia;RU;UA0-UA8-UA9-UB0-UB8-UB9-UC0-UC8-UC9-UD0-UD8-UD9-UE0-UE8-UE9-UF0-UF8-UF9-UG0-UG8-UG9-UH0-UH8-UH9-UI0-UI8-UI9-RA0-RA8-RA9-RB0-RB8-RB9-RC0-RC8-RC9-RD0-RD8-RD9-RE0-RE8-RE9-RF0-RF8-RF9-RG0-RG8-RG9-RH0-RH8-RH9-RI0-RI8-RI9-RJ0-RJ8-RJ9-RK0-RK8-RK9-RL0-RL8-RL9-RM0-RM8-RM9-RN0-RN8-RN9-RO0-RO8-RO9-RP0-RP8-RP9-RQ0-RQ8-RQ9-RR0-RR8-RR9-RS0-RS8-RS9-RT0-RT8-RT9-RU0-RU8-RU9-RV0-RV8-RV9-RW0-RW8-RW9-RX0-RX8-RX9-RY0-RY8-RY9-RZ0-RZ8-RZ9-R8-R9
Australia;AU;VK-AX
Austria;AT;OE
Azerbaijan;AZ;4J-4K
Azores;PT;CU
Bahamas;BS;C6
Bahrain;BH;A9
Baker & Howland Islands;US;KH1
Balearic Islands;ES;EA6-EB6-EC6-ED6-EE6-EF6-EG6-EH6
Banaba Island (Ocean Island);KI;T33
Bangladesh;BD;S2
Barbados;BB;8P
Belarus;BY;EU-EV-EW
Belgium;BE;ON-OO-OP-OQ-OR-OS-OT
Belize;BZ;V3
Benin;BJ;TY
Bermuda;BM;VP9
Bhutan;BT;A5
Bolivia Plurinational State of;BO;CP
Bonaire;NL;PJ4
Bosnia and Herzegovina;BA;E7
Botswana;BW;A2
Bouvet Island;BV;3Y
Brazil;BR;PP-PQ-PR-PS-PT-PU-PV-PW-PX-PY-ZV-ZW-ZX-ZY-ZZ
British Indian Ocean Territory;IO;VP2V
Brunei Darussalam;BN;V8
Bulgaria;BG;LZ
Burkina Faso;BF;XT
Burundi;BI;9U
Cambodia;KH;XU
Cameroon;CM;TJ
Canada;CA;VA-VB-VC-VD-VE-VF-VG-VO-VY
Canary Islands;ES;EA8-EB8-EC8-ED8-EE8-EF8-EG8-EH8
Cape Verde;CV;D4
Cayman Islands;KY;ZF
Central African Republic;CF;TL
Central Kiribati (British Phoenix Island);KI;T31
Ceuta & Melilla;ES;EA9-EB9-EC9-ED9-EE9-EF9-EG9-EH9
Chad;TD;TT
Chagos Islands;;VQ9
Chatham Islands;NZ;ZL7
Chile;CL;CA-CB-CC-CD-CE-XQ-XR
China;CN;BA-BB-BC-BD-BE-BF-BG-BH-BI-BJ-BK-BL-BN-BP-BQ-BR-BS-BT-BY-BZ
Christmas Island;CX;VK9X
Cocos Island;;TI9
Cocos (Keeling) Islands;CC;VK9C
Colombia;CO;HJ-HK-5J-5K
Comoros;KM;D6
Congo;CG;TN
Congo the Democratic Republic of the;CD;9Q-9R-9S-9T
Cook Islands;CK;E5
Corsica;FR;TK
Costa Rica;CR;TI-TE
Cote d'Ivoire;CI;TU
Crete;GR;SV9-J49
Croatia;HR;9A
Cuba;CU;CO-CM
Curacao;CW;PJ2
Cyprus;CY;5B-C4-P3
Czech Republic;CZ;OK-OL
Denmark;DK;OU-OV-OW-OZ
Desecheo Island;US;KP5
Djibouti;DJ;J2
Dodecanese;GR;SV5-J45
Dominica;DM;J7
Dominican Republic;DO;HI
East Malaysia;MY;9M6-9M8-9W6-9W8
Easter Island;CL;CE0
Eastern Kiribati (Line Island);KI;T32
Ecuador;EC;HC-HD
Egypt;EG;SU
El Salvador;SV;YS-HU
England;EN;2E-M0-M1-M2-M3-M4-M5-M6-M7-M8-M9-MB-MX-G0-G1-G2-G3-G4-G5-G6-G7-G8-G9-GB-GX
Equatorial Guinea;GQ;3C
Eritrea;ER;E3
Estonia;EE;ES
Ethiopia;ET;ET
European Russia;RU;UA1-UA3-UA4-UA5-UA6-UA7-UB1-UB2-UB3-UB4-UB5-UB6-UB7-UC1-UC2-UC3-UC4-UC5-UC6-UC7-UD1-UD2-UD3-UD4-UD5-UD6-UD7-UE1-UE2-UE3-UE4-UE5-UE6-UE7-UF1-UF2-UF3-UF4-UF5-UF6-UF7-UG1-UG2-UG3-UG4-UG5-UG6-UG7-UH1-UH2-UH3-UH4-UH5-UH6-UH7-UI1-UI2-UI3-UI4-UI5-UI6-UI7-RA1-RA3-RA4-RA5-RA6-RA7-RB1-RB2-RB3-RB4-RB5-RB6-RB7-RC1-RC2-RC3-RC4-RC5-RC6-RC7-RD1-RD2-RD3-RD4-RD5-RD6-RD7-RE1-RE2-RE3-RE4-RE5-RE6-RE7-RF1-RF2-RF3-RF4-RF5-RF6-RF7-RG1-RG2-RG3-RG4-RG5-RG6-RG7-RH1-RH2-RH3-RH4-RH5-RH6-RH7-RI1-RI2-RI3-RI4-RI5-RI6-RI7-RJ1-RJ2-RJ3-RJ4-RJ5-RJ6-RJ7-RK1-RK2-RK3-RK4-RK5-RK6-RK7-RL1-RL2-RL3-RL4-RL5-RL6-RL7-RM1-RM2-RM3-RM4-RM5-RM6-RM7-RN1-RN2-RN3-RN4-RN5-RN6-RN7-RO1-RO2-RO3-RO4-RO5-RO6-RO7-RP1-RP2-RP3-RP4-RP5-RP6-RP7-RQ1-RQ2-RQ3-RQ4-RQ5-RQ6-RQ7-RR1-RR2-RR3-RR4-RR5-RR6-RR7-RS1-RS2-RS3-RS4-RS5-RS6-RS7-RT1-RT2-RT3-RT4-RT5-RT6-RT7-RU1-RU2-RU3-RU4-RU5-RU6-RU7-RV1-RV2-RV3-RV4-RV5-RV6-RV7-RW1-RW2-RW3-RW4-RW5-RW6-RW7-RX1-RX2-RX3-RX4-RX5-RX6-RX7-RY1-RY2-RY3-RY4-RY5-RY6-RY7-RZ1-RZ2-RZ3-RZ4-RZ5-RZ6-RZ7-R1-R2-R3-R4-R5-R6-R7
Falkland Islands (Malvinas);FK;VP8
Faroe Islands;FO;OY
Fiji;FJ;3D2
Finland;FI;OF-OG-OH-OI
France;FR;F0-F1-F2-F3-F4-F5-F6-F7-F8-F9
Franz Josef Land;RU;R1
French Guiana;GF;FY
French Southern and Antarctic Lands;FR;FT
French Polynesia;PF;FO-TX
Gabon;GA;TR
Galapagos Islands;EC;HC8-HD8
Gambia;GM;C5
Georgia;GE;4L
Germany;DE;DA-DB-DC-DD-DE-DF-DG-DH-DI-DJ-DK-DL-DM-DN-DO-DP-DQ-DR
Ghana;GH;9G
Gibraltar;GI;ZB2
Greece;GR;SV-SW-SX-SY-SZ-J4
Greenland;GL;OX
Grenada;GD;J3
Guadeloupe;GP;FG
Guam;GU;KH2
Guantanamo Bay;US;KG4
Guatemala;GT;TG-TD
Guernsey;GG;2U-MU-MP-GU-GP
Guinea;GN;3X
Guinea-Bissau;GW;J5
Guyana;GY;8R
Haiti;HT;HH
Hawaii;US;KH6-KH7
Heard Island and McDonald Islands;HM;VK0
Holy See (Vatican City State);VA;HV
Honduras;HN;HQ-HR
Hong Kong;HK;VR
Hungary;HU;HA-HG
Iceland;IS;TF
India;IN;VU
Indonesia;ID;YB-YC-YD-YE-YF-YG-YH
Iran Islamic Republic of;IR;EP-EQ
Iraq;IQ;YI
Ireland;IE;EI-EJ
Isle of Man;IM;2D-MD-MT-GD-GT
Israel;IL;4X-4Z
Italy;IT;I0-I1-I2-I3-I4-I5-I6-I7-I8-I9-IK-IN-IQ-IR-IS-IT-IU-IV-IW-IZ
Jamaica;JM;6Y
Jan Mayen;NO;JX
Japan;JP;JA-JB-JC-JD-JE-JF-JG-JH-JI-JJ-JK-JL-JM-JN-JO-JP-JQ-JR-JS-7J-7K-7L-7M-7N-8J-8N
Jersey;JE;2J-MJ-MH-GJ-GH
Johnston Island;US;KH3
Jordan;JO;JY
Kaliningrad;RU;UA2-RA2
Kazakhstan;KZ;UN-UO-UP-UQ
Kenya;KE;5Y-5Z
Kermadec Islands;NZ;ZL8
Korea Democratic People's Republic of;KP;P5
Korea Republic of;KR;HL-6K-6L-6M-6N-DS
Kure Island;US;KH7K
Kuwait;KW;9K
Kyrgyzstan;KG;EX
Lakshadweep Islands;IN;VU7
Lao People's Democratic Republic;LA;XW
Latvia;LV;YL
Lebanon;LB;OD
Lesotho;LS;7P
Liberia;LR;EL
Libya;LY;5A
Liechtenstein;LI;HB0
Lithuania;LT;LY
Lord Howe Island;AU;VK9L
Luxembourg;LU;LX
Macao;MO;XX9
Macedonia;MK;Z3
Madagascar;MG;5R
Madeira Island;PT;CT3
Malawi;MW;7Q
Maldives;MV;8Q
Mali;ML;TZ
Malta;MT;9H
Mariana Islands;US;KH0
Market Reef;;OJ0
Marshall Islands;MH;V7
Martinique;MQ;FM
Mauritania;MR;5T
Mauritius;MU;3B8
Mayotte;YT;FH-FO
Mellish Reef;AU;VK9M
Mexico;MX;XA-XB-XC-XD-XE-XF-XG-XH-XI
Micronesia Federated States of;FM;V6
Midway Island;US;KH4
Moldova Republic of;MD;ER
Monaco;MC;3A
Mongolia;MN;JT-JU-JV
Montenegro;ME;4O
Montserrat;MS;VP2M
Morocco;MA;CN
Mozambique;MZ;C8-C9
Myanmar;MM;XY-XZ
Namibia;NA;V5
Nauru;NR;C2
Navassa Island;;KP1
Nepal;NP;9N
Netherlands;NL;PA-PB-PC-PD-PE-PF-PG-PH-PI
New Caledonia;NC;FK
New Zealand;NZ;ZL-ZM
New Zealand Subantarctic Islands;NZ;ZL9
Nicaragua;NI;YN-H6-H7-HT
Niger;NE;5U
Nigeria;NG;5N
Niue;NU;ZK2
Norfolk Island;NF;VK9N
Northern Ireland;NIE;2I-MI-MN-GI-GN
Northern Mariana Islands;MP;KH0
Norway;NO;LA-LB-LC-LD-LE-LF-LG-LH-LI-LJ-LK-LL-LM-LN
Oman;OM;A4-YP-YQ-YR
Pakistan;PK;AP
Palau;PW;T8
Palestine State of;PS;E4
Palmyra & Jarvis Island;UM;KH5
Panama;PA;HO-HP
Papua New Guinea;PG;P2
Paraguay;PY;ZP
Peru;PE;OA-OB-OC
Philippines;PH;DU-DV-DW-DX-DY-DZ
Pitcairn;PN;VP6
Poland;PL;3Z6-SN-SO-SP-SQ-SR
Portugal;PT;CQ0-CQ1-CQ2-CQ3-CQ7-CQ8-CR1-CR2-CR3-CR5-CR6-CR7-CR8-CR9-CS2-CS3-CS4-CS5-CS7-CS8-CT1-CT2-CT3-CT4-CT5-CT6-CT7-CT8-CT9-CU0-CU1-CU2-CU3-CU4-CU5-CU6-CU7-CU8-CU
Pratas Islands;;BV9P
Prince Edward & Marion Islands;ZA;ZS8
Puerto Rico;PR;KP3-KP4
Qatar;QA;A7
Reunion;RE;FR
Revillagigedo Islands;MX;XA4-XB4-XC4-XD4-XE4-XF4-XG4-XH4-XI4
Rodriguez Island;MU;3B9
Romania;RO;YO-YP-YQ-YR
Rwanda;RW;9X
Sable Island;CA;CY0
Saint Barthelemy;BL;FJ
Saint Helena;SH;ZD7
Saint Kitts and Nevis;KN;V4
Saint Lucia;LC;J6
Saint Martin (French part);MF;FS
Saint Pierre and Miquelon;PM;FP
Saint Vincent and the Grenadines;VC;J8
Samoa;WS;5W
San Marino;SM;T7
Sao Tome and Principe;ST;S9
Sardinia;IT;IS0-IM0
Saudi Arabia;SA;HZ
Scarborough Reef;;BS7
Scotland;SH;2M-MM-MS-GM-GS
Senegal;SN;6V-6W
Serbia;RS;YT-YU
Seychelles;SC;S7
Sierra Leone;SL;9L
Singapore;SG;9V
Sint Eustatius and Saba;NL;PJ5-PJ6
Sint Maarten (Dutch part);SX;PJ7
Slovakia;SK;OM
Slovenia;SI;S5
Solomon Islands;SB;H4
Somalia;SO;T5-6O
South Africa;ZA;ZR-ZS-ZT-ZU
South Georgia and the South Sandwich Islands;GS;VP8S
South Sudan;SS;Z8
Spain;ES;EA-EB-EC-ED-EE-EF-EG-EH
Sri Lanka;LK;4S
St. Paul Island;US;CY9
Sudan;SD;ST
Suriname;SR;PZ
Svalbard;NO;JW
Swaziland;SZ;3DA
Sweden;SE;SA-SB-SC-SD-SE-SF-SG-SH-SI-SJ-SK-SL-SM-7S-8S
Switzerland;CH;HB
Syrian Arab Republic;SY;YK
Taiwan Province of China;TW;BM-BO-BU-BV-BW-BX
Tajikistan;TJ;EY
Tanzania United Republic of;TZ;5H-5I
Temotu Province;SB;H40
Thailand;TH;HS-E2
Timor-Leste;TL;4W
Togo;TG;5V
Tokelau;TK;ZK3
Tonga;TO;A3
Trinidad and Tobago;TT;9Y-9Z
Tristan da Cunha & Gough Island;SH;ZD9
Tunisia;TN;3V
Turkey;TR;TA-TB-TC
Turkmenistan;TM;EZ
Turks and Caicos Islands;TC;VP5
Tuvalu;TV;T2
Uganda;UG;5X
UK Sov. Base Areas on Cyprus;CY;ZC4
Ukraine;UA;UR-US-UT-UU-UV-UW-UX-UY-UZ-EM-EN-EO
United Arab Emirates;AE;A6
United States;US;AA-AB-AC-AD-AE-AF-AG-AH-AI-AJ-AK-K0-K1-K2-K3-K4-K5-K6-K7-K8-K9-KA-KB-KC-KD-KE-KF-KG-KH-KI-KJ-KK-KM-KN-KO-KP-KQ-KR-KS-KT-KU-KV-KW-KX-KY-KZ-N0-N1-N2-N3-N4-N5-N6-N7-N8-N9-NA-NB-NC-ND-NE-NF-NG-NH-NI-NJ-NK-NM-NN-NO-NP-NQ-NR-NS-NT-NU-NV-NW-NX-NY-NZ-W0-W1-W2-W3-W4-W5-W6-W7-W8-W9-WA-WB-WC-WD-WE-WF-WG-WH-WI-WJ-WK-WM-WN-WO-WP-WQ-WR-WS-WT-WU-WV-WW-WX-WY-WZ
Uruguay;UY;CV-CW-CX
Uzbekistan;UZ;UJ-UK-UL-UM
Vanuatu;VU;YJ
Venezuela Bolivarian Republic of;VE;YV-YW-YX-YY-4M
Aves Island;VE;YV0
Viet Nam;VN;3W-XV
Virgin Islands British;VG;VP2V
Virgin Islands U.S.;VI;KP2
Wake Island;US;KH9
Wales;WL;2W-MW-MC-GW-GC
Wallis and Futuna;WF;FW
West Malaysia;MY;9M2-9M4-9W2-9W4
Western Kiribati (Gilbert Island);KI;T30
Western Sahara;EH;S0
Willis Island;AU;VK9W
Yemen;YE;7O
Zambia;ZM;9I-9J
Zimbabwe;ZW;Z2
GATE;GATE;REF-XRF
1 Afghanistan AF YA-T6
2 Agalega & St. Brandon Island MU 3B6-3B7
3 Aland Islands AX OH0
4 Alaska US AL-KL-NL-WL
5 Albania AL ZA
6 Algeria DZ 7T-7U-7V-7W-7X-7Y
7 American Samoa AS KH8
8 Andaman & Nicobar Islands IN VU4
9 Andorra AD C3
10 Angola AO D2-D3
11 Anguilla AI VP2E
12 Annobon Island GQ 3C0
13 Antarctica AQ CE9-KC4A-KC4U
14 Antigua and Barbuda AG V2
15 Argentina AR LO-LP-LQ-LR-LS-LT-LU-LV-LW
16 Armenia AM EK
17 Aruba AW P4
18 Ascension Island SH ZD8
19 Asiatic Russia RU UA0-UA8-UA9-UB0-UB8-UB9-UC0-UC8-UC9-UD0-UD8-UD9-UE0-UE8-UE9-UF0-UF8-UF9-UG0-UG8-UG9-UH0-UH8-UH9-UI0-UI8-UI9-RA0-RA8-RA9-RB0-RB8-RB9-RC0-RC8-RC9-RD0-RD8-RD9-RE0-RE8-RE9-RF0-RF8-RF9-RG0-RG8-RG9-RH0-RH8-RH9-RI0-RI8-RI9-RJ0-RJ8-RJ9-RK0-RK8-RK9-RL0-RL8-RL9-RM0-RM8-RM9-RN0-RN8-RN9-RO0-RO8-RO9-RP0-RP8-RP9-RQ0-RQ8-RQ9-RR0-RR8-RR9-RS0-RS8-RS9-RT0-RT8-RT9-RU0-RU8-RU9-RV0-RV8-RV9-RW0-RW8-RW9-RX0-RX8-RX9-RY0-RY8-RY9-RZ0-RZ8-RZ9-R8-R9
20 Australia AU VK-AX
21 Austria AT OE
22 Azerbaijan AZ 4J-4K
23 Azores PT CU
24 Bahamas BS C6
25 Bahrain BH A9
26 Baker & Howland Islands US KH1
27 Balearic Islands ES EA6-EB6-EC6-ED6-EE6-EF6-EG6-EH6
28 Banaba Island (Ocean Island) KI T33
29 Bangladesh BD S2
30 Barbados BB 8P
31 Belarus BY EU-EV-EW
32 Belgium BE ON-OO-OP-OQ-OR-OS-OT
33 Belize BZ V3
34 Benin BJ TY
35 Bermuda BM VP9
36 Bhutan BT A5
37 Bolivia Plurinational State of BO CP
38 Bonaire NL PJ4
39 Bosnia and Herzegovina BA E7
40 Botswana BW A2
41 Bouvet Island BV 3Y
42 Brazil BR PP-PQ-PR-PS-PT-PU-PV-PW-PX-PY-ZV-ZW-ZX-ZY-ZZ
43 British Indian Ocean Territory IO VP2V
44 Brunei Darussalam BN V8
45 Bulgaria BG LZ
46 Burkina Faso BF XT
47 Burundi BI 9U
48 Cambodia KH XU
49 Cameroon CM TJ
50 Canada CA VA-VB-VC-VD-VE-VF-VG-VO-VY
51 Canary Islands ES EA8-EB8-EC8-ED8-EE8-EF8-EG8-EH8
52 Cape Verde CV D4
53 Cayman Islands KY ZF
54 Central African Republic CF TL
55 Central Kiribati (British Phoenix Island) KI T31
56 Ceuta & Melilla ES EA9-EB9-EC9-ED9-EE9-EF9-EG9-EH9
57 Chad TD TT
58 Chagos Islands VQ9
59 Chatham Islands NZ ZL7
60 Chile CL CA-CB-CC-CD-CE-XQ-XR
61 China CN BA-BB-BC-BD-BE-BF-BG-BH-BI-BJ-BK-BL-BN-BP-BQ-BR-BS-BT-BY-BZ
62 Christmas Island CX VK9X
63 Cocos Island TI9
64 Cocos (Keeling) Islands CC VK9C
65 Colombia CO HJ-HK-5J-5K
66 Comoros KM D6
67 Congo CG TN
68 Congo the Democratic Republic of the CD 9Q-9R-9S-9T
69 Cook Islands CK E5
70 Corsica FR TK
71 Costa Rica CR TI-TE
72 Cote d'Ivoire CI TU
73 Crete GR SV9-J49
74 Croatia HR 9A
75 Cuba CU CO-CM
76 Curacao CW PJ2
77 Cyprus CY 5B-C4-P3
78 Czech Republic CZ OK-OL
79 Denmark DK OU-OV-OW-OZ
80 Desecheo Island US KP5
81 Djibouti DJ J2
82 Dodecanese GR SV5-J45
83 Dominica DM J7
84 Dominican Republic DO HI
85 East Malaysia MY 9M6-9M8-9W6-9W8
86 Easter Island CL CE0
87 Eastern Kiribati (Line Island) KI T32
88 Ecuador EC HC-HD
89 Egypt EG SU
90 El Salvador SV YS-HU
91 England EN 2E-M0-M1-M2-M3-M4-M5-M6-M7-M8-M9-MB-MX-G0-G1-G2-G3-G4-G5-G6-G7-G8-G9-GB-GX
92 Equatorial Guinea GQ 3C
93 Eritrea ER E3
94 Estonia EE ES
95 Ethiopia ET ET
96 European Russia RU UA1-UA3-UA4-UA5-UA6-UA7-UB1-UB2-UB3-UB4-UB5-UB6-UB7-UC1-UC2-UC3-UC4-UC5-UC6-UC7-UD1-UD2-UD3-UD4-UD5-UD6-UD7-UE1-UE2-UE3-UE4-UE5-UE6-UE7-UF1-UF2-UF3-UF4-UF5-UF6-UF7-UG1-UG2-UG3-UG4-UG5-UG6-UG7-UH1-UH2-UH3-UH4-UH5-UH6-UH7-UI1-UI2-UI3-UI4-UI5-UI6-UI7-RA1-RA3-RA4-RA5-RA6-RA7-RB1-RB2-RB3-RB4-RB5-RB6-RB7-RC1-RC2-RC3-RC4-RC5-RC6-RC7-RD1-RD2-RD3-RD4-RD5-RD6-RD7-RE1-RE2-RE3-RE4-RE5-RE6-RE7-RF1-RF2-RF3-RF4-RF5-RF6-RF7-RG1-RG2-RG3-RG4-RG5-RG6-RG7-RH1-RH2-RH3-RH4-RH5-RH6-RH7-RI1-RI2-RI3-RI4-RI5-RI6-RI7-RJ1-RJ2-RJ3-RJ4-RJ5-RJ6-RJ7-RK1-RK2-RK3-RK4-RK5-RK6-RK7-RL1-RL2-RL3-RL4-RL5-RL6-RL7-RM1-RM2-RM3-RM4-RM5-RM6-RM7-RN1-RN2-RN3-RN4-RN5-RN6-RN7-RO1-RO2-RO3-RO4-RO5-RO6-RO7-RP1-RP2-RP3-RP4-RP5-RP6-RP7-RQ1-RQ2-RQ3-RQ4-RQ5-RQ6-RQ7-RR1-RR2-RR3-RR4-RR5-RR6-RR7-RS1-RS2-RS3-RS4-RS5-RS6-RS7-RT1-RT2-RT3-RT4-RT5-RT6-RT7-RU1-RU2-RU3-RU4-RU5-RU6-RU7-RV1-RV2-RV3-RV4-RV5-RV6-RV7-RW1-RW2-RW3-RW4-RW5-RW6-RW7-RX1-RX2-RX3-RX4-RX5-RX6-RX7-RY1-RY2-RY3-RY4-RY5-RY6-RY7-RZ1-RZ2-RZ3-RZ4-RZ5-RZ6-RZ7-R1-R2-R3-R4-R5-R6-R7
97 Falkland Islands (Malvinas) FK VP8
98 Faroe Islands FO OY
99 Fiji FJ 3D2
100 Finland FI OF-OG-OH-OI
101 France FR F0-F1-F2-F3-F4-F5-F6-F7-F8-F9
102 Franz Josef Land RU R1
103 French Guiana GF FY
104 French Southern and Antarctic Lands FR FT
105 French Polynesia PF FO-TX
106 Gabon GA TR
107 Galapagos Islands EC HC8-HD8
108 Gambia GM C5
109 Georgia GE 4L
110 Germany DE DA-DB-DC-DD-DE-DF-DG-DH-DI-DJ-DK-DL-DM-DN-DO-DP-DQ-DR
111 Ghana GH 9G
112 Gibraltar GI ZB2
113 Greece GR SV-SW-SX-SY-SZ-J4
114 Greenland GL OX
115 Grenada GD J3
116 Guadeloupe GP FG
117 Guam GU KH2
118 Guantanamo Bay US KG4
119 Guatemala GT TG-TD
120 Guernsey GG 2U-MU-MP-GU-GP
121 Guinea GN 3X
122 Guinea-Bissau GW J5
123 Guyana GY 8R
124 Haiti HT HH
125 Hawaii US KH6-KH7
126 Heard Island and McDonald Islands HM VK0
127 Holy See (Vatican City State) VA HV
128 Honduras HN HQ-HR
129 Hong Kong HK VR
130 Hungary HU HA-HG
131 Iceland IS TF
132 India IN VU
133 Indonesia ID YB-YC-YD-YE-YF-YG-YH
134 Iran Islamic Republic of IR EP-EQ
135 Iraq IQ YI
136 Ireland IE EI-EJ
137 Isle of Man IM 2D-MD-MT-GD-GT
138 Israel IL 4X-4Z
139 Italy IT I0-I1-I2-I3-I4-I5-I6-I7-I8-I9-IK-IN-IQ-IR-IS-IT-IU-IV-IW-IZ
140 Jamaica JM 6Y
141 Jan Mayen NO JX
142 Japan JP JA-JB-JC-JD-JE-JF-JG-JH-JI-JJ-JK-JL-JM-JN-JO-JP-JQ-JR-JS-7J-7K-7L-7M-7N-8J-8N
143 Jersey JE 2J-MJ-MH-GJ-GH
144 Johnston Island US KH3
145 Jordan JO JY
146 Kaliningrad RU UA2-RA2
147 Kazakhstan KZ UN-UO-UP-UQ
148 Kenya KE 5Y-5Z
149 Kermadec Islands NZ ZL8
150 Korea Democratic People's Republic of KP P5
151 Korea Republic of KR HL-6K-6L-6M-6N-DS
152 Kure Island US KH7K
153 Kuwait KW 9K
154 Kyrgyzstan KG EX
155 Lakshadweep Islands IN VU7
156 Lao People's Democratic Republic LA XW
157 Latvia LV YL
158 Lebanon LB OD
159 Lesotho LS 7P
160 Liberia LR EL
161 Libya LY 5A
162 Liechtenstein LI HB0
163 Lithuania LT LY
164 Lord Howe Island AU VK9L
165 Luxembourg LU LX
166 Macao MO XX9
167 Macedonia MK Z3
168 Madagascar MG 5R
169 Madeira Island PT CT3
170 Malawi MW 7Q
171 Maldives MV 8Q
172 Mali ML TZ
173 Malta MT 9H
174 Mariana Islands US KH0
175 Market Reef OJ0
176 Marshall Islands MH V7
177 Martinique MQ FM
178 Mauritania MR 5T
179 Mauritius MU 3B8
180 Mayotte YT FH-FO
181 Mellish Reef AU VK9M
182 Mexico MX XA-XB-XC-XD-XE-XF-XG-XH-XI
183 Micronesia Federated States of FM V6
184 Midway Island US KH4
185 Moldova Republic of MD ER
186 Monaco MC 3A
187 Mongolia MN JT-JU-JV
188 Montenegro ME 4O
189 Montserrat MS VP2M
190 Morocco MA CN
191 Mozambique MZ C8-C9
192 Myanmar MM XY-XZ
193 Namibia NA V5
194 Nauru NR C2
195 Navassa Island KP1
196 Nepal NP 9N
197 Netherlands NL PA-PB-PC-PD-PE-PF-PG-PH-PI
198 New Caledonia NC FK
199 New Zealand NZ ZL-ZM
200 New Zealand Subantarctic Islands NZ ZL9
201 Nicaragua NI YN-H6-H7-HT
202 Niger NE 5U
203 Nigeria NG 5N
204 Niue NU ZK2
205 Norfolk Island NF VK9N
206 Northern Ireland NIE 2I-MI-MN-GI-GN
207 Northern Mariana Islands MP KH0
208 Norway NO LA-LB-LC-LD-LE-LF-LG-LH-LI-LJ-LK-LL-LM-LN
209 Oman OM A4-YP-YQ-YR
210 Pakistan PK AP
211 Palau PW T8
212 Palestine State of PS E4
213 Palmyra & Jarvis Island UM KH5
214 Panama PA HO-HP
215 Papua New Guinea PG P2
216 Paraguay PY ZP
217 Peru PE OA-OB-OC
218 Philippines PH DU-DV-DW-DX-DY-DZ
219 Pitcairn PN VP6
220 Poland PL 3Z6-SN-SO-SP-SQ-SR
221 Portugal PT CQ0-CQ1-CQ2-CQ3-CQ7-CQ8-CR1-CR2-CR3-CR5-CR6-CR7-CR8-CR9-CS2-CS3-CS4-CS5-CS7-CS8-CT1-CT2-CT3-CT4-CT5-CT6-CT7-CT8-CT9-CU0-CU1-CU2-CU3-CU4-CU5-CU6-CU7-CU8-CU
222 Pratas Islands BV9P
223 Prince Edward & Marion Islands ZA ZS8
224 Puerto Rico PR KP3-KP4
225 Qatar QA A7
226 Reunion RE FR
227 Revillagigedo Islands MX XA4-XB4-XC4-XD4-XE4-XF4-XG4-XH4-XI4
228 Rodriguez Island MU 3B9
229 Romania RO YO-YP-YQ-YR
230 Rwanda RW 9X
231 Sable Island CA CY0
232 Saint Barthelemy BL FJ
233 Saint Helena SH ZD7
234 Saint Kitts and Nevis KN V4
235 Saint Lucia LC J6
236 Saint Martin (French part) MF FS
237 Saint Pierre and Miquelon PM FP
238 Saint Vincent and the Grenadines VC J8
239 Samoa WS 5W
240 San Marino SM T7
241 Sao Tome and Principe ST S9
242 Sardinia IT IS0-IM0
243 Saudi Arabia SA HZ
244 Scarborough Reef BS7
245 Scotland SH 2M-MM-MS-GM-GS
246 Senegal SN 6V-6W
247 Serbia RS YT-YU
248 Seychelles SC S7
249 Sierra Leone SL 9L
250 Singapore SG 9V
251 Sint Eustatius and Saba NL PJ5-PJ6
252 Sint Maarten (Dutch part) SX PJ7
253 Slovakia SK OM
254 Slovenia SI S5
255 Solomon Islands SB H4
256 Somalia SO T5-6O
257 South Africa ZA ZR-ZS-ZT-ZU
258 South Georgia and the South Sandwich Islands GS VP8S
259 South Sudan SS Z8
260 Spain ES EA-EB-EC-ED-EE-EF-EG-EH
261 Sri Lanka LK 4S
262 St. Paul Island US CY9
263 Sudan SD ST
264 Suriname SR PZ
265 Svalbard NO JW
266 Swaziland SZ 3DA
267 Sweden SE SA-SB-SC-SD-SE-SF-SG-SH-SI-SJ-SK-SL-SM-7S-8S
268 Switzerland CH HB
269 Syrian Arab Republic SY YK
270 Taiwan Province of China TW BM-BO-BU-BV-BW-BX
271 Tajikistan TJ EY
272 Tanzania United Republic of TZ 5H-5I
273 Temotu Province SB H40
274 Thailand TH HS-E2
275 Timor-Leste TL 4W
276 Togo TG 5V
277 Tokelau TK ZK3
278 Tonga TO A3
279 Trinidad and Tobago TT 9Y-9Z
280 Tristan da Cunha & Gough Island SH ZD9
281 Tunisia TN 3V
282 Turkey TR TA-TB-TC
283 Turkmenistan TM EZ
284 Turks and Caicos Islands TC VP5
285 Tuvalu TV T2
286 Uganda UG 5X
287 UK Sov. Base Areas on Cyprus CY ZC4
288 Ukraine UA UR-US-UT-UU-UV-UW-UX-UY-UZ-EM-EN-EO
289 United Arab Emirates AE A6
290 United States US AA-AB-AC-AD-AE-AF-AG-AH-AI-AJ-AK-K0-K1-K2-K3-K4-K5-K6-K7-K8-K9-KA-KB-KC-KD-KE-KF-KG-KH-KI-KJ-KK-KM-KN-KO-KP-KQ-KR-KS-KT-KU-KV-KW-KX-KY-KZ-N0-N1-N2-N3-N4-N5-N6-N7-N8-N9-NA-NB-NC-ND-NE-NF-NG-NH-NI-NJ-NK-NM-NN-NO-NP-NQ-NR-NS-NT-NU-NV-NW-NX-NY-NZ-W0-W1-W2-W3-W4-W5-W6-W7-W8-W9-WA-WB-WC-WD-WE-WF-WG-WH-WI-WJ-WK-WM-WN-WO-WP-WQ-WR-WS-WT-WU-WV-WW-WX-WY-WZ
291 Uruguay UY CV-CW-CX
292 Uzbekistan UZ UJ-UK-UL-UM
293 Vanuatu VU YJ
294 Venezuela Bolivarian Republic of VE YV-YW-YX-YY-4M
295 Aves Island VE YV0
296 Viet Nam VN 3W-XV
297 Virgin Islands British VG VP2V
298 Virgin Islands U.S. VI KP2
299 Wake Island US KH9
300 Wales WL 2W-MW-MC-GW-GC
301 Wallis and Futuna WF FW
302 West Malaysia MY 9M2-9M4-9W2-9W4
303 Western Kiribati (Gilbert Island) KI T30
304 Western Sahara EH S0
305 Willis Island AU VK9W
306 Yemen YE 7O
307 Zambia ZM 9I-9J
308 Zimbabwe ZW Z2
309 GATE GATE REF-XRF

View file

@ -0,0 +1,228 @@
<?php
function sanitize_output($string) {
if ($string === null) return '';
return htmlspecialchars($string, ENT_QUOTES | ENT_HTML5, 'UTF-8');
}
function sanitize_attribute($string) {
if ($string === null) return '';
return htmlspecialchars($string, ENT_QUOTES | ENT_HTML5, 'UTF-8');
}
function validate_callsign($callsign) {
$callsign = trim($callsign);
if (preg_match('/^[A-Z0-9\-\/\s]{3,20}$/i', $callsign)) {
return strtoupper($callsign);
}
return '';
}
function validate_module($module) {
$module = trim(strtoupper($module));
if (preg_match('/^[A-Z]$/', $module)) {
return $module;
}
return '';
}
function validate_protocol($protocol) {
$allowed = ['DPlus', 'DExtra', 'DCS', 'DMR', 'YSF', 'DEXTRA', 'DPLUS', 'DMRMmdvm', 'XLX'];
return in_array(trim($protocol), $allowed, true) ? trim($protocol) : '';
}
function GetSystemUptime() {
if (file_exists('/proc/uptime')) {
$uptime = @file_get_contents('/proc/uptime');
if ($uptime !== false) {
$parts = explode(' ', $uptime);
return isset($parts[0]) ? (int)$parts[0] : 0;
}
}
return 0;
}
function Debug($message) {
if (defined('DEBUG_MODE') && DEBUG_MODE === true) {
echo '<br><hr><pre>';
print_r($message); // Don't sanitize here as it's debug only
echo '</pre><hr><br>';
}
}
function ParseTime($Input) {
if (empty($Input) || !is_string($Input)) {
return false;
}
$Input = strip_tags($Input); // Remove any HTML tags
if (strpos($Input, "<") !== false) {
$Input = substr($Input, 0, strpos($Input, "<"));
}
// Tuesday Tue Nov 17 14:23:22 2015
$tmp = explode(" ", $Input);
// Add bounds checking
if (count($tmp) < 6) {
return false;
}
if (strlen(trim($tmp[3])) == 0) {
unset($tmp[3]);
$tmp = array_values($tmp);
}
// Check array indices exist after potential unset
if (!isset($tmp[4]) || !isset($tmp[2]) || !isset($tmp[3]) || !isset($tmp[5])) {
return false;
}
$tmp1 = explode(":", $tmp[4]);
// Check time parts exist
if (count($tmp1) < 3) {
return false;
}
$month = "";
switch (strtolower($tmp[2])) {
case 'jan' : $month = 1; break;
case 'feb' : $month = 2; break;
case 'mar' : $month = 3; break;
case 'apr' : $month = 4; break;
case 'may' : $month = 5; break;
case 'jun' : $month = 6; break;
case 'jul' : $month = 7; break;
case 'aug' : $month = 8; break;
case 'sep' : $month = 9; break;
case 'oct' : $month = 10; break;
case 'nov' : $month = 11; break;
case 'dec' : $month = 12; break;
default : $month = 1;
}
return @mktime($tmp1[0], $tmp1[1], $tmp1[2], $month, $tmp[3], $tmp[5]);
}
function FormatSeconds($seconds) {
$seconds = abs($seconds);
return sprintf("%d days %02d:%02d:%02d", $seconds/60/60/24,($seconds/60/60)%24,($seconds/60)%60,$seconds%60);
}
function CreateCode ($laenge) {
$zeichen = "1234567890abcdefghijklmnopqrstuvwyxzABCDEFGHIJKLMNAOPQRSTUVWYXZ";
$out = "";
for ($i=1;$i<=$laenge;$i++){
$out .= $zeichen[mt_rand(0,(strlen($zeichen)-1))];
}
return $out;
}
function VNStatLocalize($str) {
global $L;
if (isset($L[$str])) {
return $L[$str];
}
else {
return $str;
}
}
function VNStatGetData($iface, $vnstat_bin) {
// Validate interface name (only allow alphanumeric, dash, underscore)
if (!preg_match('/^[a-zA-Z0-9_-]+$/', $iface)) {
return null;
}
// Validate vnstat binary path
if (!file_exists($vnstat_bin) || !is_executable($vnstat_bin)) {
return null;
}
// Escape shell arguments
$iface_escaped = escapeshellarg($iface);
$vnstat_bin_escaped = escapeshellarg($vnstat_bin);
$vnstat_data = array();
$fd = @popen("$vnstat_bin_escaped --dumpdb -i $iface_escaped", "r");
if (is_resource($fd)) {
$buffer = '';
while (!feof($fd)) {
$buffer .= fgets($fd);
}
$vnstat_data = explode("\n", $buffer);
pclose($fd);
}
$day = array();
$hour = array();
$month = array();
$top = array();
if (isset($vnstat_data[0]) && strpos($vnstat_data[0], 'Error') !== false) {
return;
}
foreach($vnstat_data as $line) {
$d = explode(';', trim($line));
if ($d[0] == 'd') {
$day[$d[1]]['time'] = $d[2];
$day[$d[1]]['rx'] = $d[3] * 1024 + $d[5];
$day[$d[1]]['tx'] = $d[4] * 1024 + $d[6];
$day[$d[1]]['act'] = $d[7];
$day[$d[1]]['rx2'] = $d[5];
$day[$d[1]]['tx2'] = $d[6];
}
else if ($d[0] == 'm') {
$month[$d[1]]['time'] = $d[2];
$month[$d[1]]['rx'] = $d[3] * 1024 + $d[5];
$month[$d[1]]['tx'] = $d[4] * 1024 + $d[6];
$month[$d[1]]['act'] = $d[7];
$month[$d[1]]['rx2'] = $d[5];
$month[$d[1]]['tx2'] = $d[6];
}
else if ($d[0] == 'h') {
$hour[$d[1]]['time'] = $d[2];
$hour[$d[1]]['rx'] = $d[3];
$hour[$d[1]]['tx'] = $d[4];
$hour[$d[1]]['act'] = 1;
}
else if ($d[0] == 't') {
$top[$d[1]]['time'] = $d[2];
$top[$d[1]]['rx'] = $d[3] * 1024 + $d[5];
$top[$d[1]]['tx'] = $d[4] * 1024 + $d[6];
$top[$d[1]]['act'] = $d[7];
}
else {
$summary[$d[0]] = isset($d[1]) ? $d[1] : '';
}
}
rsort($day);
rsort($month);
rsort($hour);
return array($day, $month, $hour, $day, $month, $top, $summary);
}
function kbytes_to_string($kb) {
$byte_notation = null;
$units = array('TB','GB','MB','KB');
$scale = 1024*1024*1024;
$ui = 0;
$custom_size = isset($byte_notation) && in_array($byte_notation, $units);
while ((($kb < $scale) && ($scale > 1)) || $custom_size) {
$ui++;
$scale = $scale / 1024;
if ($custom_size && $units[$ui] == $byte_notation) {
break;
}
}
return sprintf("%0.2f %s", ($kb/$scale),$units[$ui]);
}
?>

View file

@ -0,0 +1,4 @@
<div width="100%" style="text-align:center;">
<iframe width="1050" height="800" src="http://ccs001.xreflector.net/live_seite/bndex.html" style="border:0px #000000 solid; margin-top:30px;" align="center"></iframe>
</div>

View file

@ -0,0 +1,4 @@
<div width="100%" style="text-align:center;">
<iframe width="1250" height="800" src="http://live.ircddb.net:8080/ircddblive5.html" style="border:0px #000000 solid; margin-top:30px;" align="center"></iframe>
</div>

View file

@ -0,0 +1,51 @@
<table class="listingtable">
<tr>
<th width="80" rowspan="2">Module</th>
<th width="130" rowspan="2">Name</th>
<th width="65" rowspan="2">Users</th>
<th colspan="2">DPlus</th>
<th colspan="2">DExtra</th>
<th colspan="2">DCS</th>
<th width="65" rowspan="2">DMR</th>
<th width="65" rowspan="2">YSF<br />DG-ID</th>
</tr>
<tr>
<th width="100">URCALL</th>
<th width="100">DTMF</th>
<th width="100">URCALL</th>
<th width="100">DTMF</th>
<th width="100">URCALL</th>
<th width="100">DTMF</th>
</tr>
<?php
$ReflectorNumber = substr($Reflector->GetReflectorName(), 3, 3);
$NumberOfModules = isset($PageOptions['NumberOfModules']) ? min(max($PageOptions['NumberOfModules'],0),26) : 26;
$odd = "";
for ($i = 1; $i <= $NumberOfModules; $i++) {
$module = chr(ord('A')+($i-1));
if ($odd == "#FFFFFF") { $odd = "#F1FAFA"; } else { $odd = "#FFFFFF"; }
echo '
<tr height="30" bgcolor="'.$odd.'" onMouseOver="this.bgColor=\'#FFFFCA\';" onMouseOut="this.bgColor=\''.$odd.'\';">
<td align="center">'. sanitize_output($module) .'</td>
<td align="center">'. sanitize_output(empty($PageOptions['ModuleNames'][$module]) ? '-' : $PageOptions['ModuleNames'][$module]) .'</td>
<td align="center">'. count($Reflector->GetNodesInModulesByID($module)) .'</td>
<td align="center">'. sanitize_output('REF' . $ReflectorNumber . $module . 'L') .'</td>
<td align="center">'. sanitize_output(is_numeric($ReflectorNumber) ? '*' . sprintf('%01d',$ReflectorNumber) . (($i<=4)?$module:sprintf('%02d',$i)) : '-') .'</td>
<td align="center">'. sanitize_output('XRF' . $ReflectorNumber . $module . 'L') .'</td>
<td align="center">'. sanitize_output(is_numeric($ReflectorNumber) ? 'B' . sprintf('%01d',$ReflectorNumber) . (($i<=4)?$module:sprintf('%02d',$i)) : '-') .'</td>
<td align="center">'. sanitize_output('DCS' . $ReflectorNumber . $module . 'L') .'</td>
<td align="center">'. sanitize_output(is_numeric($ReflectorNumber) ? 'D' . sprintf('%01d',$ReflectorNumber) . (($i<=4)?$module:sprintf('%02d',$i)) : '-') .'</td>
<td align="center">'. sanitize_output(4000+$i) .'</td>
<td align="center">'. sanitize_output(9+$i) .'</td>
</tr>';
}
?>
</table>

88
dashboard1/pgs/peers.php Normal file
View file

@ -0,0 +1,88 @@
<?php
$Result = @fopen($CallingHome['ServerURL']."?do=GetReflectorList", "r");
$INPUT = "";
if ($Result) {
while (!feof ($Result)) {
$INPUT .= fgets ($Result, 1024);
}
$XML = new ParseXML();
$Reflectorlist = $XML->GetElement($INPUT, "reflectorlist");
$Reflectors = $XML->GetAllElements($Reflectorlist, "reflector");
}
fclose($Result);
?>
<table class="listingtable">
<tr>
<th width="25">#</th>
<th width="100">XLX Peer</th>
<th width="154">Last Heard</th>
<th width="156">Linked for</th>
<th width="90">Protocol</th>
<th width="67">Module</th><?php
if ($PageOptions['PeerPage']['IPModus'] != 'HideIP') {
echo '
<th width="125">IP</th>';
}
?>
</tr>
<?php
$odd = "";
$Reflector->LoadFlags();
for ($i=0;$i<$Reflector->PeerCount();$i++) {
if ($odd == "#FFFFFF") { $odd = "#F1FAFA"; } else { $odd = "#FFFFFF"; }
echo '
<tr height="30" bgcolor="'.$odd.'" onMouseOver="this.bgColor=\'#FFFFCA\';" onMouseOut="this.bgColor=\''.$odd.'\';">
<td align="center">'.($i+1).'</td>';
$Name = $Reflector->Peers[$i]->GetCallSign();
$URL = '';
for ($j=1;$j<count($Reflectors);$j++) {
if ($Name === $XML->GetElement($Reflectors[$j], "name")) {
$URL = $XML->GetElement($Reflectors[$j], "dashboardurl");
}
}
if ($Result && (trim($URL) != "")) {
echo '
<td><a href="'.sanitize_attribute($URL).'" target="_blank" class="listinglink" title="Visit the Dashboard of&nbsp;'.sanitize_attribute($Name).'" style="text-decoration:none;color:#000000;">'.sanitize_output($Name).'</a></td>';
} else {
echo '
<td>'.sanitize_output($Name).'</td>';
}
echo '
<td>'.sanitize_output(date("d.m.Y H:i", $Reflector->Peers[$i]->GetLastHeardTime())).'</td>
<td>'.sanitize_output(FormatSeconds(time()-$Reflector->Peers[$i]->GetConnectTime())).' s</td>
<td align="center">'.sanitize_output($Reflector->Peers[$i]->GetProtocol()).'</td>
<td align="center">'.sanitize_output($Reflector->Peers[$i]->GetLinkedModule()).'</td>';
if ($PageOptions['PeerPage']['IPModus'] != 'HideIP') {
echo '
<td>';
$Bytes = explode(".", $Reflector->Peers[$i]->GetIP());
if ($Bytes !== false && count($Bytes) == 4) {
switch ($PageOptions['PeerPage']['IPModus']) {
case 'ShowLast1ByteOfIP' : echo sanitize_output($PageOptions['PeerPage']['MasqueradeCharacter'].'.'.$PageOptions['PeerPage']['MasqueradeCharacter'].'.'.$PageOptions['PeerPage']['MasqueradeCharacter'].'.'.$Bytes[3]); break;
case 'ShowLast2ByteOfIP' : echo sanitize_output($PageOptions['PeerPage']['MasqueradeCharacter'].'.'.$PageOptions['PeerPage']['MasqueradeCharacter'].'.'.$Bytes[2].'.'.$Bytes[3]); break;
case 'ShowLast3ByteOfIP' : echo sanitize_output($PageOptions['PeerPage']['MasqueradeCharacter'].'.'.$Bytes[1].'.'.$Bytes[2].'.'.$Bytes[3]); break;
default : echo sanitize_output($Reflector->Peers[$i]->GetIP());
}
}
echo '</td>';
}
echo '
</tr>';
if ($i == $PageOptions['PeerPage']['LimitTo']) { $i = $Reflector->PeerCount()+1; }
}
?>
</table>

View file

@ -0,0 +1,52 @@
<?php
$Result = @fopen($CallingHome['ServerURL']."?do=GetReflectorList", "r");
if (!$Result) die("HEUTE GIBTS KEIN BROT");
$INPUT = "";
while (!feof ($Result)) {
$INPUT .= fgets ($Result, 1024);
}
fclose($Result);
$XML = new ParseXML();
$Reflectorlist = $XML->GetElement($INPUT, "reflectorlist");
$Reflectors = $XML->GetAllElements($Reflectorlist, "reflector");
?>
<table class="listingtable">
<tr>
<th width="40">#</th>
<th width="75">Reflector</th>
<th width="120">Country</th>
<th width="90">Service</th>
<th width="400">Comment</th>
</tr>
<?php
$odd = "";
for ($i=0;$i<count($Reflectors);$i++) {
$NAME = sanitize_output($XML->GetElement($Reflectors[$i], "name"));
$COUNTRY = sanitize_output($XML->GetElement($Reflectors[$i], "country"));
$LASTCONTACT = intval($XML->GetElement($Reflectors[$i], "lastcontact"));
$COMMENT = sanitize_output($XML->GetElement($Reflectors[$i], "comment"));
$DASHBOARDURL = sanitize_attribute($XML->GetElement($Reflectors[$i], "dashboardurl"));
if ($odd == "#FFFFFF") { $odd = "#F1FAFA"; } else { $odd = "#FFFFFF"; }
echo '
<tr height="30" bgcolor="'.$odd.'" onMouseOver="this.bgColor=\'#FFFFCA\';" onMouseOut="this.bgColor=\''.$odd.'\';">
<td align="center">'.($i+1).'</td>
<td><a href="'.$DASHBOARDURL.'" target="_blank" class="listinglink" title="Visit the Dashboard of&nbsp;'.$NAME.'">'.$NAME.'</a></td>
<td>'.$COUNTRY.'</td>
<td align="center" valign="middle"><img src="./img/'; if ($LASTCONTACT<(time()-1800)) { echo 'down'; } ELSE { echo 'up'; } echo '.png" height="25" /></td>
<td>'.$COMMENT.'</td>
</tr>';
}
?>
</table>

View file

@ -0,0 +1,228 @@
<?php
// Initialize filter session variables
if (!isset($_SESSION['FilterCallSign'])) {
$_SESSION['FilterCallSign'] = null;
}
if (!isset($_SESSION['FilterProtocol'])) {
$_SESSION['FilterProtocol'] = null;
}
if (!isset($_SESSION['FilterModule'])) {
$_SESSION['FilterModule'] = null;
}
// Validate filter inputs
if (isset($_SESSION['FilterCallSign']) && $_SESSION['FilterCallSign'] !== null) {
$_SESSION['FilterCallSign'] = preg_replace('/[^A-Z0-9\*\-\/\s]/i', '', $_SESSION['FilterCallSign']);
}
if (isset($_SESSION['FilterProtocol']) && $_SESSION['FilterProtocol'] !== null) {
$_SESSION['FilterProtocol'] = validate_protocol($_SESSION['FilterProtocol']);
}
if (isset($_SESSION['FilterModule']) && $_SESSION['FilterModule'] !== null) {
$_SESSION['FilterModule'] = validate_module($_SESSION['FilterModule']);
}
if (isset($_POST['do'])) {
if ($_POST['do'] == 'SetFilter') {
if (isset($_POST['txtSetCallsignFilter'])) {
$_POST['txtSetCallsignFilter'] = trim($_POST['txtSetCallsignFilter']);
if ($_POST['txtSetCallsignFilter'] == "") {
$_SESSION['FilterCallSign'] = null;
}
else {
$_SESSION['FilterCallSign'] = $_POST['txtSetCallsignFilter'];
if (strpos($_SESSION['FilterCallSign'], "*") === false) {
$_SESSION['FilterCallSign'] = "*".$_SESSION['FilterCallSign']."*";
}
}
}
if (isset($_POST['txtSetProtocolFilter'])) {
$_POST['txtSetProtocolFilter'] = trim($_POST['txtSetProtocolFilter']);
if ($_POST['txtSetProtocolFilter'] == "") {
$_SESSION['FilterProtocol'] = null;
}
else {
$_SESSION['FilterProtocol'] = $_POST['txtSetProtocolFilter'];
}
}
if (isset($_POST['txtSetModuleFilter'])) {
$_POST['txtSetModuleFilter'] = trim($_POST['txtSetModuleFilter']);
if ($_POST['txtSetModuleFilter'] == "") {
$_SESSION['FilterModule'] = null;
}
else {
$_SESSION['FilterModule'] = $_POST['txtSetModuleFilter'];
}
}
}
}
if (isset($_GET['do'])) {
if ($_GET['do'] == "resetfilter") {
$_SESSION['FilterModule'] = null;
$_SESSION['FilterProtocol'] = null;
$_SESSION['FilterCallSign'] = null;
}
}
?>
<table class="listingtable"><?php
if ($PageOptions['UserPage']['ShowFilter']) {
echo '
<tr>
<th colspan="9">
<table width="100%" border="0">
<tr>
<td align="left">
<form name="frmFilterCallSign" method="post" action="./index.php?show=repeaters">
<input type="hidden" name="do" value="SetFilter" />
<input type="text" class="FilterField" value="'.sanitize_attribute($_SESSION['FilterCallSign']).'" name="txtSetCallsignFilter" placeholder="Callsign" onfocus="SuspendPageRefresh();" onblur="setTimeout(ReloadPage, '.$PageOptions['PageRefreshDelay'].');" />
<input type="submit" value="Apply" class="FilterSubmit" />
</form>
</td>';
if (($_SESSION['FilterModule'] != null) || ($_SESSION['FilterCallSign'] != null) || ($_SESSION['FilterProtocol'] != null)) {
echo '
<td><a href="./index.php?show=repeaters&do=resetfilter" class="smalllink">Disable filters</a></td>';
}
echo '
<td align="right" style="padding-right:3px;">
<form name="frmFilterProtocol" method="post" action="./index.php?show=repeaters">
<input type="hidden" name="do" value="SetFilter" />
<input type="text" class="FilterField" value="'.sanitize_attribute($_SESSION['FilterProtocol']).'" name="txtSetProtocolFilter" placeholder="Protocol" onfocus="SuspendPageRefresh();" onblur="setTimeout(ReloadPage, '.$PageOptions['PageRefreshDelay'].');" />
<input type="submit" value="Apply" class="FilterSubmit" />
</form>
</td>
<td align="right" style="padding-right:3px;">
<form name="frmFilterModule" method="post" action="./index.php?show=repeaters">
<input type="hidden" name="do" value="SetFilter" />
<input type="text" class="FilterField" value="'.sanitize_attribute($_SESSION['FilterModule']).'" name="txtSetModuleFilter" placeholder="Module" onfocus="SuspendPageRefresh();" onblur="setTimeout(ReloadPage, '.$PageOptions['PageRefreshDelay'].');" />
<input type="submit" value="Apply" class="FilterSubmit" />
</form>
</td>
</table>
</th>
</tr>';
}
?>
<tr>
<th width="25">#</th>
<th width="60">Flag</th>
<th width="100">DV Station</th>
<th width="75">Band</th>
<th width="150">Last Heard</th>
<th width="150">Linked for</th>
<th width="90">Protocol</th>
<th width="65">Module</th><?php
if ($PageOptions['RepeatersPage']['IPModus'] != 'HideIP') {
echo '
<th width="125">IP</th>';
}
?>
</tr>
<?php
$odd = "";
$Reflector->LoadFlags();
for ($i=0;$i<$Reflector->NodeCount();$i++) {
$ShowThisStation = true;
if ($PageOptions['UserPage']['ShowFilter']) {
$CS = true;
if ($_SESSION['FilterCallSign'] != null) {
if (!fnmatch($_SESSION['FilterCallSign'], $Reflector->Nodes[$i]->GetCallSign(), FNM_CASEFOLD)) {
$CS = false;
}
}
$MO = true;
if ($_SESSION['FilterModule'] != null) {
if (trim(strtolower($_SESSION['FilterModule'])) != strtolower($Reflector->Nodes[$i]->GetLinkedModule())) {
$MO = false;
}
}
$PR = true;
if ($_SESSION['FilterProtocol'] != null) {
if (trim(strtolower($_SESSION['FilterProtocol'])) != strtolower($Reflector->Nodes[$i]->GetProtocol())) {
$PR = false;
}
}
$ShowThisStation = ($CS && $MO && $PR);
}
if ($ShowThisStation) {
if ($odd == "#FFFFFF") { $odd = "#F1FAFA"; } else { $odd = "#FFFFFF"; }
echo '
<tr height="30" bgcolor="'.$odd.'" onMouseOver="this.bgColor=\'#FFFFCA\';" onMouseOut="this.bgColor=\''.$odd.'\';">
<td align="center">'.($i+1).'</td>
<td align="center">';
list ($Flag, $Name) = $Reflector->GetFlag($Reflector->Nodes[$i]->GetCallSign());
if (file_exists("./img/flags/".$Flag.".png")) {
echo '<a href="#" class="tip"><img src="./img/flags/'.sanitize_attribute($Flag).'.png" height="15" alt="'.sanitize_attribute($Name).'" /><span>'.sanitize_output($Name).'</span></a>';
}
echo '</td>
<td><a href="http://www.aprs.fi/'.sanitize_attribute($Reflector->Nodes[$i]->GetCallSign());
if ($Reflector->Nodes[$i]->GetSuffix() != "") echo '-'.sanitize_attribute($Reflector->Nodes[$i]->GetSuffix());
echo '" class="pl" target="_blank">'.sanitize_output($Reflector->Nodes[$i]->GetCallSign());
if ($Reflector->Nodes[$i]->GetSuffix() != "") { echo '-'.sanitize_output($Reflector->Nodes[$i]->GetSuffix()); }
echo '</a></td>
<td>';
if (($Reflector->Nodes[$i]->GetPrefix() == 'REF') || ($Reflector->Nodes[$i]->GetPrefix() == 'XRF')) {
switch ($Reflector->Nodes[$i]->GetPrefix()) {
case 'REF' : echo 'REF-Link'; break;
case 'XRF' : echo 'XRF-Link'; break;
}
}
else {
switch ($Reflector->Nodes[$i]->GetSuffix()) {
case 'A' : echo '23cm'; break;
case 'B' : echo '70cm'; break;
case 'C' : echo '2m'; break;
case 'D' : echo 'Dongle'; break;
case 'G' : echo 'Internet-Gateway'; break;
default : echo '';
}
}
echo '</td>
<td>'.sanitize_output(date("d.m.Y H:i", $Reflector->Nodes[$i]->GetLastHeardTime())).'</td>
<td>'.sanitize_output(FormatSeconds(time()-$Reflector->Nodes[$i]->GetConnectTime())).' s</td>
<td>'.sanitize_output($Reflector->Nodes[$i]->GetProtocol()).'</td>
<td align="center">'.sanitize_output($Reflector->Nodes[$i]->GetLinkedModule()).'</td>';
if ($PageOptions['RepeatersPage']['IPModus'] != 'HideIP') {
echo '
<td>';
$Bytes = explode(".", $Reflector->Nodes[$i]->GetIP());
if ($Bytes !== false && count($Bytes) == 4) {
switch ($PageOptions['RepeatersPage']['IPModus']) {
case 'ShowLast1ByteOfIP' : echo sanitize_output($PageOptions['RepeatersPage']['MasqueradeCharacter'].'.'.$PageOptions['RepeatersPage']['MasqueradeCharacter'].'.'.$PageOptions['RepeatersPage']['MasqueradeCharacter'].'.'.$Bytes[3]); break;
case 'ShowLast2ByteOfIP' : echo sanitize_output($PageOptions['RepeatersPage']['MasqueradeCharacter'].'.'.$PageOptions['RepeatersPage']['MasqueradeCharacter'].'.'.$Bytes[2].'.'.$Bytes[3]); break;
case 'ShowLast3ByteOfIP' : echo sanitize_output($PageOptions['RepeatersPage']['MasqueradeCharacter'].'.'.$Bytes[1].'.'.$Bytes[2].'.'.$Bytes[3]); break;
default : echo sanitize_output($Reflector->Nodes[$i]->GetIP());
}
}
echo '</td>';
}
echo '
</tr>';
}
if ($i == $PageOptions['RepeatersPage']['LimitTo']) { $i = $Reflector->NodeCount()+1; }
}
?>
</table>

103
dashboard1/pgs/traffic.php Normal file
View file

@ -0,0 +1,103 @@
<?php
if (!isset($_GET['iface'])) {
if (isset($VNStat['Interfaces'][0]['Address'])) {
$_GET['iface'] = $VNStat['Interfaces'][0]['Address'];
}
else {
$_GET['iface'] = "";
}
}
// Validate interface name against whitelist
if (!empty($_GET['iface'])) {
$valid = false;
for ($i = 0; $i < count($VNStat['Interfaces']); $i++) {
if ($_GET['iface'] === $VNStat['Interfaces'][$i]['Address']) {
$valid = true;
break;
}
}
if (!$valid) {
$_GET['iface'] = "";
}
}
?>
<table class="listingtable">
<tr>
<th>Network interfaces</th>
<th>Statistics</th>
</tr>
<tr>
<td bgcolor="#F1FAFA" align="left" valign="top" style="padding-left:5px;"><?php
for ($i=0;$i<count($VNStat['Interfaces']);$i++) {
echo '<a href="./index.php?show=traffic&iface='.sanitize_attribute($VNStat['Interfaces'][$i]['Address']).'" class="listinglink">'.sanitize_output($VNStat['Interfaces'][$i]['Name']).'</a>';
if ($i < count($VNStat['Interfaces'])-1) {
echo '<br />';
}
}
?></td>
<td bgcolor="#FFFFFF"><?php
$Data = VNStatGetData($_GET['iface'], $VNStat['Binary']);
echo '
<table style="margin:10px;">
<tr>
<td>Day</td>
<td>RX</td>
<td>TX</td>
<td>Avg Rx</td>
<td>Avg TX</td>
</tr>';
for ($i=0;$i<count($Data[0]);$i++) {
if ($Data[0][$i]['time'] > 0) {
echo '
<tr>
<td width="100">'.date("d.m.Y", $Data[0][$i]['time']).'</td>
<td width="100">'.kbytes_to_string($Data[0][$i]['rx']).'</td>
<td width="100">'.kbytes_to_string($Data[0][$i]['tx']).'</td>
<td width="100">'.kbytes_to_string($Data[0][$i]['rx2']).'</td>
<td width="100">'.kbytes_to_string($Data[0][$i]['tx2']).'</td>
</tr>';
}
}
echo '</table>';
echo '
<table style="margin:10px;">
<tr>
<td>Month</td>
<td>RX</td>
<td>TX</td>
<td>Avg Rx</td>
<td>Avg TX</td>
</tr>';
for ($i=0;$i<count($Data[1]);$i++) {
if ($Data[1][$i]['time'] > 0) {
echo '
<tr>
<td width="100">'.date("F", $Data[1][$i]['time']).'</td>
<td width="100">'.kbytes_to_string($Data[1][$i]['rx']).'</td>
<td width="100">'.kbytes_to_string($Data[1][$i]['tx']).'</td>
<td width="100">'.kbytes_to_string($Data[1][$i]['rx2']).'</td>
<td width="100">'.kbytes_to_string($Data[1][$i]['tx2']).'</td>
</tr>';
}
}
echo '</table>';
?>
</td>
</tr>
</table>

240
dashboard1/pgs/users.php Normal file
View file

@ -0,0 +1,240 @@
<?php
if (!isset($_SESSION['FilterCallSign'])) {
$_SESSION['FilterCallSign'] = null;
}
if (!isset($_SESSION['FilterModule'])) {
$_SESSION['FilterModule'] = null;
}
if (isset($_POST['do'])) {
if ($_POST['do'] == 'SetFilter') {
if (isset($_POST['txtSetCallsignFilter'])) {
$_POST['txtSetCallsignFilter'] = trim($_POST['txtSetCallsignFilter']);
if ($_POST['txtSetCallsignFilter'] == "") {
$_SESSION['FilterCallSign'] = null;
}
else {
$_SESSION['FilterCallSign'] = $_POST['txtSetCallsignFilter'];
if (strpos($_SESSION['FilterCallSign'], "*") === false) {
$_SESSION['FilterCallSign'] = "*".$_SESSION['FilterCallSign']."*";
}
}
}
if (isset($_POST['txtSetModuleFilter'])) {
$_POST['txtSetModuleFilter'] = trim($_POST['txtSetModuleFilter']);
if ($_POST['txtSetModuleFilter'] == "") {
$_SESSION['FilterModule'] = null;
}
else {
$_SESSION['FilterModule'] = $_POST['txtSetModuleFilter'];
}
}
}
}
if (isset($_GET['do'])) {
if ($_GET['do'] == "resetfilter") {
$_SESSION['FilterModule'] = null;
$_SESSION['FilterCallSign'] = null;
}
}
// Validate filter inputs
if (isset($_SESSION['FilterCallSign']) && $_SESSION['FilterCallSign'] !== null) {
$_SESSION['FilterCallSign'] = preg_replace('/[^A-Z0-9\*\-\/\s]/i', '', $_SESSION['FilterCallSign']);
}
if (isset($_SESSION['FilterModule']) && $_SESSION['FilterModule'] !== null) {
$_SESSION['FilterModule'] = validate_module($_SESSION['FilterModule']);
}
?>
<table border="0">
<tr>
<td valign="top">
<table class="listingtable"><?php
if ($PageOptions['UserPage']['ShowFilter']) {
echo '
<tr>
<th colspan="8">
<table width="100%" border="0">
<tr>
<td align="left">
<form name="frmFilterCallSign" method="post" action="./index.php">
<input type="hidden" name="do" value="SetFilter" />
<input type="text" class="FilterField" value="'.sanitize_attribute($_SESSION['FilterCallSign']).'" name="txtSetCallsignFilter" placeholder="Callsign" onfocus="SuspendPageRefresh();" onblur="setTimeout(ReloadPage, '.$PageOptions['PageRefreshDelay'].');" />
<input type="submit" value="Apply" class="FilterSubmit" />
</form>
</td>';
if (($_SESSION['FilterModule'] != null) || ($_SESSION['FilterCallSign'] != null)) {
echo '
<td><a href="./index.php?do=resetfilter" class="smalllink">Disable filters</a></td>';
}
echo '
<td align="right" style="padding-right:3px;">
<form name="frmFilterModule" method="post" action="./index.php">
<input type="hidden" name="do" value="SetFilter" />
<input type="text" class="FilterField" value="'.sanitize_attribute($_SESSION['FilterModule']).'" name="txtSetModuleFilter" placeholder="Module" onfocus="SuspendPageRefresh();" onblur="setTimeout(ReloadPage, '.$PageOptions['PageRefreshDelay'].');" />
<input type="submit" value="Apply" class="FilterSubmit" />
</form>
</td>
</table>
</th>
</tr>';
}
?>
<tr>
<th>#</th>
<th>Flag</th>
<th>Callsign</th>
<th>Suffix</th>
<th>DPRS</th>
<th>Via / Peer</th>
<th>Last heard</th>
<th align="center" valign="middle"><img src="./img/ear.png" alt="Listening on" /></th>
</tr><?php
$Reflector->LoadFlags();
$odd = "";
for ($i=0;$i<$Reflector->StationCount();$i++) {
$ShowThisStation = true;
if ($PageOptions['UserPage']['ShowFilter']) {
$CS = true;
if ($_SESSION['FilterCallSign'] != null) {
if (!fnmatch($_SESSION['FilterCallSign'], $Reflector->Stations[$i]->GetCallSign(), FNM_CASEFOLD)) {
$CS = false;
}
}
$MO = true;
if ($_SESSION['FilterModule'] != null) {
if (trim(strtolower($_SESSION['FilterModule'])) != strtolower($Reflector->Stations[$i]->GetModule())) {
$MO = false;
}
}
$ShowThisStation = ($CS && $MO);
}
if ($ShowThisStation) {
if ($odd == "#FFFFFF") { $odd = "#F1FAFA"; } else { $odd = "#FFFFFF"; }
echo '
<tr height="30" bgcolor="'.$odd.'" onMouseOver="this.bgColor=\'#FFFFCA\';" onMouseOut="this.bgColor=\''.$odd.'\';">
<td align="center" valign="middle" width="35">';
if ($i==0 && $Reflector->Stations[$i]->GetLastHeardTime() > (time() - 60)) {
echo '<img src="./img/tx.gif" style="margin-top:3px;" height="20"/>';
}
else {
echo ($i+1);
}
echo '</td>
<td align="center" width="60">';
list ($Flag, $Name) = $Reflector->GetFlag($Reflector->Stations[$i]->GetCallSign());
if (file_exists("./img/flags/".$Flag.".png")) {
echo '<a href="#" class="tip"><img src="./img/flags/'.sanitize_attribute($Flag).'.png" height="15" alt="'.sanitize_attribute($Name).'" /><span>'.sanitize_output($Name).'</span></a>';
}
echo '</td>
<td width="75"><a href="https://www.qrz.com/db/'.sanitize_attribute($Reflector->Stations[$i]->GetCallsignOnly()).'" class="pl" target="_blank">'.sanitize_output($Reflector->Stations[$i]->GetCallsignOnly()).'</a></td>
<td width="60">'.sanitize_output($Reflector->Stations[$i]->GetSuffix()).'</td>
<td width="50" align="center"><a href="http://www.aprs.fi/'.sanitize_attribute($Reflector->Stations[$i]->GetCallsignOnly()).'" class="pl" target="_blank"><img src="./img/sat.png" /></a></td>
<td width="150">'.sanitize_output($Reflector->Stations[$i]->GetVia());
if ($Reflector->Stations[$i]->GetPeer() != $Reflector->GetReflectorName()) {
echo ' / '.sanitize_output($Reflector->Stations[$i]->GetPeer());
}
echo '</td>
<td width="150">'.sanitize_output(@date("d.m.Y H:i", $Reflector->Stations[$i]->GetLastHeardTime())).'</td>
<td align="center" width="30">'.sanitize_output($Reflector->Stations[$i]->GetModule()).'</td>
</tr>';
}
if ($i == $PageOptions['LastHeardPage']['LimitTo']) { $i = $Reflector->StationCount()+1; }
}
?>
</table>
</td>
<td style="padding-left:50px;" align="center" valign="top">
<table class="listingtable">
<?php
$Modules = $Reflector->GetModules();
sort($Modules, SORT_STRING);
echo '
<tr>';
for ($i=0;$i<count($Modules);$i++) {
if (isset($PageOptions['ModuleNames'][$Modules[$i]])) {
echo '
<th>'.sanitize_output($PageOptions['ModuleNames'][$Modules[$i]]);
if (trim($PageOptions['ModuleNames'][$Modules[$i]]) != "") {
echo '<br />';
}
echo sanitize_output($Modules[$i]).'</th>';
}
else {
echo '
<th>'.sanitize_output($Modules[$i]).'</th>';
}
}
echo '
</tr>
<tr bgcolor="#FFFFFF" style="padding:0px;">';
$GlobalPositions = array();
for ($i=0;$i<count($Modules);$i++) {
$Users = $Reflector->GetNodesInModulesByID($Modules[$i]);
echo '
<td valign="top" style="border:0px;padding:0px;">
<table width="100" border="0" style="padding:0px;margin:0px;">';
$odd = "";
$UserCheckedArray = array();
for ($j=0;$j<count($Users);$j++) {
if ($odd == "#FFFFFF") { $odd = "#F1FAFA"; } else { $odd = "#FFFFFF"; }
$Displayname = $Reflector->GetCallsignAndSuffixByID($Users[$j]);
echo '
<tr height="25" bgcolor="'.$odd.'" onMouseOver="this.bgColor=\'#FFFFCA\';" onMouseOut="this.bgColor=\''.$odd.'\';">
<td valign="top" style="border-bottom:1px #C1DAD7 solid;"><a href="http://www.aprs.fi/'.sanitize_attribute($Displayname).'" class="pl" target="_blank">'.sanitize_output($Displayname).'</a> </td>
</tr>';
$UserCheckedArray[] = $Users[$j];
}
echo '
</table>
</td>';
}
echo '
</tr>';
?>
</table>
</td>
</tr>
</table>