<?php
	// Last-Updated: 2026-08-03 19:12 EDT
	// Created: 2026-06-02 (Paul KN2R new exp.php public monitor); packaged 2026-07
	// Authors: Paul Aidukas KN2R, Logan Crook K8LRC
	// ============================================================================
	// PACKAGE TEMPLATE — DO NOT EDIT for normal installs.
	// install-tlbweb.sh / update-tlbweb.sh copy this file to /var/www/html/exp.php
	// and fill YOUR_* placeholders from tlb.ini and/or installer prompts.
	//
	// Operators: edit tlb.ini (copy from tlb.ini.sample) or answer the installer.
	// Do not hand-edit this .template file.
	//
	// Placeholders filled by installer:
	//   YOUR_SERVER_IP, YOUR_LINK_TYPE, YOUR_REFLECTOR_NAME, YOUR_SITE_KIND,
	//   YOUR_SUPERMON_URL, YOUR_PUBLIC_MONITOR_SCRIPT
	//
	// Public read-only monitor. Admin controls live in tlb-admin/ (Apache auth).
	// ============================================================================

	$tlbcmdport = "";  // If the tlbcmd port is different from the default, set this to your port. e.g. "-p6198"
	$tlblogpath = "";  // Optional full path to tlb.log (default: /home/tlb.log)
	$tlbmessagespath = "";  // Optional full path to messages log (default: /home/tlb/log/messages)

	require __DIR__ . '/tlb-common.inc';

	session_start(array('name' => 'explbmon'));

	if (!empty($_GET['partial'])) {
		header('Content-Type: text/html; charset=UTF-8');
		header('Cache-Control: no-store, no-cache, must-revalidate');
		echo exp_render_live_panel($tlbcmdport, false);
		exit;
	}

	if (empty($_SESSION['exp_conference_id'])) {
		$output = tlb_exec_piped($tlbcmdport, 'set ConferenceID', 'tail -1');
		$output = str_replace('"', '', $output);
		$f = preg_split("/[=]+/", $output);
		$_SESSION['exp_conference_id'] = $f[1] ?? '';
	}
	$ConferenceID = $_SESSION['exp_conference_id'];
	$livePanelHtml = exp_render_live_panel($tlbcmdport, false);
	$connCountDisplay = 0;
	if (preg_match('/\bdata-conns="(\d+)"/', $livePanelHtml, $mConnBar)) {
		$connCountDisplay = (int) $mConnBar[1];
	}
