. */ //Get root directory of the application $programPath = dirname(__FILE__); //Load External Functions require_once("$programPath/functions.php"); $config = loadConfig(); //Only display errors if set to in the config if($config['general']['debug']) { ini_set("display_errors", "On"); error_reporting(E_ALL); } else ini_set("display_errors", "Off"); //Delete old style cookie if(array_key_exists('currentSettings', $_COOKIE)) setcookie("currentSettings", "", time() - 3600, "/", ".".$_SERVER['SERVER_NAME']); //Load location settings from cookie $sendCookie = false; $currentSettings = []; if(!array_key_exists('localSettings', $_COOKIE)) $sendCookie = true; else { $allLocations = explode("~", $_COOKIE['localSettings']); foreach($allLocations as $thisLocation) { $profileParts = explode("!", $thisLocation); if(count($profileParts) != 9) continue; $currentSettings[] = [ 'city' => $profileParts[0], 'lat' => $profileParts[1], 'lon' => $profileParts[2], 'orig' => $profileParts[3], 'radarCode' => $profileParts[4], 'rwrOrig' => $profileParts[5], 'stateAbbr' => $profileParts[6], 'timezone' => $profileParts[7], 'wxZone' => $profileParts[8] ]; } } //Overwrite first setting profile in array with all other settings on server if(count($currentSettings) == 0 || count(array_diff($config['location'], $currentSettings[0])) != 0) $sendCookie = true; $currentSettings[0] = $config['location']; //Load selected profile; make sure cookie is set and not malformed if(array_key_exists('selectedProfile', $_COOKIE) && is_numeric($_COOKIE['selectedProfile']) && intval($_COOKIE['selectedProfile']) < count($currentSettings)) $selectedProfile = intval($_COOKIE['selectedProfile']); else { $selectedProfile = 0; $sendCookie = true; } //Parse settings loaded from cookie for safety reasons //Implicitly trust server config, for better or worse if($selectedProfile > 0) { foreach($currentSettings[$selectedProfile] as $key => $value) { switch($key) { case "radarCode": case "orig": case "rwrOrig": if(!preg_match("/^[A-Z0-9]{5}$/", $value)) { unset($currentSettings[$selectedProfile]); $selectedProfile = 0; $sendCookie = true; break 2; } break; case "stateAbbr": if(!preg_match("/^[A-Z]{2}$/", $value)) { unset($currentSettings[$selectedProfile]); $selectedProfile = 0; $sendCookie = true; break 2; } break; case "wxZone": if(!preg_match("/^[A-Z]{3}[0-9]{3}$/", $value)) { unset($currentSettings[$selectedProfile]); $selectedProfile = 0; $sendCookie = true; break 2; } break; case "city": if(strip_tags($value) != $value) { unset($currentSettings[$selectedProfile]); $selectedProfile = 0; $sendCookie = true; break 2; } break; case "lat": case "lon": if(!is_numeric($value)) { unset($currentSettings[$selectedProfile]); $selectedProfile = 0; $sendCookie = true; break 2; } break; case "timezone": if(!in_array($value, timezone_identifiers_list())) { unset($currentSettings[$selectedProfile]); $selectedProfile = 0; $sendCookie = true; break 2; } break; } } } //Save settings in case something changed if($sendCookie) { $profileParts = []; foreach($currentSettings as $thisLocation) { $profileParts[] = join("!", [ (array_key_exists('city', $thisLocation) ? rawurlencode($thisLocation['city']) : ""), (array_key_exists('lat', $thisLocation) ? $thisLocation['lat'] : ""), (array_key_exists('lon', $thisLocation) ? $thisLocation['lon'] : ""), (array_key_exists('orig', $thisLocation) ? $thisLocation['orig'] : ""), (array_key_exists('radarCode', $thisLocation) ? $thisLocation['radarCode'] : ""), (array_key_exists('rwrOrig', $thisLocation) ? $thisLocation['rwrOrig'] : ""), (array_key_exists('stateAbbr', $thisLocation) ? $thisLocation['stateAbbr'] : ""), (array_key_exists('timezone', $thisLocation) ? rawurlencode($thisLocation['timezone']) : ""), (array_key_exists('wxZone', $thisLocation) ? $thisLocation['wxZone'] : "") ]); } $cookiePrefix = (ip2long($_SERVER['SERVER_NAME']) === false ? "." : ""); setcookie("selectedProfile", "$selectedProfile", time() + 31536000, "/", $cookiePrefix.$_SERVER['SERVER_NAME']); setrawcookie("localSettings", join("~", $profileParts), time() + 31536000, "/", $cookiePrefix.$_SERVER['SERVER_NAME']); } //Set the specified timezone date_default_timezone_set($currentSettings[$selectedProfile]['timezone']); //Let the fun begin! if(!array_key_exists('type', $_GET)) die(); if($_GET['type'] == "preload") { $preloadData = []; $preloadData['localRadarVideo'] = ""; if(array_key_exists('emwin', $config['categories']) && array_key_exists('radarCode', $currentSettings[$selectedProfile])) { foreach($config['categories']['emwin']['data'] as $value) { if($value['filter'] == "RAD" . $currentSettings[$selectedProfile]['radarCode'] && isset($value["videoPath"])) { $preloadData['localRadarVideo'] = $value["videoPath"]; break; } } } $preloadData['categories'] = []; foreach($config['categories'] as $type => $typeProps) { foreach($config['categories'][$type]['data'] as $thisSlug => $thisValue) { unset($config['categories'][$type]['data'][$thisSlug]['path']); unset($config['categories'][$type]['data'][$thisSlug]['filter']); unset($config['categories'][$type]['data'][$thisSlug]['mode']); unset($config['categories'][$type]['data'][$thisSlug]['fast']); } $preloadData['categories'][$type] = $config['categories'][$type]; } $preloadData['showSysInfo'] = $config['general']['showSysInfo']; $preloadData['showSatdumpInfo'] = array_key_exists('satdumpAPI', $config['general']); $preloadData['showGraphs'] = array_key_exists('graphiteAPI', $config['general']); $preloadData['showEmwinInfo'] = array_key_exists('emwinPath', $config['general']) && is_dir($config['general']['emwinPath']); $preloadData['allowUserLoader'] = array_key_exists('emwinPath', $config['general']) && is_dir($config['general']['emwinPath']) && $config['otheremwin']['allowUserLoader']; $preloadData['showAdminInfo'] = array_key_exists('adminPath', $config['general']) && is_dir($config['general']['adminPath']); if($preloadData['showEmwinInfo']) { $preloadData['otherEmwin'] = loadOtherEmwin($config); foreach($preloadData['otherEmwin']['system'] as $key => $value) { unset($preloadData['otherEmwin']['system'][$key]['truncate']); unset($preloadData['otherEmwin']['system'][$key]['identifier']); } } $preloadData['showCurrentWeather'] = $preloadData['showEmwinInfo'] && array_key_exists('stateAbbr', $currentSettings[$selectedProfile]) && array_key_exists('wxZone', $currentSettings[$selectedProfile]) && array_key_exists('orig', $currentSettings[$selectedProfile]); $currentTheme = loadTheme($config); if($currentTheme === false) $preloadData['theme'] = "default"; else $preloadData['theme'] = $currentTheme['slug']; header('Content-Type: application/json; charset=utf-8'); echo json_encode($preloadData); } elseif($_GET['type'] == "metadata") { //Prepare Metadata Return Value $metadata = []; if(!array_key_exists('id', $_GET)) die(); //Various stats from goestools if($_GET['id'] == 'packetsContent') { set_error_handler("convertToException"); try { $tzUrl = urlencode($currentSettings[$selectedProfile]['timezone']); $packetOK1hrArray = json_decode(file_get_contents($config['general']['graphiteAPI']."?format=json&from=-1hours&tz=$tzUrl&target=stats.packets_ok"))[0]->datapoints; $packetOK1dayArray = json_decode(file_get_contents($config['general']['graphiteAPI']."?format=json&from=-24hours&tz=$tzUrl&target=stats.packets_ok"))[0]->datapoints; $packetDrop1hrArray = json_decode(file_get_contents($config['general']['graphiteAPI']."?format=json&from=-1hours&tz=$tzUrl&target=stats.packets_dropped"))[0]->datapoints; $packetDrop1dayArray = json_decode(file_get_contents($config['general']['graphiteAPI']."?format=json&from=-24hours&tz=$tzUrl&target=stats.packets_dropped"))[0]->datapoints; $packetOK1hr = $packetOK1day = $packetDrop1hr = $packetDrop1day = 0; foreach($packetOK1hrArray as $thisPacket) {$packetOK1hr += $thisPacket[0];} foreach($packetOK1dayArray as $thisPacket) {$packetOK1day += $thisPacket[0];} foreach($packetDrop1hrArray as $thisPacket) {$packetDrop1hr += $thisPacket[0];} foreach($packetDrop1dayArray as $thisPacket) {$packetDrop1day += $thisPacket[0];} $metadata['description'] = "1 Hour Average: " . round(($packetOK1hr / ($packetOK1hr + $packetDrop1hr)) * 100, 4) . "% OK | 1 Day Average: " . round(($packetOK1day / ($packetOK1day + $packetDrop1day)) * 100, 4) . "% OK"; $metadata['svg1hr'] = preg_replace("(clip-path.*clip-rule.*\")", "", file_get_contents($config['general']['graphiteAPI']."?width=600&height=350&format=svg&colorList=green%2Cred&fontSize=14&title=HRIT%20Packets%20%2F%20Second%20(1%20Hour)&fgcolor=FFFFFF&lineWidth=2&from=-1hours&tz=$tzUrl&target=alias(stats.packets_ok%2C%22Packets%20OK%22)&target=alias(stats.packets_dropped%2C%22Packets%20Dropped%22)")); $metadata['svg1day'] = preg_replace("(clip-path.*clip-rule.*\")", "", file_get_contents($config['general']['graphiteAPI']."?width=600&height=350&format=svg&colorList=green%2Cred&fontSize=14&title=HRIT%20Packets%20%2F%20Second%20(1%20Day)&fgcolor=FFFFFF&lineWidth=2&from=-1days&tz=$tzUrl&target=alias(stats.packets_ok%2C%22Packets%20OK%22)&target=alias(stats.packets_dropped%2C%22Packets%20Dropped%22)")); } catch(exception $e) { $metadata = []; } restore_error_handler(); } elseif($_GET['id'] == 'viterbiContent') parseGraphiteData($metadata, $currentSettings[$selectedProfile]['timezone'], $config['general']['graphiteAPI'], "divideSeries(stats_counts.viterbi_errors,sumSeries(stats_counts.packets_dropped,stats_counts.packets_ok))", "Avg Viterbi Error Corrections / Packet", "red"); elseif($_GET['id'] == 'rsContent') parseGraphiteData($metadata, $currentSettings[$selectedProfile]['timezone'], $config['general']['graphiteAPI'], "stats.reed_solomon_errors", "Reed-Solomon Errors / Second", "6464FF"); elseif($_GET['id'] == 'gainContent') parseGraphiteData($metadata, $currentSettings[$selectedProfile]['timezone'], $config['general']['graphiteAPI'], "stats.gauges.gain", "Gain Multiplier", "orange"); elseif($_GET['id'] == 'freqContent') parseGraphiteData($metadata, $currentSettings[$selectedProfile]['timezone'], $config['general']['graphiteAPI'], "stats.gauges.frequency", "Frequency Offset", "brown"); elseif($_GET['id'] == 'omegaContent') parseGraphiteData($metadata, $currentSettings[$selectedProfile]['timezone'], $config['general']['graphiteAPI'], "stats.gauges.omega", "Samples/Symbol in Clock Recovery", "008080"); //Other EMWIN metadata elseif($_GET['id'] == 'otherEmwin') { if(array_key_exists('emwinPath', $config['general']) && is_dir($config['general']['emwinPath'])) { //Get all emwin files and config $allEmwinFiles = scandir_recursive($config['general']['emwinPath'], $config['general']['fastEmwin']); $otherEmwinConfig = loadOtherEmwin($config); //Load pertinent pieces of information where for cards with all available information $allUnique = $otherEmwinFiles = []; $otherEmwinFiles['system'] = $otherEmwinFiles['user'] = $metadata['system'] = $metadata['user'] = []; for($i = 0; $i < count($otherEmwinConfig['system']); $i++) $otherEmwinFiles['system'][$i] = $metadata['system'][$i] = []; for($i = 0; $i < count($otherEmwinConfig['user']); $i++) $otherEmwinFiles['user'][$i] = $metadata['user'][$i] = []; foreach($allEmwinFiles as $thisFile) { if(preg_match("/-([A-Z0-9]{8})\.TXT$/i", $thisFile, $matches)) { $allUnique[] = $matches[1]; foreach(array('system', 'user') as $thisType) for($i = 0; $i < count($otherEmwinConfig[$thisType]); $i++) if(preg_match("/-{$otherEmwinConfig[$thisType][$i]['identifier']}\.TXT$/i", $thisFile)) $otherEmwinFiles[$thisType][$i][] = $thisFile; } } //Supress if additional data loader is disabled if($config['otheremwin']['allowUserLoader']) { $metadata['allUnique'] = array_unique($allUnique); sort($metadata['allUnique']); } //Count user-queried files $metadata['numUserFiles'] = 0; foreach($otherEmwinFiles['user'] as $thisCardFiles) $metadata['numUserFiles'] += count($thisCardFiles); $metadata['maxUserFiles'] = $config['otheremwin']['maxUserFiles']; //Sort and parse messages foreach(array('system', 'user') as $thisType) { //Safety for user-queried files if($thisType == 'user' && $config['otheremwin']['maxUserFiles'] != 0 && $metadata['numUserFiles'] > $config['otheremwin']['maxUserFiles']) continue; for($i = 0; $i < count($otherEmwinConfig[$thisType]); $i++) { usort($otherEmwinFiles[$thisType][$i], "sortEMWIN"); foreach($otherEmwinFiles[$thisType][$i] as $thisFile) { $thisFileData = file($thisFile); switch($otherEmwinConfig[$thisType][$i]['format']) { case 'paragraph': $metadata[$thisType][$i] = array_merge($metadata[$thisType][$i], linesToParagraphs($thisFileData, $otherEmwinConfig[$thisType][$i]['truncate'])); break; case 'formatted': $thisFileString = ""; foreach($thisFileData as $key => $value) { if($key < $otherEmwinConfig[$thisType][$i]['truncate']) continue; $thisFileString .= trim($value) . "\n"; } $metadata[$thisType][$i][] = $thisFileString; break; } } } } //Satellite TLE $latestTleFile = findNewestEmwin($allEmwinFiles, "EPHTWOUS"); $metadata['satelliteTle'] = []; if($latestTleFile != "") { $latestTleArray = file($latestTleFile); for($i = 0; $i < count($latestTleArray); $i += 3) $metadata['satelliteTle'][] = trim($latestTleArray[$i]); sort($metadata['satelliteTle']); $metadata['satelliteTleDate'] = getEMWINDate($latestTleFile); } //EMWIN License $emwinLicenseFile = findNewestEmwin($allEmwinFiles, "FEEBAC1S"); if($emwinLicenseFile == "") { $metadata['emwinLicense'] = "None Found"; $metadata['emwinLicenseDate'] = "N/A"; } else { $metadata['emwinLicense'] = linesToParagraphs(file($emwinLicenseFile), 4)[0]; $metadata['emwinLicenseDate'] = getEMWINDate($emwinLicenseFile); } } if(array_key_exists('adminPath', $config['general']) && is_dir($config['general']['adminPath'])) { //Admin update $allAdminFiles = scandir_recursive($config['general']['adminPath'], true); $allAdminFiles = preg_grep("/[0-9]{4}\.[0-9]{2}\.[0-9]{2}\.(txt|TXT)$/", $allAdminFiles); usort($allAdminFiles, "sortByBasename"); $adminDateParts = explode("_", basename($allAdminFiles[count($allAdminFiles) - 1])); $metadata['latestAdminDate'] = DateTimeImmutable::createFromFormat("Y.m.d", substr($adminDateParts[count($adminDateParts) - 1], 0, -4))->format("M d, Y"); //Detect if it's unicode, and if it's not, convert it to UTF-8 from an assumed WINDOWS-1252 $latestAdminData = file_get_contents($allAdminFiles[count($allAdminFiles) - 1]); if(!preg_match('//u', $latestAdminData)) $latestAdminData = iconv('WINDOWS-1252', 'UTF-8', $latestAdminData); $metadata['latestAdmin'] = $latestAdminData; } } //System Info elseif($_GET['id'] == 'sysInfo') { if(!$config['general']['showSysInfo']) die(); $metadata['sysData'] = []; //Windows System Info if(PHP_OS_FAMILY == "Windows") { //Windows Version $metadata['sysData'][] = array("name" => "Windows Version", "value" => ucfirst(php_uname('v'))); //Get Data from PowerShell $powershellData = json_decode(shell_exec("powershell -EncodedCommand " . "JABtAGUAbQBvAHIAeQAgAD0AIABnAGMAaQBtACAAdwBpAG4AMwAyAF8AbwBwAGU" . "AcgBhAHQAaQBuAGcAcwB5AHMAdABlAG0AIAAtAFAAcgBvAHAAZQByAHQAeQAgAF" . "QAbwB0AGEAbABWAGkAcwBpAGIAbABlAE0AZQBtAG8AcgB5AFMAaQB6AGUALABGA" . "HIAZQBlAFAAaAB5AHMAaQBjAGEAbABNAGUAbQBvAHIAeQA7ACAAJABiAGEAdAB0" . "AGUAcgB5ACAAPQAgAGcAYwBpAG0AIAB3AGkAbgAzADIAXwBiAGEAdAB0AGUAcgB" . "5ADsAIAAkAHIAZQB0AFYAYQBsACAAPQAgAEAAewB1AHAAdABpAG0AZQAgAD0AIA" . "AkACgAKABnAGUAdAAtAGQAYQB0AGUAKQAgAC0AIAAoAGcAYwBpAG0AIABXAGkAb" . "gAzADIAXwBPAHAAZQByAGEAdABpAG4AZwBTAHkAcwB0AGUAbQApAC4ATABhAHMA" . "dABCAG8AbwB0AFUAcABUAGkAbQBlACkALgBUAG8AdABhAGwAUwBlAGMAbwBuAGQ" . "AcwA7ACAAYwBwAHUATABvAGEAZAAgAD0AIAAkACgAZwBjAGkAbQAgAFcAaQBuAD" . "MAMgBfAFAAcgBvAGMAZQBzAHMAbwByACAALQBQAHIAbwBwAGUAcgB0AHkAIABMA" . "G8AYQBkAFAAZQByAGMAZQBuAHQAYQBnAGUAKQAuAEwAbwBhAGQAUABlAHIAYwBl" . "AG4AdABhAGcAZQA7ACAAbQBlAG0AVABvAHQAYQBsACAAPQAgACQAbQBlAG0AbwB" . "yAHkALgBUAG8AdABhAGwAVgBpAHMAaQBiAGwAZQBNAGUAbQBvAHIAeQBTAGkAeg" . "BlADsAIABtAGUAbQBBAHYAYQBpAGwAYQBiAGwAZQAgAD0AIAAkAG0AZQBtAG8Ac" . "gB5AC4ARgByAGUAZQBQAGgAeQBzAGkAYwBhAGwATQBlAG0AbwByAHkAOwB9ADsA" . "IABpAGYAKAAkAGIAYQB0AHQAZQByAHkAIAAtAG4AZQAgACQAbgB1AGwAbAApAHs" . "AJAByAGUAdABWAGEAbAAuAEEAZABkACgAIgBwAG8AdwBlAHIAUwB0AGEAdAB1AH" . "MAIgAsACAAQAAoADIALAAzACwANgAsADcALAA4ACwAOQApACAALQBjAG8AbgB0A" . "GEAaQBuAHMAIAAkAGIAYQB0AHQAZQByAHkALgBCAGEAdAB0AGUAcgB5AFMAdABh" . "AHQAdQBzACkAOwAgACQAcgBlAHQAVgBhAGwALgBBAGQAZAAoACIAYgBhAHQAdAB" . "lAHIAeQBQAGUAcgBjAGUAbgB0AGEAZwBlACIALAAgACQAYgBhAHQAdABlAHIAeQ" . "AuAEUAcwB0AGkAbQBhAHQAZQBkAEMAaABhAHIAZwBlAFIAZQBtAGEAaQBuAGkAb" . "gBnACkAOwB9ACAAJAByAGUAdABWAGEAbAAgAHwAIABDAG8AbgB2AGUAcgB0AFQA" . "bwAtAEoAUwBPAE4AIAAtAEMAbwBtAHAAcgBlAHMAcwA=")); //Parse data - hand some of it off for later if(property_exists($powershellData, "powerStatus")) $metadata['sysData'][] = array("name" => "Power Status", "value" => $powershellData->powerStatus ? "Plugged In" : "Unplugged"); if(property_exists($powershellData, "batteryPercentage")) $metadata['sysData'][] = array("name" => "Battery Percentage", "value" => $powershellData->batteryPercentage . "%"); $metadata['sysData'][] = array("name" => "CPU Load Average", "value" => $powershellData->cpuLoad . "%"); $uptimeStr = $powershellData->uptime; $memTotal = $powershellData->memTotal; $memAvailable = $powershellData->memAvailable; //Info about running processes (parsed later) $runningProcesses = shell_exec("tasklist"); //System temp data on Windows is not supported $metadata['tempData'] = []; } //Other Systems (assume Linux-like system) else { //Kernel Info $metadata['sysData'][] = array("name" => "OS Version", "value" => trim(shell_exec("lsb_release -ds"))); $metadata['sysData'][] = array("name" => "Kernel Version", "value" => php_uname('s') . " " . php_uname('r')); //Uptime $uptimeStr = file_get_contents('/proc/uptime'); //CPU Load $loadAvg = sys_getloadavg(); $metadata['sysData'][] = array("name" => "CPU Load (1min, 5min, 15min)", "value" => round($loadAvg[0], 2) . ", " . round($loadAvg[1], 2) . ", " . round($loadAvg[2], 2)); //Memory Usage (parsed later) $memFile = fopen('/proc/meminfo','r'); $memTotal = 0; $memAvailable = 0; while ($line = fgets($memFile)) { $memPieces = []; if (preg_match('/^MemTotal:\s+(\d+)\skB$/', $line, $memPieces)) $memTotal = $memPieces[1]; if (preg_match('/^MemAvailable:\s+(\d+)\skB$/', $line, $memPieces)) $memAvailable = $memPieces[1]; } fclose($memFile); //Power Status if(file_exists("/sys/class/power_supply/AC/online")) $metadata['sysData'][] = array("name" => "Power Status", "value" => file_get_contents("/sys/class/power_supply/AC/online") == 1 ? "Plugged In" : "Unplugged"); //Battery if(file_exists("/sys/class/power_supply/BAT0/capacity")) $metadata['sysData'][] = array("name" => "Battery Percentage", "value" => trim(file_get_contents("/sys/class/power_supply/BAT0/capacity")) . "%"); //System Temps $hwmonDirs = scandir("/sys/class/hwmon/"); $metadata['tempData'] = []; foreach($hwmonDirs as $thisHwmon) { if($thisHwmon == "." || $thisHwmon == "..") continue; $thisDevicesSensors = glob("/sys/class/hwmon/" . $thisHwmon . "/{temp,fan}*_input", GLOB_BRACE); if(count($thisDevicesSensors) == 0) continue; $tempBaseName = ucfirst(str_replace("_", " ", trim(file_get_contents("/sys/class/hwmon/" . $thisHwmon . "/name")))); $tempCount = $fanCount = 1; foreach($thisDevicesSensors as $thisSensor) { $metadata['tempData'][] = []; if(strpos($thisSensor, "temp") !== false) { if(file_exists(str_replace("input", "label", $thisSensor))) $thisSensorName = trim(file_get_contents(str_replace("input", "label", $thisSensor))) . " Temp"; else $thisSensorName = "$tempBaseName Temp" . (count($thisDevicesSensors) > 1 ? " $tempCount" : ""); $metadata['tempData'][count($metadata['tempData']) - 1]['name'] = $thisSensorName; //Some sensors error when below 0 degrees - catch these errors set_error_handler("convertToException"); try { $thisSensorData = file_get_contents($thisSensor); $metadata['tempData'][count($metadata['tempData']) - 1]['value'] = intval(trim($thisSensorData)) / 1000 . "° C"; } catch (exception $e) { //Failed; return an error $metadata['tempData'][count($metadata['tempData']) - 1]['value'] = "Error!"; } //Return to typical error handler restore_error_handler(); $tempCount++; } else { if(file_exists(str_replace("input", "label", $thisSensor))) $thisSensorName = trim(file_get_contents(str_replace("input", "label", $thisSensor))); else $thisSensorName = "$tempBaseName Fan" . (count($thisDevicesSensors) > 1 ? " $fanCount" : ""); $metadata['tempData'][count($metadata['tempData']) - 1]['name'] = $thisSensorName . " Speed"; $metadata['tempData'][count($metadata['tempData']) - 1]['value'] = trim(file_get_contents($thisSensor)) . " RPM"; $fanCount++; } } } //Info about running processes $runningProcesses = shell_exec("ps acxo command"); } //Disk Usage (all OSs) $totalDiskSpace = round(disk_total_space($programPath) / 1073741824, 2); $usedDiskSpace = $totalDiskSpace - round(disk_free_space($programPath) / 1073741824, 2); $metadata['sysData'][] = array("name" => "Disk Used", "value" => $usedDiskSpace . "GB / " . $totalDiskSpace . "GB - " . round(($usedDiskSpace / $totalDiskSpace) * 100, 2) . "%"); //Memory Usage $metadata['sysData'][] = array("name" => "Memory Used", "value" => round(($memTotal - $memAvailable) / 1048576, 2) . "GB / " . round($memTotal / 1048576, 2) . "GB - " . round((($memTotal - $memAvailable) / $memTotal) * 100, 2) . "%"); //Uptime (all OSs) $num = (int)floatval($uptimeStr); $uptimeStr = str_pad(round(fmod($num, 60)), 2, "0", STR_PAD_LEFT); $num = intdiv($num, 60); $uptimeStr = str_pad($num % 60, 2, "0", STR_PAD_LEFT) . ":" . $uptimeStr; $num = intdiv($num, 60); $uptimeStr = str_pad($num % 24, 2, "0", STR_PAD_LEFT) . ":" . $uptimeStr; $uptimeStr = intdiv($num, 24) . " days, " . $uptimeStr; $metadata['sysData'][] = array("name" => "Uptime", "value" => $uptimeStr); //Find running satellite decoders (all OSs) $noDecoderFound = true; if(stripos($runningProcesses, "goesrecv") !== false || stripos($runningProcesses, "goesproc") !== false) { $noDecoderFound = false; $metadata['sysData'][] = array("name" => "Goesrecv Status", "value" => stripos($runningProcesses, "goesrecv") !== false ? "Running" : "Not Running"); $metadata['sysData'][] = array("name" => "Goesproc Status", "value" => stripos($runningProcesses, "goesproc") !== false ? "Running" : "Not Running"); if(verifyCommand("goesrecv")) $metadata['sysData'][] = array("name" => "Goestools Version", "value" => explode(" ", str_replace("goesrecv -- ", "", explode(PHP_EOL, shell_exec("goesrecv --version"))[0]))[0]); } if(stripos($runningProcesses, "satdump") !== false) { $noDecoderFound = false; $metadata['sysData'][] = array("name" => "SatDump Status", "value" => "Running"); } if($noDecoderFound) $metadata['sysData'][] = array("name" => "Satellite Decoder", "value" => "None Found!"); //SatDump Statistics (all OSs) if(array_key_exists('satdumpAPI', $config['general'])) { $metadata['satdumpData'] = []; set_error_handler("convertToException"); try { $satdumpStats = json_decode(file_get_contents($config['general']['satdumpAPI'])); } catch(exception $e) { $satdumpStats = []; } restore_error_handler(); foreach($satdumpStats as $stat => $value) { $metadata['satdumpData'][]['title'] = ucwords(str_replace("_", " ", $stat)); $metadata['satdumpData'][count($metadata['satdumpData']) - 1]['values'] = []; foreach($value as $subName => $subValue) { if(is_float($subValue)) $valToUse = round($subValue, 5); elseif(is_bool($subValue)) $valToUse = $subValue ? "True" : "False"; else $valToUse = $subValue; $metadata['satdumpData'][count($metadata['satdumpData']) - 1]['values'][] = array("name" => ucwords(str_replace("_", " ", $subName)), "value" => $valToUse); } } } } //Check if it's an image metadata request elseif(array_key_exists($_GET['id'], $config['categories']) && array_key_exists('subid', $_GET) && array_key_exists($_GET['subid'], $config['categories'][$_GET['id']]['data'])) { //Query looks valid; load from disk if available if(!is_dir($config['categories'][$_GET['id']]['data'][$_GET['subid']]['path'])) die("Invalid server config: path for this image type does not exist"); $metadata['title'] = $config['categories'][$_GET['id']]['data'][$_GET['subid']]['title']; $metadata['images'] = []; $formatInfo = getFormatByMode($config['categories'][$_GET['id']]['data'][$_GET['subid']]['mode'], $config['categories'][$_GET['id']]['data'][$_GET['subid']]['filter']); $fileList = scandir_recursive($config['categories'][$_GET['id']]['data'][$_GET['subid']]['path'], $config['categories'][$_GET['id']]['data'][$_GET['subid']]['fast']); $refinedList = preg_grep($formatInfo["regex"], $fileList); foreach($refinedList as $file) { preg_match($formatInfo["regex"], $file, $regexMatches); $DateTime = DateTime::createFromFormat($formatInfo["dateFormat"], $regexMatches['date'], new DateTimeZone("UTC")); if($DateTime === false) continue; $DateTime->setTimezone(new DateTimeZone(date_default_timezone_get())); $metadata['images'][]['description'] = $DateTime->format('F j, Y g:i A T'); $metadata['images'][count($metadata['images']) - 1]['timestamp'] = $DateTime->getTimestamp(); } usort($metadata['images'], 'sortByTimestamp'); } //Nothing matched - request invalid else die(); header('Content-Type: application/json; charset=utf-8'); echo json_encode($metadata); } elseif($_GET['type'] == "data") { if(!array_key_exists('id', $_GET) || !array_key_exists($_GET['id'], $config['categories']) || !array_key_exists('subid', $_GET) || !array_key_exists($_GET['subid'], $config['categories'][$_GET['id']]['data'])) die(); //Get image at requested timestamp if(array_key_exists('timestamp', $_GET)) { $DateTime = new DateTime("now", new DateTimeZone("UTC")); $DateTime->setTimestamp($_GET['timestamp']); switch($config['categories'][$_GET['id']]['data'][$_GET['subid']]['mode']) { case "satdump_geo": $regex = "/(\\\\|\/)" . $DateTime->format('Y-m-d_H-i-s') . "(\\\\|\/)[^\\\\\/]*{$config['categories'][$_GET['id']]['data'][$_GET['subid']]['filter']}\..{3}$/i"; break; case "begin": $regex = "/(\\\\|\/)" . $DateTime->format('YmdHis') . "[^\\\\\/]*{$config['categories'][$_GET['id']]['data'][$_GET['subid']]['filter']}[^\\\\\/]*\..{3}$/i"; break; case "beginu": $regex = "/(\\\\|\/)" . $DateTime->format('Ymd_His') . "[^\\\\\/]*{$config['categories'][$_GET['id']]['data'][$_GET['subid']]['filter']}[^\\\\\/]*\..{3}$/i"; break; case "beginz": $regex = "/(\\\\|\/)" . $DateTime->format('Ymd\THis\Z') . "[^\\\\\/]*{$config['categories'][$_GET['id']]['data'][$_GET['subid']]['filter']}[^\\\\\/]*\..{3}$/i"; break; case "emwin": $regex = "/_" . $DateTime->format('YmdHis') . "_[^\\\\\/]*{$config['categories'][$_GET['id']]['data'][$_GET['subid']]['filter']}[^\\\\\/]*\..{3}$/i"; break; case "xrit": $regex = "/{$config['categories'][$_GET['id']]['data'][$_GET['subid']]['filter']}[^\\\\\/]*" . $DateTime->format('YmdHi') . "\..{3}$/i"; break; case "end": $regex = "/{$config['categories'][$_GET['id']]['data'][$_GET['subid']]['filter']}[^\\\\\/]*" . $DateTime->format('YmdHis') . "\..{3}$/i"; break; case "endu": $regex = "/{$config['categories'][$_GET['id']]['data'][$_GET['subid']]['filter']}[^\\\\\/]*" . $DateTime->format('Ymd_His') . "\..{3}$/i"; break; case "endz": $regex = "/{$config['categories'][$_GET['id']]['data'][$_GET['subid']]['filter']}[^\\\\\/]*" . $DateTime->format('Ymd\THis\Z') . "\..{3}$/i"; break; default: die(); break; } $fileList = scandir_recursive($config['categories'][$_GET['id']]['data'][$_GET['subid']]['path'], $config['categories'][$_GET['id']]['data'][$_GET['subid']]['fast']); $refinedList = array_values(preg_grep($regex, $fileList)); if($refinedList === false || count($refinedList) == 0) die(); $returnImage = $refinedList[0]; } //Get newest image else { $formatInfo = getFormatByMode($config['categories'][$_GET['id']]['data'][$_GET['subid']]['mode'], $config['categories'][$_GET['id']]['data'][$_GET['subid']]['filter']); $fileList = scandir_recursive($config['categories'][$_GET['id']]['data'][$_GET['subid']]['path'], $config['categories'][$_GET['id']]['data'][$_GET['subid']]['fast']); $refinedList = array_values(preg_grep($formatInfo["regex"], $fileList)); if($refinedList === false || count($refinedList) == 0) die(); $newestTimestamp = $newest = 0; for($i = 0; $i < count($refinedList); $i++) { preg_match($formatInfo["regex"], $refinedList[$i], $regexMatches); $DateTime = DateTime::createFromFormat($formatInfo["dateFormat"], $regexMatches['date'], new DateTimeZone("UTC")); if($DateTime === false) continue; if($DateTime->getTimestamp() > $newestTimestamp) { $newest = $i; $newestTimestamp = $DateTime->getTimestamp(); } } $returnImage = $refinedList[$newest]; } header('Content-Type: ' . mime_content_type($returnImage)); header('Content-Disposition: inline; filename=' . basename($returnImage)); header('Content-Length: ' . filesize($returnImage)); readfile($returnImage); } elseif($_GET['type'] == "hurricaneData") { if(!array_key_exists('timestamp', $_GET) || !array_key_exists('id', $_GET) || preg_match("/^[A-Z0-9]{2}$/", $_GET['id']) == 0 || !array_key_exists('product', $_GET) || preg_match("/^[A-Z0-9]{6}$/", $_GET['product']) == 0) die(); $path = findSpecificEMWIN(scandir_recursive($config['general']['emwinPath'], $config['general']['fastEmwin']), $_GET['product'].$_GET['id'], $_GET['timestamp']); header('Content-Type: ' . mime_content_type($path)); header('Content-Disposition: inline; filename=' . basename($path)); header('Content-Length: ' . filesize($path)); readfile($path); } elseif($_GET['type'] == "localRadarData") { if(!array_key_exists('timestamp', $_GET)) die(); $path = findSpecificEMWIN(scandir_recursive($config['general']['emwinPath'], $config['general']['fastEmwin']), "RAD" . $currentSettings[$selectedProfile]['radarCode'], $_GET['timestamp']); header('Content-Type: ' . mime_content_type($path)); header('Content-Disposition: inline; filename=' . basename($path)); header('Content-Length: ' . filesize($path)); readfile($path); } elseif($_GET['type'] == "tle") { $path = findNewestEmwin(scandir_recursive($config['general']['emwinPath'], $config['general']['fastEmwin']), "EPHTWOUS"); header("Pragma: no-cache"); header('Content-Type: ' . mime_content_type($path)); header("Cache-Control: max-age=0, no-cache, no-store, must-revalidate"); header("Expires: Thu, 01 Jan 1970 00:00:01 GMT"); header('Content-Disposition: attachment; filename=weather.txt'); header('Content-Length: ' . filesize($path)); readfile($path); } elseif($_GET['type'] == "settings") { if($_GET['dropdown'] == "") die(); $dropdownList = []; switch($_GET['dropdown']) { case "general": //Query all emwin files $allEmwinFiles = scandir_recursive($config['general']['emwinPath'], $config['general']['fastEmwin']); //Find pertinent data in emwin files $dropdownList['radar'] = $dropdownList['stateAbbr'] = $dropdownList['orig'] = $dropdownList['rwrOrig'] = $dropdownList['timezone'] = $allOrig = $allRwrOrig = []; foreach($allEmwinFiles as $thisFile) { if(strpos($thisFile, "-RAD") !== false) $dropdownList['radar'][] = substr($thisFile, -9, 5); if(strpos($thisFile, "-ZFP") !== false) { $dropdownList['stateAbbr'][] = substr($thisFile, -6, 2); $allOrig[] = substr($thisFile, -9, 5); } if(strpos($thisFile, "-RWR") !== false) { $dropdownList['stateAbbr'][] = substr($thisFile, -6, 2); //Probably redundant $allRwrOrig[] = substr($thisFile, -9, 5); } } //Distill information from EMWIN files into user menus $dropdownList['radar'] = array_unique($dropdownList['radar']); $dropdownList['stateAbbr'] = array_unique($dropdownList['stateAbbr']); $allOrig = array_unique($allOrig); $allRwrOrig = array_unique($allRwrOrig); sort($dropdownList['radar']); sort($dropdownList['stateAbbr']); //Additional Processing for Product Office Listings foreach($allOrig as $thisOrig) $dropdownList['orig'][] = array("state" => substr($thisOrig, 3, 2), "orig" => substr($thisOrig, 0, 3)); foreach($allRwrOrig as $thisOrig) $dropdownList['rwrOrig'][] = array("state" => substr($thisOrig, 3, 2), "orig" => substr($thisOrig, 0, 3)); usort($dropdownList['rwrOrig'], "sortOrig"); usort($dropdownList['orig'], "sortOrig"); //Timezones $dropdownList['timezone'] = DateTimeZone::listIdentifiers(DateTimeZone::AMERICA | DateTimeZone::ATLANTIC | DateTimeZone::PACIFIC); sort($dropdownList['timezone']); break; case "wxZone": if(!preg_match("/^[A-Z0-9]{5}$/", $_GET['orig'])) break; $localZfpPath = findNewestEMWIN(scandir_recursive($config['general']['emwinPath'], $config['general']['fastEmwin']), "ZFP".$_GET['orig']); if($localZfpPath == "") break; $localZfpArr = file($localZfpPath); $i = 0; foreach($localZfpArr as $thisLine) { if(preg_match("/^[A-Z]{3}[0-9]{3}/", $thisLine)) { $dropdownList[] = array("wxZone" => substr($thisLine, 0, 6), "city" => ""); $j = $i + 1; while(!is_numeric($localZfpArr[$j][0])) { $dropdownList[count($dropdownList) - 1]["city"] .= str_replace(array("-", "..."), ", ", $localZfpArr[$j]); $j++; } } $i++; } for($i = 0; $i < count($dropdownList); $i++) $dropdownList[$i]["city"] = trim($dropdownList[$i]["city"], " ,\n\r\t\v\x00"); usort($dropdownList, "sortByCity"); break; case "city": if(!preg_match("/^[A-Z0-9]{5}$/", $_GET['rwrOrig'])) break; $localRwrPath = findNewestEMWIN(scandir_recursive($config['general']['emwinPath'], $config['general']['fastEmwin']), "RWR".$_GET['rwrOrig']); if($localRwrPath == "") break; $localRwrArr = file($localRwrPath); $currentlyDecoding = false; foreach($localRwrArr as $thisLine) { if(stripos($thisLine, "CITY") === 0) { $currentlyDecoding = true; continue; } if(strpos($thisLine, "$$") === 0 || stripos($thisLine, "STATION/POSITION") === 0) { $currentlyDecoding = false; continue; } if(trim($thisLine) == "" || stripos($thisLine, "...") === 0 || stripos($thisLine, "6HR ") === 0) continue; if($currentlyDecoding) $dropdownList[] = trim(preg_replace("/[^A-Za-z0-9 \-.]/", "", substr($thisLine, 0, 15))); } sort($dropdownList); break; case "theme": $themes = findAllThemes(); $dropdownList['default'] = "Built-In (Dark)"; foreach($themes as $theme => $themeData) { if(array_key_exists("name", $themeData)) $dropdownList[$theme] = htmlspecialchars(strip_tags($themeData['name'])); else $dropdownList[$theme] = htmlspecialchars(strip_tags($theme)); } break; default: break; } header('Content-Type: application/json; charset=utf-8'); echo json_encode($dropdownList); } elseif($_GET['type'] == "alertJSON") { $returnData = []; $latestHurricaneMessage = 0; $returnData['localEmergencies'] = $returnData['blueAlerts'] = $returnData['amberAlerts'] = $returnData['civilDangerWarnings'] = $returnData['localEvacuations'] = $returnData['hurricaneStatement'] = $returnData['weatherWarnings'] = $returnData['spaceWeatherAlerts'] = []; //Query all emwin files $allEmwinFiles = scandir_recursive($config['general']['emwinPath'], $config['general']['fastEmwin']); $alertStateAbbrs = "(" . implode('|', array_unique(array($currentSettings[$selectedProfile]['stateAbbr'], substr($currentSettings[$selectedProfile]['orig'], -2), substr($currentSettings[$selectedProfile]['rwrOrig'], -2)))) . ")"; //Find pertinent files $wwFiles = preg_grep("/-(SQW|DSW|FRW|FFW|FLW|SVR|TOR|EWW)" . $currentSettings[$selectedProfile]['orig'] . "\.TXT$/i", $allEmwinFiles); $spsFiles = preg_grep("/-SPS" . $currentSettings[$selectedProfile]['orig'] . "\.TXT$/i", $allEmwinFiles); $hlsFiles = preg_grep("/-HLS.*" . $currentSettings[$selectedProfile]['orig'] . "\.TXT$/i", $allEmwinFiles); $laeFiles = preg_grep("/-LAE.*$alertStateAbbrs\.TXT$/i", $allEmwinFiles); $bluFiles = preg_grep("/-BLU.*$alertStateAbbrs\.TXT$/i", $allEmwinFiles); $caeFiles = preg_grep("/-CAE.*$alertStateAbbrs\.TXT$/i", $allEmwinFiles); $cdwFiles = preg_grep("/-CDW.*$alertStateAbbrs\.TXT$/i", $allEmwinFiles); $eviFiles = preg_grep("/-EVI.*$alertStateAbbrs\.TXT$/i", $allEmwinFiles); //Load data from files found foreach($laeFiles as $thisFile) $returnData['localEmergencies'] = array_merge($returnData['localEmergencies'], linesToParagraphs(file($thisFile), 4)); foreach($bluFiles as $thisFile) $returnData['blueAlerts'] = array_merge($returnData['blueAlerts'], linesToParagraphs(file($thisFile), 4)); foreach($caeFiles as $thisFile) $returnData['amberAlerts'] = array_merge($returnData['amberAlerts'], linesToParagraphs(file($thisFile), 4)); foreach($cdwFiles as $thisFile) $returnData['civilDangerWarnings'] = array_merge($returnData['civilDangerWarnings'], linesToParagraphs(file($thisFile), 4)); foreach($eviFiles as $thisFile) $returnData['localEvacuations'] = array_merge($returnData['localEvacuations'], linesToParagraphs(file($thisFile), 4)); //Hurricane Statement - Only get most recent foreach($hlsFiles as $thisFile) { $hurricaneStatementLines = file($thisFile); foreach($hurricaneStatementLines as $hurricaneStatementLine) { $thisLine = trim($hurricaneStatementLine); if($thisLine != "" && is_numeric($thisLine[0])) { preg_match("/^(?