setTimeZone($local_tz); $local_time = $dt->format('H:i:s M jS'); // Every value below comes from log-line parsing in // mmdvmhost/functions.php, which in turn parses log lines // produced by RF traffic. A station transmitting on RF // can put almost any byte sequence into the callsign or // target field; without escaping it lands in the // dashboard's HTML refresh every 1.5s. Normalise once // here so every echo below works on safe values. // // $modeHtml — "Slot 1" -> "TS1" cosmetic + escape // $cs — callsign (HTML-safe text) // $csUrl — callsign URL-encoded for href= path // $csSuffix — D-Star station ID after `/` (HTML-safe) // $tgt — target callsign / talkgroup (HTML-safe) // $src — source ("RF"/"Net"/etc.; HTML-safe) // $dur, $loss, $ber — numeric; HTML-safe defensively. // // The downstream str_replace ' '->' ' has to run // AFTER htmlspecialchars; the entity reference ` ` // is intentional raw HTML output, not data. $modeHtml = htmlspecialchars(str_replace('Slot ', 'TS', $listElem[1]), ENT_QUOTES, 'UTF-8'); $cs = htmlspecialchars((string)$listElem[2], ENT_QUOTES, 'UTF-8'); $csUrl = rawurlencode((string)$listElem[2]); $csSuffix = htmlspecialchars((string)$listElem[3], ENT_QUOTES, 'UTF-8'); // Target normalisation: if it's a single character left-pad // it to 8 spaces (cosmetic, matches legacy layout). The // visible value is HTML-escaped, then spaces become // non-breaking-space entities AFTER the escape so the // entity isn't double-encoded. $tgtRaw = (string)$listElem[4]; // Append this operator's own alias in parentheses when the // target is a plain "TG " and TGList_CN.json has a name for // it — MMDVMHost's log never carries a name, only the numeric // ID, so without this lookup the column can only ever show // digits (see getTGNameMap() in functions.php). if (preg_match('/^TG\s+(\d+)$/', trim($tgtRaw), $tgMatch)) { $tgName = getTGNameMap()[(int)$tgMatch[1]] ?? null; if ($tgName !== null) { $tgtRaw .= " ($tgName)"; } } if (strlen($tgtRaw) === 1) { $tgtRaw = str_pad($tgtRaw, 8, ' ', STR_PAD_LEFT); } $tgtHtml = htmlspecialchars($tgtRaw, ENT_QUOTES, 'UTF-8'); $src = htmlspecialchars((string)$listElem[5], ENT_QUOTES, 'UTF-8'); $dur = htmlspecialchars((string)$listElem[6], ENT_QUOTES, 'UTF-8'); $loss = htmlspecialchars((string)(isset($listElem[7]) ? $listElem[7] : ''), ENT_QUOTES, 'UTF-8'); $ber = htmlspecialchars((string)(isset($listElem[8]) ? $listElem[8] : ''), ENT_QUOTES, 'UTF-8'); echo ""; echo ""; echo ""; if (is_numeric($listElem[2])) { if ($listElem[2] > 9999) { echo ""; } else { echo ""; } } elseif (!preg_match('/[A-Za-z].*[0-9]|[0-9].*[A-Za-z]/', $listElem[2])) { echo ""; } else { // Strip any "-suffix" before linking — re-derive the // url-encoded form from the trimmed value. $csTrim = (strpos($listElem[2], "-") > 0) ? substr($listElem[2], 0, strpos($listElem[2], "-")) : (string)$listElem[2]; $csTrimHtml = htmlspecialchars($csTrim, ENT_QUOTES, 'UTF-8'); $csTrimUrl = rawurlencode($csTrim); if ( $listElem[3] && $listElem[3] != ' ' ) { echo ""; } else { echo ""; } } if ( substr($tgtRaw, 0, 6) === 'CQCQCQ' ) { echo ""; } else { echo ""; } if ($listElem[5] == "RF"){ echo ""; }else{ echo ""; } if ($listElem[6] == null) { // Live duration $utc_time = $listElem[0]; $utc_tz = new DateTimeZone('UTC'); $now = new DateTime("now", $utc_tz); $dt = new DateTime($utc_time, $utc_tz); $duration = $now->getTimestamp() - $dt->getTimestamp(); $duration_string = $duration<999 ? round($duration) . "+" : "∞"; echo ""; } else if ($listElem[6] == "DMR Data") { echo ""; } else if ($listElem[6] == "POCSAG Data") { echo ""; } else { echo ""; // Colour the Loss Field if (floatval($listElem[7]) < 1) { echo ""; } elseif (floatval($listElem[7]) == 1) { echo ""; } elseif (floatval($listElem[7]) > 1 && floatval($listElem[7]) <= 3) { echo ""; } else { echo ""; } // Colour the BER Field if (floatval($listElem[8]) == 0) { echo ""; } elseif (floatval($listElem[8]) >= 0.0 && floatval($listElem[8]) <= 1.9) { echo ""; } elseif (floatval($listElem[8]) >= 2.0 && floatval($listElem[8]) <= 4.9) { echo ""; } else { echo ""; } } echo "\n"; } } } ?>
()Time in time zone Transmitted Mode Callsign Target, D-Star Reflector, DMR Talk Group etc Received from source (s)Duration in Seconds Packet Loss Bit Error Rate
$local_time$modeHtml$cs$cs$cs
$csTrimHtml/$csSuffix
(GPS)
$csTrimHtml
(GPS)
$tgtHtml".str_replace(' ', ' ', $tgtHtml)."RF$srcTX " . $duration_string . " secDMR DataPOCSAG Data$dur$loss$loss$loss$loss$ber$ber$ber$ber