Compare commits

...

6 commits

Author SHA1 Message Date
Diman Todorov 4727ef2244
Merge 48f0d867ad into 32c3241de0 2025-10-14 08:54:36 -07:00
LX1IQ 32c3241de0
Merge pull request #253 from MW0MWZ/master
Dashboard2 XSS / Security fixes
2025-10-14 13:43:36 +02:00
Andy Taylor 80821c25a3 Remove .DS_Store and update .gitignore 2025-10-14 12:26:32 +01:00
Andy Taylor 61204c3ed4 XSS Vulnerability Patches and Security Enhancements for Dashboard2 2025-10-14 12:25:26 +01:00
Diman Todorov 48f0d867ad
Addressed PR comment
Removed last byte of disconnect packet to ensure equivalence with ircdbgw.
2022-09-21 23:47:55 -07:00
Diman Todorov c220fa2b61
Added missing 0x20 in DCS EncodeDisconnectPacket
As is, EncodeDisconnectPacket will fail IsValidDisconnectPacket check. The encoded packet is only has 18 bytes instead of 19 because it's missing a 0x20.
2022-09-03 23:33:30 -07:00
12 changed files with 129 additions and 47 deletions

1
.gitignore vendored
View file

@ -2,3 +2,4 @@
src/xlxd src/xlxd
ambed/ambed ambed/ambed
ambedtest/ambedtest ambedtest/ambedtest
.DS_Store

View file

@ -1,3 +1,28 @@
xlx db v2.3.8
SECURITY UPDATE - XSS Vulnerability Patches and Security Enhancements
- "functions.php" added SafeOutput() and SafeOutputAttr() for XSS protection
added GenerateCSRFToken() and ValidateCSRFToken() for CSRF protection
- "index.php" added session_start() for CSRF token support
added SafeOutput() to all $_GET['show'] outputs
added input whitelist validation for $_GET['show'] parameter
changed file permission from 777 to 600 for hash file (security hardening)
added SafeOutputAttr() to all meta tag outputs
added SafeOutput() to contact email output
improved error messages to prevent information disclosure
- "users.php" added CSRF token validation for all POST requests
added CSRF tokens to both filter forms
added input validation with regex for callsign filter (alphanumeric, dash, asterisk only)
added input validation with regex for module filter (single letter A-Z only)
added SafeOutput() and SafeOutputAttr() to all user data outputs
added SafeOutput() to all callsign, suffix, via, peer, and module outputs
- "repeaters.php" added SafeOutput() to all node callsign, suffix, protocol, and module outputs
added SafeOutput() to all IP address outputs
- "peers.php" added SafeOutput() and SafeOutputAttr() to peer name and URL outputs
added SafeOutput() to protocol, module, and IP address outputs
- "reflectors.php" added SafeOutput() and SafeOutputAttr() to reflector name, country, comment, and URL outputs
- "class.reflector.php" added URL validation in CallHome() method to prevent remote file inclusion attacks
xlx db v2.3.1 xlx db v2.3.1
- "config.inc.php" $CallingHome['InterlinkFile'] added - "config.inc.php" $CallingHome['InterlinkFile'] added
@ -16,7 +41,7 @@ xlx db v2.2.2
This version is a major release with voluntary self-registration feature build in. This version is a major release with voluntary self-registration feature build in.
You need to edit the conf.inc.php to your needs. You need to edit the conf.inc.php to your needs.
On the first run your personal hash to access the database is place in the servers /tmp folder. On the first run your personal hash to access the database is place in the server<EFBFBD>s /tmp folder.
Take care to make a backup of this file because this folder is cleaned up after a server reboot. Take care to make a backup of this file because this folder is cleaned up after a server reboot.
This version is a major release This version is a major release
@ -44,7 +69,7 @@ xlx db v2.1.4
- "class.reflector.php" improved the flag search - "class.reflector.php" improved the flag search
- "country.csv" added serveral prefixes - "country.csv" added serveral prefixes
- "flags" added Puerto Ricco and Åland Islands - "flags" added Puerto Ricco and <EFBFBD>land Islands
xlx db v2.1.3 xlx db v2.1.3

View file