?>
<html>
<head>
   <meta name="author" content="Paul Aidukas KN2R">
   <meta name="co-author" content="Logan Crook K8LRC">
   <meta name="generator" content="Paul Aidukas KN2R, Logan Crook K8LRC, and AI co-generator">
   <meta name="description" content="The LinkBox Reflector Status">
   <meta name="keywords" content="TLB, LinkBox, IRLP, Reflector, Asterisk, AllStar">
   <meta name="version" content="2+">
	<meta name="robots" content="noindex, nofollow">
	<!-- Short tab title (do not dump ConferenceID — it can be a long sentence) -->
	<title>YOUR_LINK_TYPE YOUR_REFLECTOR_NAME YOUR_SITE_KIND Monitor</title>
	<style type="text/css">
		table.status { width: 99%; border-collapse: collapse; border: 1px solid #666; }
		table.status th {
			padding: 0 1.0em;
			text-align: left;
         font-size: 15.6px;
         font-family: New Courier;
         background-color: lightgray;
			border: 1px solid #666;
      }
		table.status td {
			padding: 0 0.5em;
			text-align: left;
         font-size: 15.4px;
         font-family: New Courier;
         background-color: white;
			border: 1px solid #666;
     }
		table.status th.col-node,
		table.status td.col-node,
		table.status th.col-ip,
		table.status td.col-ip,
		table.status th.col-proto,
		table.status td.col-proto,
		table.status th.col-rx,
		table.status td.col-rx {
			text-align: center;
			white-space: nowrap;
			width: 1%;
		}
		table.status th.col-attr,
		table.status td.col-attr {
			text-align: left;
			white-space: nowrap;
		}
		table.status th.col-conn,
		table.status td.col-conn {
			text-align: right;
			white-space: nowrap;
			width: 1%;
		}
		table.status tr.rColor td, table.status tr.rColor a {
         background-color: black;
			color: lemonchiffon;
      }
		.refresh-hint {
			font-family: New Courier;
			font-size: 13px;
			margin: 0 0 0.5em;
			color: darkgreen;
			display: flex;
			justify-content: center;
			align-items: center;
			position: relative;
		}
		.refresh-hint .conn-count {
			position: absolute;
			left: 0;
			font-size: 15px;
			font-weight: bold;
			color: #000;
			white-space: nowrap;
		}
		.nav-links {
			font-family: New Courier;
			font-size: 14px;
			line-height: 1.6;
		}
		table.attributes th {
			padding: 0 0.5em;
			text-align: center;
		}
		table.attributes td {
			padding: 0 0.8em;
         background-color: #b5a896;
		}
      a:link { text-decoration: none; color: blue; }
      a:visited { text-decoration: none; color: black; }
      a:active { text-decoration: none; background-color: black; color: lemonchiffon; }
      a:hover { text-decoration: none; background-color: black; color: lightcyan; }
	</style>
</head>

<body style="background-color: #b5a896;">
   <center>
       <h2><i>
       The LinkBox Monitor 2+ YOUR_LINK_TYPE YOUR_REFLECTOR_NAME YOUR_SITE_KIND
       </i><br>
       IP Address:&nbsp; YOUR_SERVER_IP
       </h2>
       <h2><?php echo htmlspecialchars($ConferenceID, ENT_QUOTES, 'UTF-8'); ?></h2>
       <div class="nav-links">
       <a href="YOUR_SUPERMON_URL"><b>&nbsp; Show AllStar HUB activity linked to this YOUR_SITE_KIND &nbsp;</b></a>
       <br>
       <a href="tlb-admin/"><b>&nbsp; TLB Administration Tools &nbsp;</b></a>
       </div>
       <br>
   </center>

	<div style="width:88%; font-family: New Courier; margin: auto; border: 1px solid white; padding:.25em;">
	<div id="refresh-hint" class="refresh-hint">
		<span id="conn-count" class="conn-count">Conns: <?php echo (int) $connCountDisplay; ?></span>
		<span>Live status updates every 2 seconds</span>
	</div>
	<div id="exp-live-panel">
	<?php echo $livePanelHtml; ?>
	</div>
	</div>

	<center>
	<!--IRLP_HINT_START-->
   <table><tr><th style="text-align:left; font-size: 16px;">Make sure you have the following line in your IRLP  'environment'  file:<br>export  ALLOW_EXPERIMENTAL_NODES=YES</th></tr></table>
	<hr style="width:72%;">
	<!--IRLP_HINT_END-->

	<h4><p>Connected node's Attribute characters are as follows:</p></h4>
	<table class="attributes" style="font-size: 15px; border-collapse: collapse; ">
		<tr><th>A</th><td>logged in as an Administrator</td></tr>
		<tr><th>a</th><td>ADPCM CODEC</td></tr>
		<tr><th>B</th><td>a linked theBridge conference</td></tr>
		<tr><th>C</th><td>a linked Conference other than theBridge</td></tr>
		<tr><th>c</th><td>chat text suppressed</td></tr>
		<tr><th>F</th><td>playing a File (using the .play or .test commands)</td></tr>
		<tr><th>f</th><td>full duplex connection</td></tr>
		<tr><th>I</th><td>Inactive connection</td></tr>
		<tr><th>K</th><td>Kicked</td></tr>
		<tr><th>L</th><td>Lurker</td></tr>
		<tr><th>M</th><td>audio and text are Muted</td></tr>
		<tr><th>m</th><td>audio is muted</td></tr>
		<tr><th>n</th><td>Nailed up GSM connection</td></tr>
		<tr><th>P</th><td>a Permanent connection (connected by a .connect command)</td></tr>
		<tr><th>R</th><td>Receive only (monitored)</td></tr>
		<tr><th>S</th><td>logged in as a Sysop</td></tr>
		<tr><th>T</th><td>currently Talking</td></tr>
		<tr><th>t</th><td>text muted</td></tr>
		<tr><th>u</th><td>uLaw CODEC</td></tr>
		<tr><th>x</th><td>not currently active in the conference</td></tr>
		<tr><th>*</th><td>using Asterisk protocol</td></tr>
		<tr><th>0</th><td>using Speak Freely protocol</td></tr>
		<tr><th>1</th><td>using RTP protocol</td></tr>
		<tr><th>7</th><td>G.726 CODEC</td></tr>
		<tr><th>!</th><td>an old version of theBridge which sent SDES packets containing a private "txt" extension field</td></tr>
	</table>
   <br>
	<hr style="width:72%;"><br><b>LinkBox Admins:</b><br>
       <table style="font-size: 14px;"><tr><th>LinkBox Connect command line:&nbsp; .connect -p 2074 -s ipaddress </th></tr></table>
       <table style="font-size: 14px;"><tr><th>LinkBox Disconnect command line:&nbsp; .bump stn####, or callsign, or ipaddress </th></tr></table>
       <table style="font-size: 14px;"><tr><th>Web controls (Connect, Mute, Bump, Disconnect, Ban, Unban):&nbsp; use the <a href="tlb-admin/">Administration Tool</a>.</th></tr></table>
	<p style="font-family: New Courier; font-size: 12px; margin: 0.75em 0 1em;">
	<i>Author: Paul Aidukas KN2R &nbsp;&bull;&nbsp; Co-author: Logan Crook K8LRC &nbsp;&bull;&nbsp; Co-generator: AI.</i>
	</p>
	<br><br>
   </center>

<script>
(function() {
	var REFRESH_MS = 2000;
	var MONITOR_SCRIPT = 'YOUR_PUBLIC_MONITOR_SCRIPT';

	function syncConnCount(root) {
		var data = root ? root.querySelector('#conn-count-data') : null;
		var bar = document.getElementById('conn-count');
		if (data && bar) {
			bar.textContent = 'Conns: ' + (data.getAttribute('data-conns') || '0');
		}
	}

	function refreshLivePanel() {
		return fetch(MONITOR_SCRIPT + '?partial=1', { credentials: 'same-origin', cache: 'no-store' })
			.then(function(response) {
				if (!response.ok) {
					throw new Error('refresh failed');
				}
				return response.text();
			})
			.then(function(html) {
				var panel = document.getElementById('exp-live-panel');
				if (panel) {
					panel.innerHTML = html;
					syncConnCount(panel);
				}
			});
	}

	function scheduleRefresh() {
		setTimeout(function() {
			refreshLivePanel()
				.catch(function() {})
				.then(scheduleRefresh);
		}, REFRESH_MS);
	}

	document.addEventListener('DOMContentLoaded', function() {
		scheduleRefresh();
	});
})();
</script>
</body>
</html>
