diff --git a/birdnet-pi/rootfs/helpers/views.php b/birdnet-pi/rootfs/helpers/views.php
new file mode 100644
index 000000000..359d1b9a8
--- /dev/null
+++ b/birdnet-pi/rootfs/helpers/views.php
@@ -0,0 +1,457 @@
+ $_SESSION['behind_time'] + 86400)) {
+ shell_exec("sudo -u".$user." git -C ".$home."/BirdNET-Pi fetch > /dev/null 2>/dev/null &");
+ $str = trim(shell_exec("sudo -u".$user." git -C ".$home."/BirdNET-Pi status"));
+ if (preg_match("/behind '.*?' by (\d+) commit(s?)\b/", $str, $matches)) {
+ $num_commits_behind = $matches[1];
+ }
+ if (preg_match('/\b(\d+)\b and \b(\d+)\b different commits each/', $str, $matches)) {
+ $num1 = (int) $matches[1];
+ $num2 = (int) $matches[2];
+ $num_commits_behind = $num1 + $num2;
+ }
+ if (stripos($str, "Your branch is up to date") !== false) {
+ $num_commits_behind = '0';
+ }
+ $_SESSION['behind'] = $num_commits_behind;
+ $_SESSION['behind_time'] = time();
+}
+if(isset($_SESSION['behind'])&&intval($_SESSION['behind']) >= 99) {?>
+
+WARNING: Your latitude and longitude are not set properly. Please do so now in Tools -> Settings.";
+}
+elseif ($config["LATITUDE"] == "0.000") {
+ echo "
+";}
+ if($_GET['view'] == "System Controls"){
+ ensure_authenticated();
+ include('scripts/system_controls.php');
+ }
+ if($_GET['view'] == "Services"){
+ ensure_authenticated();
+ include('scripts/service_controls.php');
+ }
+ if($_GET['view'] == "Spectrogram"){include('spectrogram.php');}
+ if($_GET['view'] == "View Log"){echo "
";}
+ if($_GET['view'] == "Overview"){include('overview.php');}
+ if($_GET['view'] == "Todays Detections"){include('todays_detections.php');}
+ if($_GET['view'] == "Kiosk"){$kiosk = true;include('todays_detections.php');}
+ if($_GET['view'] == "Species Stats"){include('stats.php');}
+ if($_GET['view'] == "Weekly Report"){include('weekly_report.php');}
+ if($_GET['view'] == "Streamlit"){echo "
";}
+ if($_GET['view'] == "Daily Charts"){include('history.php');}
+ if($_GET['view'] == "Tools"){
+ ensure_authenticated();
+ $url = $_SERVER['SERVER_NAME']."/scripts/adminer.php";
+ echo "
";
+ }
+ if($_GET['view'] == "Recordings"){include('play.php');}
+ if($_GET['view'] == "Settings"){include('scripts/config.php');}
+ if($_GET['view'] == "Advanced"){include('scripts/advanced.php');}
+ if($_GET['view'] == "Included"){
+ ensure_authenticated();
+ if(isset($_GET['species']) && isset($_GET['add'])){
+ $file = './scripts/include_species_list.txt';
+ $str = file_get_contents("$file");
+ $str = preg_replace("/(^[\r\n]*|[\r\n]+)[\s\t]*[\r\n]+/", "\n", $str);
+ file_put_contents("$file", "$str");
+ if(isset($_GET['species'])){
+ foreach ($_GET['species'] as $selectedOption)
+ file_put_contents("./scripts/include_species_list.txt", htmlspecialchars_decode($selectedOption, ENT_QUOTES)."\n", FILE_APPEND);
+ }
+ } elseif(isset($_GET['species']) && isset($_GET['del'])){
+ $file = './scripts/include_species_list.txt';
+ $str = file_get_contents("$file");
+ $str = preg_replace('/^\h*\v+/m', '', $str);
+ file_put_contents("$file", "$str");
+ foreach($_GET['species'] as $selectedOption) {
+ $content = file_get_contents("../BirdNET-Pi/include_species_list.txt");
+ $newcontent = str_replace($selectedOption, "", "$content");
+ $newcontent = str_replace(htmlspecialchars_decode($selectedOption, ENT_QUOTES), "", "$newcontent");
+ file_put_contents("./scripts/include_species_list.txt", "$newcontent");
+ }
+ $file = './scripts/include_species_list.txt';
+ $str = file_get_contents("$file");
+ $str = preg_replace('/^\h*\v+/m', '', $str);
+ file_put_contents("$file", "$str");
+ }
+ include('./scripts/include_list.php');
+ }
+ if($_GET['view'] == "Excluded"){
+ ensure_authenticated();
+ if(isset($_GET['species']) && isset($_GET['add'])){
+ $file = './scripts/exclude_species_list.txt';
+ $str = file_get_contents("$file");
+ $str = preg_replace("/(^[\r\n]*|[\r\n]+)[\s\t]*[\r\n]+/", "\n", $str);
+ file_put_contents("$file", "$str");
+ foreach ($_GET['species'] as $selectedOption)
+ file_put_contents("./scripts/exclude_species_list.txt", htmlspecialchars_decode($selectedOption, ENT_QUOTES)."\n", FILE_APPEND);
+ } elseif (isset($_GET['species']) && isset($_GET['del'])){
+ $file = './scripts/exclude_species_list.txt';
+ $str = file_get_contents("$file");
+ $str = preg_replace('/^\h*\v+/m', '', $str);
+ file_put_contents("$file", "$str");
+ foreach($_GET['species'] as $selectedOption) {
+ $content = file_get_contents("./scripts/exclude_species_list.txt");
+ $newcontent = str_replace($selectedOption, "", "$content");
+ $newcontent = str_replace(htmlspecialchars_decode($selectedOption, ENT_QUOTES), "", "$content");
+ file_put_contents("./scripts/exclude_species_list.txt", "$newcontent");
+ }
+ $file = './scripts/exclude_species_list.txt';
+ $str = file_get_contents("$file");
+ $str = preg_replace('/^\h*\v+/m', '', $str);
+ file_put_contents("$file", "$str");
+ }
+ include('./scripts/exclude_list.php');
+ }
+ if($_GET['view'] == "Converted"){
+ ensure_authenticated();
+ if(isset($_GET['species']) && isset($_GET['add'])){
+ $file = './scripts/convert_species_list.txt';
+ $str = file_get_contents("$file");
+ $str = preg_replace("/(^[\r\n]*|[\r\n]+)[\s\t]*[\r\n]+/", "\n", $str);
+ file_put_contents("$file", "$str");
+ // Write $_GET['species'] to the file
+ file_put_contents("./scripts/convert_species_list.txt", htmlspecialchars_decode($_GET['species'], ENT_QUOTES)."\n", FILE_APPEND);
+ } elseif (isset($_GET['species']) && isset($_GET['del'])){
+ $file = './scripts/convert_species_list.txt';
+ $str = file_get_contents("$file");
+ $str = preg_replace('/^\h*\v+/m', '', $str);
+ file_put_contents("$file", "$str");
+ foreach($_GET['species'] as $selectedOption) {
+ $content = file_get_contents("./scripts/convert_species_list.txt");
+ $newcontent = str_replace($selectedOption, "", "$content");
+ $newcontent = str_replace(htmlspecialchars_decode($selectedOption, ENT_QUOTES), "", "$content");
+ file_put_contents("./scripts/convert_species_list.txt", "$newcontent");
+ }
+ $file = './scripts/convert_species_list.txt';
+ $str = file_get_contents("$file");
+ $str = preg_replace('/^\h*\v+/m', '', $str);
+ file_put_contents("$file", "$str");
+ }
+ include('./scripts/convert_list.php');
+ }
+ if($_GET['view'] == "File"){
+ echo "
";
+ }
+ if($_GET['view'] == "Webterm"){
+ ensure_authenticated('You cannot access the web terminal');
+ echo "
";
+ }
+} elseif(isset($_GET['submit'])) {
+ ensure_authenticated();
+ $allowedCommands = array('sudo systemctl stop livestream.service && sudo systemctl stop icecast2.service',
+ 'sudo systemctl restart livestream.service && sudo systemctl restart icecast2.service',
+ 'sudo systemctl disable --now livestream.service && sudo systemctl disable icecast2 && sudo systemctl stop icecast2.service',
+ 'sudo systemctl enable icecast2 && sudo systemctl start icecast2.service && sudo systemctl enable --now livestream.service',
+ 'sudo systemctl stop web_terminal.service',
+ 'sudo systemctl restart web_terminal.service',
+ 'sudo systemctl disable --now web_terminal.service',
+ 'sudo systemctl enable --now web_terminal.service',
+ 'sudo systemctl stop birdnet_log.service',
+ 'sudo systemctl restart birdnet_log.service',
+ 'sudo systemctl disable --now birdnet_log.service',
+ 'sudo systemctl enable --now birdnet_log.service',
+ 'sudo systemctl stop birdnet_analysis.service',
+ 'sudo systemctl restart birdnet_analysis.service',
+ 'sudo systemctl disable --now birdnet_analysis.service',
+ 'sudo systemctl enable --now birdnet_analysis.service',
+ 'sudo systemctl stop birdnet_stats.service',
+ 'sudo systemctl restart birdnet_stats.service',
+ 'sudo systemctl disable --now birdnet_stats.service',
+ 'sudo systemctl enable --now birdnet_stats.service',
+ 'sudo systemctl stop birdnet_recording.service',
+ 'sudo systemctl restart birdnet_recording.service',
+ 'sudo systemctl disable --now birdnet_recording.service',
+ 'sudo systemctl enable --now birdnet_recording.service',
+ 'sudo systemctl stop chart_viewer.service',
+ 'sudo systemctl restart chart_viewer.service',
+ 'sudo systemctl disable --now chart_viewer.service',
+ 'sudo systemctl enable --now chart_viewer.service',
+ 'sudo systemctl stop spectrogram_viewer.service',
+ 'sudo systemctl restart spectrogram_viewer.service',
+ 'sudo systemctl disable --now spectrogram_viewer.service',
+ 'sudo systemctl enable --now spectrogram_viewer.service',
+ 'sudo systemctl enable '.get_service_mount_name().' && sudo reboot',
+ 'sudo systemctl disable '.get_service_mount_name().' && sudo reboot',
+ 'stop_core_services.sh',
+ 'restart_services.sh',
+ 'sudo reboot',
+ 'update_birdnet.sh',
+ 'sudo shutdown now',
+ 'sudo clear_all_data.sh');
+ $command = $_GET['submit'];
+ if(in_array($command,$allowedCommands)){
+ if(isset($command)){
+ $initcommand = $command;
+ if (strpos($command, "systemctl") !== false) {
+ //If there more than one command to execute, processes then separately
+ //currently only livestream service uses multiple commands to interact with the required services
+ if (strpos($command, " && ") !== false) {
+ $separate_commands = explode("&&", trim($command));
+ $new_multiservice_status_command = "";
+ foreach ($separate_commands as $indiv_service_command) {
+ //explode the string by " " space so we can get each individual component of the command
+ //and eventually the service name at the end
+ $separate_command_tmp = explode(" ", trim($indiv_service_command));
+ //get the service names
+ $new_multiservice_status_command .= " " . trim(end($separate_command_tmp));
+ }
+
+ $service_names = $new_multiservice_status_command;
+ } else {
+ //only one service needs restarting so we only need to query the status of one service
+ $tmp = explode(" ", trim($command));
+ $service_names = end($tmp);
+ }
+
+ $command .= " & sleep 3;sudo systemctl status " . $service_names;
+ }
+ if($initcommand == "update_birdnet.sh") {
+ session_unset();
+ }
+ $results = shell_exec("$command 2>&1");
+ $results = str_replace("FAILURE", "
FAILURE", $results);
+ $results = str_replace("failed", "
failed",$results);
+ $results = str_replace("active (running)", "
active (running)",$results);
+ $results = str_replace("Your branch is up to date", "
Your branch is up to date",$results);
+
+ $results = str_replace("(+)", "(
+)",$results);
+ $results = str_replace("(-)", "(
-)",$results);
+
+ // split the input string into lines
+ $lines = explode("\n", $results);
+
+ // iterate over each line
+ foreach ($lines as &$line) {
+ // check if the line matches the pattern
+ if (preg_match('/^(.+?)\s*\|\s*(\d+)\s*([\+\- ]+)(\d+)?$/', $line, $matches)) {
+ // extract the filename, count, and indicator letters
+ $filename = $matches[1];
+ $count = $matches[2];
+ $diff = $matches[3];
+ $delta = $matches[4] ?? '';
+ // determine the indicator letters
+ $diff_array = str_split($diff);
+ $indicators = array_map(function ($d) use ($delta) {
+ if ($d === '+') {
+ return "
+";
+ } elseif ($d === '-') {
+ return "
-";
+ } elseif ($d === ' ') {
+ if ($delta !== '') {
+ return 'A';
+ } else {
+ return ' ';
+ }
+ }
+ }, $diff_array);
+ // modify the line with the new indicator letters
+ $line = sprintf('%-35s|%3d %s%s', $filename, $count, implode('', $indicators), $delta);
+ }
+ }
+
+ // rejoin the modified lines into a string
+ $output = implode("\n", $lines);
+ $results = $output;
+
+ // remove script tags (xss)
+ $results = preg_replace('##is', '', $results);
+ if(strlen($results) == 0) {
+ $results = "This command has no output.";
+ }
+ echo "
| Output of command:`".$initcommand."` |
|---|
$results |
";
+ }
+ }
+ ob_end_flush();
+} else {include('overview.php');}
+?>
+
+
+