@ -1,4 +1,5 @@
<?php <?php
session_start();
/* /*
* This dashboard is being developed by the DVBrazil Team as a courtesy to * This dashboard is being developed by the DVBrazil Team as a courtesy to
@ -9,12 +10,12 @@
if (file_exists("./pgs/functions.php")) { if (file_exists("./pgs/functions.php")) {
require_once("./pgs/functions.php"); require_once("./pgs/functions.php");
} else { } else {
die("functions.php does not exist."); die("Required file not found.");
} }
if (file_exists("./pgs/config.inc.php")) { if (file_exists("./pgs/config.inc.php")) {
require_once("./pgs/config.inc.php"); require_once("./pgs/config.inc.php");
} else { } else {
die("config.inc.php does not exist."); die("Required file not found.");
} }
if (!class_exists('ParseXML')) require_once("./pgs/class.parsexml.php"); if (!class_exists('ParseXML')) require_once("./pgs/class.parsexml.php");
@ -44,7 +45,7 @@ if ($CallingHome['Active']) {
@fwrite($Ressource, "\n" . '$Hash = "' . $Hash . '";'); @fwrite($Ressource, "\n" . '$Hash = "' . $Hash . '";');
@fwrite($Ressource, "\n\n" . '?>'); @fwrite($Ressource, "\n\n" . '?>');
@fclose($Ressource); @fclose($Ressource);
@exec("chmod 777 " . $CallingHome['HashFile']); @exec("chmod 600 " . $CallingHome['HashFile']);
$CallHomeNow = true; $CallHomeNow = true;
} }
} else { } else {
@ -79,12 +80,11 @@ if ($CallingHome['Active']) {
<meta charset="utf-8"> <meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1"> <meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="description" content="<?php echo $PageOptions['MetaDescription']; ?>"/> <meta name="description" content="<?php echo SafeOutputAttr($PageOptions['MetaDescription']); ?>"/>
<meta name="keywords" content="<?php echo $PageOptions['MetaKeywords']; ?>"/> <meta name="keywords" content="<?php echo SafeOutputAttr($PageOptions['MetaKeywords']); ?>"/>
<meta name="author" content="<?php echo $PageOptions['MetaAuthor']; ?>"/> <meta name="author" content="<?php echo SafeOutputAttr($PageOptions['MetaAuthor']); ?>"/>
<meta name="revisit" content="<?php echo $PageOptions['MetaRevisit']; ?>"/> <meta name="revisit" content="<?php echo SafeOutputAttr($PageOptions['MetaRevisit']); ?>"/>
<meta name="robots" content="<?php echo $PageOptions['MetaAuthor']; ?>"/> <meta name="robots" content="<?php echo SafeOutputAttr($PageOptions['MetaAuthor']); ?>"/>
<meta http-equiv="content-type" content="text/html; charset=utf-8"/> <meta http-equiv="content-type" content="text/html; charset=utf-8"/>
<title><?php echo $Reflector->GetReflectorName(); ?> Reflector Dashboard</title> <title><?php echo $Reflector->GetReflectorName(); ?> Reflector Dashboard</title>
<link rel="icon" href="./favicon.ico" type="image/vnd.microsoft.icon"> <link rel="icon" href="./favicon.ico" type="image/vnd.microsoft.icon">
@ -113,8 +113,8 @@ if ($CallingHome['Active']) {
if (($_SERVER['REQUEST_METHOD'] === 'POST') || isset($_GET['do'])) { if (($_SERVER['REQUEST_METHOD'] === 'POST') || isset($_GET['do'])) {
echo ' echo '
document.location.href = "./index.php'; document.location.href = "./index.php';
if (isset($_GET['show'])) { if (isset($_GET['show']) && $_GET['show'] !== '') {
echo '?show=' . $_GET['show']; echo '?show=' . SafeOutput($_GET['show']);
} }
echo '";'; echo '";';
} else { } else {
@ -194,6 +194,15 @@ if ($CallingHome['Active']) {
} }
} }
// Whitelist allowed values
if (!isset($_GET['show'])) {
$_GET['show'] = '';
}
$allowed_shows = ['users', 'repeaters', 'liveircddb', 'peers', 'reflectors', ''];
if (!in_array($_GET['show'], $allowed_shows, true)) {
$_GET['show'] = '';
}
switch ($_GET['show']) { switch ($_GET['show']) {
case 'users' : case 'users' :
require_once("./pgs/users.php"); require_once("./pgs/users.php");
@ -222,7 +231,7 @@ if ($CallingHome['Active']) {
<footer class="footer"> <footer class="footer">
<div class="container"> <div class="container">
<p><a href="mailto:<?php echo $PageOptions['ContactEmail']; ?>"><?php echo $PageOptions['ContactEmail']; ?></a> <p><a href="mailto:<?php echo SafeOutputAttr($PageOptions['ContactEmail']); ?>"><?php echo SafeOutput($PageOptions['ContactEmail']); ?></a>
</p> </p>
</div> </div>
</footer> </footer>

View file

@ -419,6 +419,10 @@ class xReflector {
} }
public function CallHome() { public function CallHome() {
// Validate URL before making request
if (!filter_var($this->CallingHomeServerURL, FILTER_VALIDATE_URL)) {
return false;
}
$xml = '<?xml version="1.0" encoding="UTF-8" standalone="yes"?> $xml = '<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<query>CallingHome</query>'.$this->ReflectorXML.$this->InterlinkXML; <query>CallingHome</query>'.$this->ReflectorXML.$this->InterlinkXML;
$p = @stream_context_create(array('http' => array('header' => "Content-type: application/x-www-form-urlencoded\r\n", $p = @stream_context_create(array('http' => array('header' => "Content-type: application/x-www-form-urlencoded\r\n",

View file

@ -16,7 +16,7 @@ $PageOptions = array();
$PageOptions['ContactEmail'] = 'your_email'; // Support E-Mail address $PageOptions['ContactEmail'] = 'your_email'; // Support E-Mail address
$PageOptions['DashboardVersion'] = '2.3.7'; // Dashboard Version $PageOptions['DashboardVersion'] = '2.3.8'; // Dashboard Version
$PageOptions['PageRefreshActive'] = true; // Activate automatic refresh $PageOptions['PageRefreshActive'] = true; // Activate automatic refresh
$PageOptions['PageRefreshDelay'] = '10000'; // Page refresh time in miliseconds $PageOptions['PageRefreshDelay'] = '10000'; // Page refresh time in miliseconds

0
dashboard2/pgs/country.csv Executable file → Normal file
View file

View file

@ -59,4 +59,30 @@ function CreateCode ($laenge) {
return $out; return $out;
} }
function SafeOutput($string, $encoding = 'UTF-8') {
return htmlspecialchars($string, ENT_QUOTES | ENT_HTML5, $encoding);
}
function SafeOutputAttr($string, $encoding = 'UTF-8') {
// Extra safe for attributes
return htmlspecialchars($string, ENT_QUOTES | ENT_HTML5, $encoding);
}
function GenerateCSRFToken() {
if (!isset($_SESSION)) {
session_start();
}
if (!isset($_SESSION['csrf_token'])) {
$_SESSION['csrf_token'] = bin2hex(random_bytes(32));
}
return $_SESSION['csrf_token'];
}
function ValidateCSRFToken($token) {
if (!isset($_SESSION)) {
session_start();
}
return isset($_SESSION['csrf_token']) && hash_equals($_SESSION['csrf_token'], $token);
}
?> ?>

View file

@ -44,8 +44,8 @@ for ($i=0;$i<$Reflector->PeerCount();$i++) {
<tr class="table-center"> <tr class="table-center">
<td>'.($i+1).'</td>'; <td>'.($i+1).'</td>';
$Name = $Reflector->Peers[$i]->GetCallSign(); $Name = $Reflector->Peers[$i]->GetCallSign();
$URL = ''; $URL = '';
for ($j=1;$j<count($Reflectors);$j++) { for ($j=1;$j<count($Reflectors);$j++) {
if ($Name === $XML->GetElement($Reflectors[$j], "name")) { if ($Name === $XML->GetElement($Reflectors[$j], "name")) {
@ -53,15 +53,15 @@ for ($i=0;$i<$Reflector->PeerCount();$i++) {
} }
} }
if ($Result && (trim($URL) != "")) { if ($Result && (trim($URL) != "")) {
echo '<td><a href="'.$URL.'" target="_blank" class="listinglink" title="Visit the Dashboard of&nbsp;'.$Name.'" style="text-decoration:none;color:#000000;">'.$Name.'</a></td>'; echo '<td><a href="' . SafeOutputAttr($URL) . '" target="_blank" class="listinglink" title="Visit the Dashboard of&nbsp;' . SafeOutputAttr($Name) . '" style="text-decoration:none;color:#000000;">' . SafeOutput($Name) . '</a></td>';
} else { } else {
echo '<td>'.$Name.'</td>'; echo '<td>' . SafeOutput($Name) . '</td>';
} }
echo ' echo '
<td>'.date("d.m.Y H:i", $Reflector->Peers[$i]->GetLastHeardTime()).'</td> <td>'.date("d.m.Y H:i", $Reflector->Peers[$i]->GetLastHeardTime()).'</td>
<td>'.FormatSeconds(time()-$Reflector->Peers[$i]->GetConnectTime()).' s</td> <td>'.FormatSeconds(time()-$Reflector->Peers[$i]->GetConnectTime()).' s</td>
<td>'.$Reflector->Peers[$i]->GetProtocol().'</td> <td>'.SafeOutput($Reflector->Peers[$i]->GetProtocol()).'</td>
<td>'.$Reflector->Peers[$i]->GetLinkedModule().'</td>'; <td>'.SafeOutput($Reflector->Peers[$i]->GetLinkedModule()).'</td>';
if ($PageOptions['PeerPage']['IPModus'] != 'HideIP') { if ($PageOptions['PeerPage']['IPModus'] != 'HideIP') {
echo '<td>'; echo '<td>';
$Bytes = explode(".", $Reflector->Peers[$i]->GetIP()); $Bytes = explode(".", $Reflector->Peers[$i]->GetIP());
@ -70,7 +70,7 @@ for ($i=0;$i<$Reflector->PeerCount();$i++) {
case 'ShowLast1ByteOfIP' : echo $PageOptions['PeerPage']['MasqueradeCharacter'].'.'.$PageOptions['PeerPage']['MasqueradeCharacter'].'.'.$PageOptions['PeerPage']['MasqueradeCharacter'].'.'.$Bytes[3]; break; case 'ShowLast1ByteOfIP' : echo $PageOptions['PeerPage']['MasqueradeCharacter'].'.'.$PageOptions['PeerPage']['MasqueradeCharacter'].'.'.$PageOptions['PeerPage']['MasqueradeCharacter'].'.'.$Bytes[3]; break;
case 'ShowLast2ByteOfIP' : echo $PageOptions['PeerPage']['MasqueradeCharacter'].'.'.$PageOptions['PeerPage']['MasqueradeCharacter'].'.'.$Bytes[2].'.'.$Bytes[3]; break; case 'ShowLast2ByteOfIP' : echo $PageOptions['PeerPage']['MasqueradeCharacter'].'.'.$PageOptions['PeerPage']['MasqueradeCharacter'].'.'.$Bytes[2].'.'.$Bytes[3]; break;
case 'ShowLast3ByteOfIP' : echo $PageOptions['PeerPage']['MasqueradeCharacter'].'.'.$Bytes[1].'.'.$Bytes[2].'.'.$Bytes[3]; break; case 'ShowLast3ByteOfIP' : echo $PageOptions['PeerPage']['MasqueradeCharacter'].'.'.$Bytes[1].'.'.$Bytes[2].'.'.$Bytes[3]; break;
default : echo '<a href="http://'.$Reflector->Peers[$i]->GetIP().'" target="_blank" style="text-decoration:none;color:#000000;">'.$Reflector->Peers[$i]->GetIP().'</a>'; default : echo '<a href="http://'.SafeOutput($Reflector->Peers[$i]->GetIP()).'" target="_blank" style="text-decoration:none;color:#000000;">'.SafeOutput($Reflector->Peers[$i]->GetIP()).'</a>';
} }
} }
echo '</td>'; echo '</td>';

View file

@ -38,10 +38,10 @@ for ($i=0;$i<count($Reflectors);$i++) {
echo ' echo '
<tr class="table-center"> <tr class="table-center">
<td>'.($i+1).'</td> <td>'.($i+1).'</td>
<td><a href="'.$DASHBOARDURL.'" target="_blank" class="listinglink" title="Visit the Dashboard of&nbsp;'.$NAME.'">'.$NAME.'</a></td> <td><a href="' . SafeOutputAttr($DASHBOARDURL) . '" target="_blank" class="listinglink" title="Visit the Dashboard of&nbsp;' . SafeOutputAttr($NAME) . '">' . SafeOutput($NAME) . '</a></td>
<td>'.$COUNTRY.'</td> <td>' . SafeOutput($COUNTRY) . '</td>
<td><img src="./img/'; if ($LASTCONTACT<(time()-1800)) { echo 'down'; } ELSE { echo 'up'; } echo '.png" class="table-status" alt=""></td> <td><img src="./img/'; if ($LASTCONTACT<(time()-1800)) { echo 'down'; } ELSE { echo 'up'; } echo '.png" class="table-status" alt=""></td>
<td>'.$COMMENT.'</td> <td>' . SafeOutput($COMMENT) . '</td>
</tr>'; </tr>';
} }

View file

@ -30,10 +30,10 @@ for ($i=0;$i<$Reflector->NodeCount();$i++) {
echo '<a href="#" class="tip"><img src="./img/flags/'.$Flag.'.png" class="table-flag" alt="'.$Name.'"><span>'.$Name.'</span></a>'; echo '<a href="#" class="tip"><img src="./img/flags/'.$Flag.'.png" class="table-flag" alt="'.$Name.'"><span>'.$Name.'</span></a>';
} }
echo '</td> echo '</td>
<td><a href="http://www.aprs.fi/'.$Reflector->Nodes[$i]->GetCallSign(); <td><a href="http://www.aprs.fi/'.SafeOutput($Reflector->Nodes[$i]->GetCallSign());
if ($Reflector->Nodes[$i]->GetSuffix() != "") echo '-'.$Reflector->Nodes[$i]->GetSuffix(); if ($Reflector->Nodes[$i]->GetSuffix() != "") echo '-'.SafeOutput($Reflector->Nodes[$i]->GetSuffix());
echo '" class="pl" target="_blank">'.$Reflector->Nodes[$i]->GetCallSign(); echo '" class="pl" target="_blank">'.SafeOutput($Reflector->Nodes[$i]->GetCallSign());
if ($Reflector->Nodes[$i]->GetSuffix() != "") { echo '-'.$Reflector->Nodes[$i]->GetSuffix(); } if ($Reflector->Nodes[$i]->GetSuffix() != "") { echo '-'.SafeOutput($Reflector->Nodes[$i]->GetSuffix()); }
echo '</a></td> echo '</a></td>
<td>'; <td>';
if (($Reflector->Nodes[$i]->GetPrefix() == 'REF') || ($Reflector->Nodes[$i]->GetPrefix() == 'XRF')) { if (($Reflector->Nodes[$i]->GetPrefix() == 'REF') || ($Reflector->Nodes[$i]->GetPrefix() == 'XRF')) {
@ -55,8 +55,8 @@ for ($i=0;$i<$Reflector->NodeCount();$i++) {
echo '</td> echo '</td>
<td>'.date("d.m.Y H:i", $Reflector->Nodes[$i]->GetLastHeardTime()).'</td> <td>'.date("d.m.Y H:i", $Reflector->Nodes[$i]->GetLastHeardTime()).'</td>
<td>'.FormatSeconds(time()-$Reflector->Nodes[$i]->GetConnectTime()).' s</td> <td>'.FormatSeconds(time()-$Reflector->Nodes[$i]->GetConnectTime()).' s</td>
<td>'.$Reflector->Nodes[$i]->GetProtocol().'</td> <td>'.SafeOutput($Reflector->Nodes[$i]->GetProtocol()).'</td>
<td>'.$Reflector->Nodes[$i]->GetLinkedModule().'</td>'; <td>'.SafeOutput($Reflector->Nodes[$i]->GetLinkedModule()).'</td>';
if ($PageOptions['RepeatersPage']['IPModus'] != 'HideIP') { if ($PageOptions['RepeatersPage']['IPModus'] != 'HideIP') {
echo ' echo '
<td>'; <td>';

View file

@ -9,6 +9,11 @@ if (!isset($_SESSION['FilterModule'])) {
} }
if (isset($_POST['do'])) { if (isset($_POST['do'])) {
// Validate CSRF token
if (!isset($_POST['csrf_token']) || !ValidateCSRFToken($_POST['csrf_token'])) {
die('CSRF token validation failed');
}
if ($_POST['do'] == 'SetFilter') { if ($_POST['do'] == 'SetFilter') {
if (isset($_POST['txtSetCallsignFilter'])) { if (isset($_POST['txtSetCallsignFilter'])) {
@ -17,12 +22,17 @@ if (isset($_POST['do'])) {
$_SESSION['FilterCallSign'] = null; $_SESSION['FilterCallSign'] = null;
} }
else { else {
$_SESSION['FilterCallSign'] = $_POST['txtSetCallsignFilter']; // Validate callsign format (alphanumeric, dash, asterisk only)
if (strpos($_SESSION['FilterCallSign'], "*") === false) { if (preg_match('/^[A-Z0-9\-\*]+$/i', $_POST['txtSetCallsignFilter'])) {
$_SESSION['FilterCallSign'] = "*".$_SESSION['FilterCallSign']."*"; $_SESSION['FilterCallSign'] = $_POST['txtSetCallsignFilter'];
if (strpos($_SESSION['FilterCallSign'], "*") === false) {
$_SESSION['FilterCallSign'] = "*".$_SESSION['FilterCallSign']."*";
}
} else {
// Invalid format, reject it
$_SESSION['FilterCallSign'] = null;
} }
} }
} }
if (isset($_POST['txtSetModuleFilter'])) { if (isset($_POST['txtSetModuleFilter'])) {
@ -31,9 +41,14 @@ if (isset($_POST['do'])) {
$_SESSION['FilterModule'] = null; $_SESSION['FilterModule'] = null;
} }
else { else {
$_SESSION['FilterModule'] = $_POST['txtSetModuleFilter']; // Validate module is single letter A-Z
if (preg_match('/^[A-Z]$/i', $_POST['txtSetModuleFilter'])) {
$_SESSION['FilterModule'] = strtoupper($_POST['txtSetModuleFilter']);
} else {
// Invalid format, reject it
$_SESSION['FilterModule'] = null;
}
} }
} }
} }
} }
@ -60,7 +75,8 @@ if ($PageOptions['UserPage']['ShowFilter']) {
<td align="left"> <td align="left">
<form name="frmFilterCallSign" method="post" action="./index.php"> <form name="frmFilterCallSign" method="post" action="./index.php">
<input type="hidden" name="do" value="SetFilter" /> <input type="hidden" name="do" value="SetFilter" />
<input type="text" class="FilterField" value="'.$_SESSION['FilterCallSign'].'" name="txtSetCallsignFilter" placeholder="Callsign" onfocus="SuspendPageRefresh();" onblur="setTimeout(ReloadPage, '.$PageOptions['PageRefreshDelay'].');" /> <input type="hidden" name="csrf_token" value="' . GenerateCSRFToken() . '" />
<input type="text" class="FilterField" value="'.SafeOutputAttr($_SESSION['FilterCallSign']).'" name="txtSetCallsignFilter" placeholder="Callsign" onfocus="SuspendPageRefresh();" onblur="setTimeout(ReloadPage, '.$PageOptions['PageRefreshDelay'].');" />
<input type="submit" value="Apply" class="FilterSubmit" /> <input type="submit" value="Apply" class="FilterSubmit" />
</form> </form>
</td>'; </td>';
@ -72,7 +88,8 @@ if ($PageOptions['UserPage']['ShowFilter']) {
<td align="right" style="padding-right:3px;"> <td align="right" style="padding-right:3px;">
<form name="frmFilterModule" method="post" action="./index.php"> <form name="frmFilterModule" method="post" action="./index.php">
<input type="hidden" name="do" value="SetFilter" /> <input type="hidden" name="do" value="SetFilter" />
<input type="text" class="FilterField" value="'.$_SESSION['FilterModule'].'" name="txtSetModuleFilter" placeholder="Module" onfocus="SuspendPageRefresh();" onblur="setTimeout(ReloadPage, '.$PageOptions['PageRefreshDelay'].');" /> <input type="hidden" name="csrf_token" value="' . GenerateCSRFToken() . '" />
<input type="text" class="FilterField" value="'.SafeOutputAttr($_SESSION['FilterModule']).'" name="txtSetModuleFilter" placeholder="Module" onfocus="SuspendPageRefresh();" onblur="setTimeout(ReloadPage, '.$PageOptions['PageRefreshDelay'].');" />
<input type="submit" value="Apply" class="FilterSubmit" /> <input type="submit" value="Apply" class="FilterSubmit" />
</form> </form>
</td> </td>
@ -133,16 +150,16 @@ for ($i=0;$i<$Reflector->StationCount();$i++) {
echo '<a href="#" class="tip"><img src="./img/flags/' . $Flag . '.png" class="table-flag" alt="' . $Name . '"><span>' . $Name . '</span></a>'; echo '<a href="#" class="tip"><img src="./img/flags/' . $Flag . '.png" class="table-flag" alt="' . $Name . '"><span>' . $Name . '</span></a>';
} }
echo '</td> echo '</td>
<td><a href="https://www.qrz.com/db/' . $Reflector->Stations[$i]->GetCallsignOnly() . '" class="pl" target="_blank">' . $Reflector->Stations[$i]->GetCallsignOnly() . '</a></td> <td><a href="https://www.qrz.com/db/' . SafeOutput($Reflector->Stations[$i]->GetCallsignOnly()) . '" class="pl" target="_blank">' . SafeOutput($Reflector->Stations[$i]->GetCallsignOnly()) . '</a></td>
<td>' . $Reflector->Stations[$i]->GetSuffix() . '</td> <td>' . SafeOutput($Reflector->Stations[$i]->GetSuffix()) . '</td>
<td><a href="http://www.aprs.fi/' . $Reflector->Stations[$i]->GetCallsignOnly() . '" class="pl" target="_blank"><img src="./img/sat.png" alt=""></a></td> <td><a href="http://www.aprs.fi/' . SafeOutput($Reflector->Stations[$i]->GetCallsignOnly()) . '" class="pl" target="_blank"><img src="./img/sat.png" alt=""></a></td>
<td>' . $Reflector->Stations[$i]->GetVia(); <td>' . SafeOutput($Reflector->Stations[$i]->GetVia());
if ($Reflector->Stations[$i]->GetPeer() != $Reflector->GetReflectorName()) { if ($Reflector->Stations[$i]->GetPeer() != $Reflector->GetReflectorName()) {
echo ' / ' . $Reflector->Stations[$i]->GetPeer(); echo ' / ' . SafeOutput($Reflector->Stations[$i]->GetPeer());
} }
echo '</td> echo '</td>
<td>' . @date("d.m.Y H:i", $Reflector->Stations[$i]->GetLastHeardTime()) . '</td> <td>' . @date("d.m.Y H:i", $Reflector->Stations[$i]->GetLastHeardTime()) . '</td>
<td>' . $Reflector->Stations[$i]->GetModule() . '</td> <td>' . SafeOutput($Reflector->Stations[$i]->GetModule()) . '</td>
</tr>'; </tr>';
} }
if ($i == $PageOptions['LastHeardPage']['LimitTo']) { if ($i == $PageOptions['LastHeardPage']['LimitTo']) {
@ -192,7 +209,7 @@ for ($i=0;$i<count($Modules);$i++) {
$Displayname = $Reflector->GetCallsignAndSuffixByID($Users[$j]); $Displayname = $Reflector->GetCallsignAndSuffixByID($Users[$j]);
echo ' echo '
<tr> <tr>
<td><a href="http://www.aprs.fi/'.$Displayname.'" class="pl" target="_blank">'.$Displayname.'</a> </td> <td><a href="http://www.aprs.fi/' . SafeOutput($Displayname) . '" class="pl" target="_blank">' . SafeOutput($Displayname) . '</a> </td>
</tr>'; </tr>';
$UserCheckedArray[] = $Users[$j]; $UserCheckedArray[] = $Users[$j];
} }

View file

@ -526,10 +526,10 @@ void CDcsProtocol::EncodeDisconnectPacket(CBuffer *Buffer, CClient *Client)
Buffer->Set((uint8 *)(const char *)Client->GetCallsign(), CALLSIGN_LEN-1); Buffer->Set((uint8 *)(const char *)Client->GetCallsign(), CALLSIGN_LEN-1);
Buffer->Append((uint8)' '); Buffer->Append((uint8)' ');
Buffer->Append((uint8)Client->GetModule()); Buffer->Append((uint8)Client->GetModule());
Buffer->Append((uint8)' ');
Buffer->Append((uint8)0x00); Buffer->Append((uint8)0x00);
Buffer->Append((uint8 *)(const char *)GetReflectorCallsign(), CALLSIGN_LEN-1); Buffer->Append((uint8 *)(const char *)GetReflectorCallsign(), CALLSIGN_LEN-1);
Buffer->Append((uint8)' '); Buffer->Append((uint8)' ');
Buffer->Append((uint8)0x00);
} }
void CDcsProtocol::EncodeDvPacket(const CDvHeaderPacket &Header, const CDvFramePacket &DvFrame, uint32 iSeq, CBuffer *Buffer) const void CDcsProtocol::EncodeDvPacket(const CDvHeaderPacket &Header, const CDvFramePacket &DvFrame, uint32 iSeq, CBuffer *Buffer) const